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: 349558 $")
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 #ifdef HAVE_PRI
00075 #include "sig_pri.h"
00076 #endif
00077
00078 #if defined(HAVE_SS7)
00079 #include "sig_ss7.h"
00080 #endif
00081
00082 #ifdef HAVE_OPENR2
00083
00084 #define SIG_MFCR2_MAX_CHANNELS 672
00085 #include <openr2.h>
00086 #endif
00087
00088 #include "asterisk/lock.h"
00089 #include "asterisk/channel.h"
00090 #include "asterisk/config.h"
00091 #include "asterisk/module.h"
00092 #include "asterisk/pbx.h"
00093 #include "asterisk/file.h"
00094 #include "asterisk/ulaw.h"
00095 #include "asterisk/alaw.h"
00096 #include "asterisk/callerid.h"
00097 #include "asterisk/adsi.h"
00098 #include "asterisk/cli.h"
00099 #include "asterisk/cdr.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/features.h"
00102 #include "asterisk/musiconhold.h"
00103 #include "asterisk/say.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/app.h"
00106 #include "asterisk/dsp.h"
00107 #include "asterisk/astdb.h"
00108 #include "asterisk/manager.h"
00109 #include "asterisk/causes.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/utils.h"
00112 #include "asterisk/transcap.h"
00113 #include "asterisk/stringfields.h"
00114 #include "asterisk/abstract_jb.h"
00115 #include "asterisk/smdi.h"
00116 #include "asterisk/astobj.h"
00117 #include "asterisk/event.h"
00118 #include "asterisk/devicestate.h"
00119 #include "asterisk/paths.h"
00120 #include "asterisk/ccss.h"
00121 #include "asterisk/data.h"
00122
00123
00124
00125
00126
00127
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 #define SMDI_MD_WAIT_TIMEOUT 1500
00276
00277 static const char * const lbostr[] = {
00278 "0 db (CSU)/0-133 feet (DSX-1)",
00279 "133-266 feet (DSX-1)",
00280 "266-399 feet (DSX-1)",
00281 "399-533 feet (DSX-1)",
00282 "533-655 feet (DSX-1)",
00283 "-7.5db (CSU)",
00284 "-15db (CSU)",
00285 "-22.5db (CSU)"
00286 };
00287
00288
00289
00290 static struct ast_jb_conf default_jbconf =
00291 {
00292 .flags = 0,
00293 .max_size = 200,
00294 .resync_threshold = 1000,
00295 .impl = "fixed",
00296 .target_extra = 40,
00297 };
00298 static struct ast_jb_conf global_jbconf;
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 #define DEFAULT_CIDRINGS 1
00313
00314 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00315
00316
00317
00318 #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))
00319
00320 static const char tdesc[] = "DAHDI Telephony Driver"
00321 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00322 " w/"
00323 #if defined(HAVE_PRI)
00324 "PRI"
00325 #endif
00326 #if defined(HAVE_SS7)
00327 #if defined(HAVE_PRI)
00328 " & "
00329 #endif
00330 "SS7"
00331 #endif
00332 #if defined(HAVE_OPENR2)
00333 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00334 " & "
00335 #endif
00336 "MFC/R2"
00337 #endif
00338 #endif
00339 ;
00340
00341 static const char config[] = "chan_dahdi.conf";
00342
00343 #define SIG_EM DAHDI_SIG_EM
00344 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00345 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00346 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00347 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00348 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00349 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00350 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00351 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00352 #define SIG_FXSLS DAHDI_SIG_FXSLS
00353 #define SIG_FXSGS DAHDI_SIG_FXSGS
00354 #define SIG_FXSKS DAHDI_SIG_FXSKS
00355 #define SIG_FXOLS DAHDI_SIG_FXOLS
00356 #define SIG_FXOGS DAHDI_SIG_FXOGS
00357 #define SIG_FXOKS DAHDI_SIG_FXOKS
00358 #define SIG_PRI DAHDI_SIG_CLEAR
00359 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00360 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00361 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00362 #define SIG_MFCR2 DAHDI_SIG_CAS
00363 #define SIG_SF DAHDI_SIG_SF
00364 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00365 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00366 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00367 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00368 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00369
00370 #ifdef LOTS_OF_SPANS
00371 #define NUM_SPANS DAHDI_MAX_SPANS
00372 #else
00373 #define NUM_SPANS 32
00374 #endif
00375
00376 #define CHAN_PSEUDO -2
00377
00378 #define CALLPROGRESS_PROGRESS 1
00379 #define CALLPROGRESS_FAX_OUTGOING 2
00380 #define CALLPROGRESS_FAX_INCOMING 4
00381 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00382
00383 #define NUM_CADENCE_MAX 25
00384 static int num_cadence = 4;
00385 static int user_has_defined_cadences = 0;
00386
00387 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00388 { { 125, 125, 2000, 4000 } },
00389 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00390 { { 125, 125, 125, 125, 125, 4000 } },
00391 { { 1000, 500, 2500, 5000 } },
00392 };
00393
00394
00395
00396
00397
00398 static int cidrings[NUM_CADENCE_MAX] = {
00399 2,
00400 4,
00401 3,
00402 2,
00403 };
00404
00405
00406 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00407
00408 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00409 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00410
00411 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00412 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00413
00414 static char defaultcic[64] = "";
00415 static char defaultozz[64] = "";
00416
00417
00418 static char mwimonitornotify[PATH_MAX] = "";
00419 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00420 static int mwisend_rpas = 0;
00421 #endif
00422
00423 static char progzone[10] = "";
00424
00425 static int usedistinctiveringdetection = 0;
00426 static int distinctiveringaftercid = 0;
00427
00428 static int numbufs = 4;
00429
00430 static int mwilevel = 512;
00431 static int dtmfcid_level = 256;
00432
00433 #define REPORT_CHANNEL_ALARMS 1
00434 #define REPORT_SPAN_ALARMS 2
00435 static int report_alarms = REPORT_CHANNEL_ALARMS;
00436
00437 #ifdef HAVE_PRI
00438 static int pridebugfd = -1;
00439 static char pridebugfilename[1024] = "";
00440 #endif
00441
00442
00443 static int firstdigittimeout = 16000;
00444
00445
00446 static int gendigittimeout = 8000;
00447
00448
00449 static int matchdigittimeout = 3000;
00450
00451
00452 AST_MUTEX_DEFINE_STATIC(iflock);
00453
00454
00455 static int ifcount = 0;
00456
00457 #ifdef HAVE_PRI
00458 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00459 #endif
00460
00461
00462
00463 AST_MUTEX_DEFINE_STATIC(monlock);
00464
00465
00466
00467 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00468 static ast_cond_t ss_thread_complete;
00469 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00470 AST_MUTEX_DEFINE_STATIC(restart_lock);
00471 static int ss_thread_count = 0;
00472 static int num_restart_pending = 0;
00473
00474 static int restart_monitor(void);
00475
00476 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);
00477
00478 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00479
00480 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00481 {
00482
00483
00484
00485
00486 }
00487
00488
00489 static inline int dahdi_get_event(int fd)
00490 {
00491 int j;
00492 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00493 return -1;
00494 return j;
00495 }
00496
00497
00498 static inline int dahdi_wait_event(int fd)
00499 {
00500 int i, j = 0;
00501 i = DAHDI_IOMUX_SIGEVENT;
00502 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00503 return -1;
00504 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00505 return -1;
00506 return j;
00507 }
00508
00509
00510 #define READ_SIZE 160
00511
00512 #define MASK_AVAIL (1 << 0)
00513 #define MASK_INUSE (1 << 1)
00514
00515 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00516 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00517 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00518 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00519 #define MIN_MS_SINCE_FLASH ((2000) )
00520 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00521
00522 struct dahdi_pvt;
00523
00524
00525
00526
00527
00528 static int ringt_base = DEFAULT_RINGT;
00529
00530 #if defined(HAVE_SS7)
00531
00532 struct dahdi_ss7 {
00533 struct sig_ss7_linkset ss7;
00534 };
00535
00536 static struct dahdi_ss7 linksets[NUM_SPANS];
00537
00538 static int cur_ss7type = -1;
00539 static int cur_linkset = -1;
00540 static int cur_pointcode = -1;
00541 static int cur_cicbeginswith = -1;
00542 static int cur_adjpointcode = -1;
00543 static int cur_networkindicator = -1;
00544 static int cur_defaultdpc = -1;
00545 #endif
00546
00547 #ifdef HAVE_OPENR2
00548 struct dahdi_mfcr2 {
00549 pthread_t r2master;
00550 openr2_context_t *protocol_context;
00551 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00552 int numchans;
00553 int monitored_count;
00554 };
00555
00556 struct dahdi_mfcr2_conf {
00557 openr2_variant_t variant;
00558 int mfback_timeout;
00559 int metering_pulse_timeout;
00560 int max_ani;
00561 int max_dnis;
00562 signed int get_ani_first:2;
00563 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00564 signed int skip_category_request:2;
00565 #endif
00566 unsigned int call_files:1;
00567 unsigned int allow_collect_calls:1;
00568 unsigned int charge_calls:1;
00569 unsigned int accept_on_offer:1;
00570 unsigned int forced_release:1;
00571 unsigned int double_answer:1;
00572 signed int immediate_accept:2;
00573 char logdir[OR2_MAX_PATH];
00574 char r2proto_file[OR2_MAX_PATH];
00575 openr2_log_level_t loglevel;
00576 openr2_calling_party_category_t category;
00577 };
00578
00579
00580 static struct dahdi_mfcr2 **r2links;
00581
00582 static int r2links_count = 0;
00583
00584 #endif
00585
00586 #ifdef HAVE_PRI
00587
00588 struct dahdi_pri {
00589 int dchannels[SIG_PRI_NUM_DCHANS];
00590 int mastertrunkgroup;
00591 int prilogicalspan;
00592 struct sig_pri_span pri;
00593 };
00594
00595 static struct dahdi_pri pris[NUM_SPANS];
00596
00597 #if defined(HAVE_PRI_CCSS)
00598
00599 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00600 #endif
00601
00602 #else
00603
00604 struct dahdi_pri;
00605 #endif
00606
00607 #define SUB_REAL 0
00608 #define SUB_CALLWAIT 1
00609 #define SUB_THREEWAY 2
00610
00611
00612 #define POLARITY_IDLE 0
00613 #define POLARITY_REV 1
00614
00615
00616 struct distRingData {
00617 int ring[3];
00618 int range;
00619 };
00620 struct ringContextData {
00621 char contextData[AST_MAX_CONTEXT];
00622 };
00623 struct dahdi_distRings {
00624 struct distRingData ringnum[3];
00625 struct ringContextData ringContext[3];
00626 };
00627
00628 static const char * const subnames[] = {
00629 "Real",
00630 "Callwait",
00631 "Threeway"
00632 };
00633
00634 struct dahdi_subchannel {
00635 int dfd;
00636 struct ast_channel *owner;
00637 int chan;
00638 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00639 struct ast_frame f;
00640 unsigned int needringing:1;
00641 unsigned int needbusy:1;
00642 unsigned int needcongestion:1;
00643 unsigned int needanswer:1;
00644 unsigned int needflash:1;
00645 unsigned int needhold:1;
00646 unsigned int needunhold:1;
00647 unsigned int linear:1;
00648 unsigned int inthreeway:1;
00649 struct dahdi_confinfo curconf;
00650 };
00651
00652 #define CONF_USER_REAL (1 << 0)
00653 #define CONF_USER_THIRDCALL (1 << 1)
00654
00655 #define MAX_SLAVES 4
00656
00657
00658
00659
00660 typedef enum {
00661 MWI_SEND_NULL = 0,
00662 MWI_SEND_SA,
00663 MWI_SEND_SA_WAIT,
00664 MWI_SEND_PAUSE,
00665 MWI_SEND_SPILL,
00666 MWI_SEND_CLEANUP,
00667 MWI_SEND_DONE,
00668 } mwisend_states;
00669
00670 struct mwisend_info {
00671 struct timeval pause;
00672 mwisend_states mwisend_current;
00673 };
00674
00675
00676 enum DAHDI_IFLIST {
00677 DAHDI_IFLIST_NONE,
00678 DAHDI_IFLIST_MAIN,
00679 #if defined(HAVE_PRI)
00680 DAHDI_IFLIST_NO_B_CHAN,
00681 #endif
00682 };
00683
00684 struct dahdi_pvt {
00685 ast_mutex_t lock;
00686 struct callerid_state *cs;
00687 struct ast_channel *owner;
00688
00689
00690 struct dahdi_subchannel sub_unused;
00691 struct dahdi_subchannel subs[3];
00692 struct dahdi_confinfo saveconf;
00693
00694 struct dahdi_pvt *slaves[MAX_SLAVES];
00695 struct dahdi_pvt *master;
00696 int inconference;
00697
00698 int bufsize;
00699 int buf_no;
00700 int buf_policy;
00701 int faxbuf_no;
00702 int faxbuf_policy;
00703 int sig;
00704
00705
00706
00707
00708 int radio;
00709 int outsigmod;
00710 int oprmode;
00711 struct dahdi_pvt *oprpeer;
00712
00713 float cid_rxgain;
00714
00715 float rxgain;
00716
00717 float txgain;
00718
00719 float txdrc;
00720 float rxdrc;
00721
00722 int tonezone;
00723 enum DAHDI_IFLIST which_iflist;
00724 struct dahdi_pvt *next;
00725 struct dahdi_pvt *prev;
00726
00727
00728
00729
00730
00731
00732
00733 unsigned int adsi:1;
00734
00735
00736
00737
00738
00739 unsigned int answeronpolarityswitch:1;
00740
00741
00742
00743
00744
00745 unsigned int busydetect:1;
00746
00747
00748
00749
00750
00751 unsigned int callreturn:1;
00752
00753
00754
00755
00756
00757
00758 unsigned int callwaiting:1;
00759
00760
00761
00762
00763 unsigned int callwaitingcallerid:1;
00764
00765
00766
00767
00768
00769
00770 unsigned int cancallforward:1;
00771
00772
00773
00774
00775 unsigned int canpark:1;
00776
00777 unsigned int confirmanswer:1;
00778
00779
00780
00781
00782 unsigned int destroy:1;
00783 unsigned int didtdd:1;
00784
00785 unsigned int dialednone:1;
00786
00787
00788
00789
00790 unsigned int dialing:1;
00791
00792 unsigned int digital:1;
00793
00794 unsigned int dnd:1;
00795
00796 unsigned int echobreak:1;
00797
00798
00799
00800
00801
00802 unsigned int echocanbridged:1;
00803
00804 unsigned int echocanon:1;
00805
00806 unsigned int faxhandled:1;
00807
00808 unsigned int usefaxbuffers:1;
00809
00810 unsigned int bufferoverrideinuse:1;
00811
00812 unsigned int firstradio:1;
00813
00814
00815
00816
00817 unsigned int hanguponpolarityswitch:1;
00818
00819 unsigned int hardwaredtmf:1;
00820
00821
00822
00823
00824
00825
00826 unsigned int hidecallerid:1;
00827
00828
00829
00830
00831
00832 unsigned int hidecalleridname:1;
00833
00834 unsigned int ignoredtmf:1;
00835
00836
00837
00838
00839
00840 unsigned int immediate:1;
00841
00842 unsigned int inalarm:1;
00843
00844 unsigned int mate:1;
00845
00846 unsigned int outgoing:1;
00847
00848
00849
00850
00851
00852
00853 unsigned int permcallwaiting:1;
00854
00855
00856
00857
00858 unsigned int permhidecallerid:1;
00859
00860
00861
00862
00863 unsigned int priindication_oob:1;
00864
00865
00866
00867
00868 unsigned int priexclusive:1;
00869
00870
00871
00872
00873 unsigned int pulse:1;
00874
00875 unsigned int pulsedial:1;
00876 unsigned int restartpending:1;
00877
00878
00879
00880
00881
00882 unsigned int restrictcid:1;
00883
00884
00885
00886
00887 unsigned int threewaycalling:1;
00888
00889
00890
00891
00892
00893
00894
00895
00896 unsigned int transfer:1;
00897
00898
00899
00900
00901
00902
00903
00904 unsigned int use_callerid:1;
00905
00906
00907
00908
00909
00910
00911 unsigned int use_callingpres:1;
00912
00913
00914
00915
00916
00917 unsigned int usedistinctiveringdetection:1;
00918
00919
00920
00921
00922 unsigned int dahditrcallerid:1;
00923
00924
00925
00926
00927 unsigned int transfertobusy:1;
00928
00929
00930
00931
00932 unsigned int mwimonitor_neon:1;
00933
00934
00935
00936
00937 unsigned int mwimonitor_fsk:1;
00938
00939
00940
00941
00942
00943 unsigned int mwimonitor_rpas:1;
00944
00945 unsigned int mwimonitoractive:1;
00946
00947 unsigned int mwisendactive:1;
00948
00949
00950
00951
00952 unsigned int inservice:1;
00953
00954
00955
00956
00957 unsigned int locallyblocked:1;
00958
00959
00960
00961
00962 unsigned int remotelyblocked:1;
00963
00964
00965
00966
00967 unsigned int manages_span_alarms:1;
00968
00969 #if defined(HAVE_PRI)
00970 struct sig_pri_span *pri;
00971 int logicalspan;
00972 #endif
00973
00974
00975
00976
00977 unsigned int use_smdi:1;
00978 struct mwisend_info mwisend_data;
00979
00980 struct ast_smdi_interface *smdi_iface;
00981
00982
00983 struct dahdi_distRings drings;
00984
00985
00986
00987
00988
00989 char context[AST_MAX_CONTEXT];
00990
00991
00992
00993 char defcontext[AST_MAX_CONTEXT];
00994
00995 char exten[AST_MAX_EXTENSION];
00996
00997
00998
00999
01000 char language[MAX_LANGUAGE];
01001
01002
01003
01004
01005 char mohinterpret[MAX_MUSICCLASS];
01006
01007
01008
01009
01010 char mohsuggest[MAX_MUSICCLASS];
01011 char parkinglot[AST_MAX_EXTENSION];
01012 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01013
01014 char cid_ani[AST_MAX_EXTENSION];
01015 #endif
01016
01017 int cid_ani2;
01018
01019 char cid_num[AST_MAX_EXTENSION];
01020
01021
01022
01023
01024 char cid_tag[AST_MAX_EXTENSION];
01025
01026 int cid_ton;
01027
01028 char cid_name[AST_MAX_EXTENSION];
01029
01030 char cid_subaddr[AST_MAX_EXTENSION];
01031 char *origcid_num;
01032 char *origcid_name;
01033
01034 char callwait_num[AST_MAX_EXTENSION];
01035
01036 char callwait_name[AST_MAX_EXTENSION];
01037
01038 char rdnis[AST_MAX_EXTENSION];
01039
01040 char dnid[AST_MAX_EXTENSION];
01041
01042
01043
01044
01045 ast_group_t group;
01046
01047 int law_default;
01048
01049 int law;
01050 int confno;
01051 int confusers;
01052 int propconfno;
01053
01054
01055
01056
01057 ast_group_t callgroup;
01058
01059
01060
01061
01062 ast_group_t pickupgroup;
01063
01064
01065
01066
01067 struct ast_variable *vars;
01068 int channel;
01069 int span;
01070 time_t guardtime;
01071 int cid_signalling;
01072 int cid_start;
01073 int dtmfcid_holdoff_state;
01074 struct timeval dtmfcid_delay;
01075 int callingpres;
01076 int callwaitingrepeat;
01077 int cidcwexpire;
01078 int cid_suppress_expire;
01079
01080 unsigned char *cidspill;
01081
01082 int cidpos;
01083
01084 int cidlen;
01085
01086 int ringt;
01087
01088
01089
01090
01091 int ringt_base;
01092
01093
01094
01095
01096
01097
01098 int stripmsd;
01099
01100
01101
01102
01103
01104
01105 int callwaitcas;
01106
01107 int callwaitrings;
01108
01109 struct {
01110 struct dahdi_echocanparams head;
01111 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01112 } echocancel;
01113
01114
01115
01116
01117 int echotraining;
01118
01119 char echorest[20];
01120
01121
01122
01123
01124 int busycount;
01125
01126
01127
01128
01129 int busycompare;
01130
01131
01132
01133
01134 int busytonelength;
01135
01136
01137
01138
01139 int busyquietlength;
01140
01141
01142
01143
01144 int busyfuzziness;
01145
01146
01147
01148
01149 int silencethreshold;
01150
01151
01152
01153
01154 int callprogress;
01155
01156
01157
01158
01159 int waitfordialtone;
01160 struct timeval waitingfordt;
01161 struct timeval flashtime;
01162
01163 struct ast_dsp *dsp;
01164
01165 struct dahdi_dialoperation dop;
01166 int whichwink;
01167
01168 char finaldial[64];
01169 char accountcode[AST_MAX_ACCOUNT_CODE];
01170 int amaflags;
01171 struct tdd_state *tdd;
01172
01173 char call_forward[AST_MAX_EXTENSION];
01174
01175
01176
01177
01178 char mailbox[AST_MAX_EXTENSION];
01179
01180 struct ast_event_sub *mwi_event_sub;
01181
01182 char dialdest[256];
01183 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01184 struct dahdi_vmwi_info mwisend_setting;
01185 unsigned int mwisend_fsk: 1;
01186 unsigned int mwisend_rpas:1;
01187 #endif
01188 int distinctivering;
01189 int dtmfrelax;
01190
01191 int fake_event;
01192
01193
01194
01195
01196 int polarityonanswerdelay;
01197
01198 struct timeval polaritydelaytv;
01199
01200
01201
01202
01203 int sendcalleridafter;
01204
01205 int polarity;
01206
01207 int dsp_features;
01208 #if defined(HAVE_SS7)
01209
01210 struct sig_ss7_linkset *ss7;
01211 #endif
01212 #ifdef HAVE_OPENR2
01213 struct dahdi_mfcr2 *mfcr2;
01214 openr2_chan_t *r2chan;
01215 openr2_calling_party_category_t mfcr2_recvd_category;
01216 openr2_calling_party_category_t mfcr2_category;
01217 int mfcr2_dnis_index;
01218 int mfcr2_ani_index;
01219 int mfcr2call:1;
01220 int mfcr2_answer_pending:1;
01221 int mfcr2_charge_calls:1;
01222 int mfcr2_allow_collect_calls:1;
01223 int mfcr2_forced_release:1;
01224 int mfcr2_dnis_matched:1;
01225 int mfcr2_call_accepted:1;
01226 int mfcr2_progress:1;
01227 int mfcr2_accept_on_offer:1;
01228 #endif
01229
01230 char begindigit;
01231
01232 int muting;
01233 void *sig_pvt;
01234 struct ast_cc_config_params *cc_params;
01235
01236
01237
01238
01239
01240
01241 char dialstring[AST_CHANNEL_NAME];
01242 };
01243
01244 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01245 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01246 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01247 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01248 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01249 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01250 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01298 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01299 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01300 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01301 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01302 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01303 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01304 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01305 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01306 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01307 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01308 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01309 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01310 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01311 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01312
01313 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01314
01315 static struct dahdi_pvt *iflist = NULL;
01316 static struct dahdi_pvt *ifend = NULL;
01317
01318 #if defined(HAVE_PRI)
01319 static struct dahdi_parms_pseudo {
01320 int buf_no;
01321 int buf_policy;
01322 int faxbuf_no;
01323 int faxbuf_policy;
01324 } dahdi_pseudo_parms;
01325 #endif
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337 struct dahdi_chan_conf {
01338 struct dahdi_pvt chan;
01339 #ifdef HAVE_PRI
01340 struct dahdi_pri pri;
01341 #endif
01342
01343 #if defined(HAVE_SS7)
01344 struct dahdi_ss7 ss7;
01345 #endif
01346
01347 #ifdef HAVE_OPENR2
01348 struct dahdi_mfcr2_conf mfcr2;
01349 #endif
01350 struct dahdi_params timing;
01351 int is_sig_auto;
01352
01353 int ignore_failed_channels;
01354
01355
01356
01357
01358
01359 char smdi_port[SMDI_MAX_FILENAME_LEN];
01360 };
01361
01362
01363 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01364 {
01365
01366
01367
01368 struct dahdi_chan_conf conf = {
01369 #ifdef HAVE_PRI
01370 .pri.pri = {
01371 .nsf = PRI_NSF_NONE,
01372 .switchtype = PRI_SWITCH_NI2,
01373 .dialplan = PRI_UNKNOWN + 1,
01374 .localdialplan = PRI_NATIONAL_ISDN + 1,
01375 .nodetype = PRI_CPE,
01376 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01377
01378 #if defined(HAVE_PRI_CCSS)
01379 .cc_ptmp_recall_mode = 1,
01380 .cc_qsig_signaling_link_req = 1,
01381 .cc_qsig_signaling_link_rsp = 1,
01382 #endif
01383
01384 .minunused = 2,
01385 .idleext = "",
01386 .idledial = "",
01387 .internationalprefix = "",
01388 .nationalprefix = "",
01389 .localprefix = "",
01390 .privateprefix = "",
01391 .unknownprefix = "",
01392 .resetinterval = -1,
01393 },
01394 #endif
01395 #if defined(HAVE_SS7)
01396 .ss7.ss7 = {
01397 .called_nai = SS7_NAI_NATIONAL,
01398 .calling_nai = SS7_NAI_NATIONAL,
01399 .internationalprefix = "",
01400 .nationalprefix = "",
01401 .subscriberprefix = "",
01402 .unknownprefix = ""
01403 },
01404 #endif
01405 #ifdef HAVE_OPENR2
01406 .mfcr2 = {
01407 .variant = OR2_VAR_ITU,
01408 .mfback_timeout = -1,
01409 .metering_pulse_timeout = -1,
01410 .max_ani = 10,
01411 .max_dnis = 4,
01412 .get_ani_first = -1,
01413 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01414 .skip_category_request = -1,
01415 #endif
01416 .call_files = 0,
01417 .allow_collect_calls = 0,
01418 .charge_calls = 1,
01419 .accept_on_offer = 1,
01420 .forced_release = 0,
01421 .double_answer = 0,
01422 .immediate_accept = -1,
01423 .logdir = "",
01424 .r2proto_file = "",
01425 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01426 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01427 },
01428 #endif
01429 .chan = {
01430 .context = "default",
01431 .cid_num = "",
01432 .cid_name = "",
01433 .cid_tag = "",
01434 .mohinterpret = "default",
01435 .mohsuggest = "",
01436 .parkinglot = "",
01437 .transfertobusy = 1,
01438
01439 .cid_signalling = CID_SIG_BELL,
01440 .cid_start = CID_START_RING,
01441 .dahditrcallerid = 0,
01442 .use_callerid = 1,
01443 .sig = -1,
01444 .outsigmod = -1,
01445
01446 .cid_rxgain = +5.0,
01447
01448 .tonezone = -1,
01449
01450 .echocancel.head.tap_length = 1,
01451
01452 .busycount = 3,
01453 .busycompare = 0,
01454 .busytonelength = 0,
01455 .busyquietlength = 0,
01456 .busyfuzziness = 0,
01457 .silencethreshold = 0,
01458
01459 .accountcode = "",
01460
01461 .mailbox = "",
01462
01463 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01464 .mwisend_fsk = 1,
01465 #endif
01466 .polarityonanswerdelay = 600,
01467
01468 .sendcalleridafter = DEFAULT_CIDRINGS,
01469
01470 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01471 .buf_no = numbufs,
01472 .usefaxbuffers = 0,
01473 .cc_params = ast_cc_config_params_init(),
01474 },
01475 .timing = {
01476 .prewinktime = -1,
01477 .preflashtime = -1,
01478 .winktime = -1,
01479 .flashtime = -1,
01480 .starttime = -1,
01481 .rxwinktime = -1,
01482 .rxflashtime = -1,
01483 .debouncetime = -1
01484 },
01485 .is_sig_auto = 1,
01486 .smdi_port = "/dev/ttyS0",
01487 };
01488
01489 return conf;
01490 }
01491
01492
01493 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01494 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01495 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01496 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01497 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01498 static int dahdi_hangup(struct ast_channel *ast);
01499 static int dahdi_answer(struct ast_channel *ast);
01500 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01501 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01502 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01503 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01504 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01505 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01506 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01507 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01508 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01509 static int dahdi_devicestate(void *data);
01510 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01511
01512 static const struct ast_channel_tech dahdi_tech = {
01513 .type = "DAHDI",
01514 .description = tdesc,
01515 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01516 .requester = dahdi_request,
01517 .send_digit_begin = dahdi_digit_begin,
01518 .send_digit_end = dahdi_digit_end,
01519 .send_text = dahdi_sendtext,
01520 .call = dahdi_call,
01521 .hangup = dahdi_hangup,
01522 .answer = dahdi_answer,
01523 .read = dahdi_read,
01524 .write = dahdi_write,
01525 .bridge = dahdi_bridge,
01526 .exception = dahdi_exception,
01527 .indicate = dahdi_indicate,
01528 .fixup = dahdi_fixup,
01529 .setoption = dahdi_setoption,
01530 .queryoption = dahdi_queryoption,
01531 .func_channel_read = dahdi_func_read,
01532 .func_channel_write = dahdi_func_write,
01533 .devicestate = dahdi_devicestate,
01534 .cc_callback = dahdi_cc_callback,
01535 };
01536
01537 #define GET_CHANNEL(p) ((p)->channel)
01538
01539 #define SIG_PRI_LIB_HANDLE_CASES \
01540 SIG_PRI: \
01541 case SIG_BRI: \
01542 case SIG_BRI_PTMP
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553 static inline int dahdi_sig_pri_lib_handles(int signaling)
01554 {
01555 int handles;
01556
01557 switch (signaling) {
01558 case SIG_PRI_LIB_HANDLE_CASES:
01559 handles = 1;
01560 break;
01561 default:
01562 handles = 0;
01563 break;
01564 }
01565
01566 return handles;
01567 }
01568
01569 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01570 {
01571 switch (sig) {
01572 case SIG_FXOLS:
01573 return ANALOG_SIG_FXOLS;
01574 case SIG_FXOGS:
01575 return ANALOG_SIG_FXOGS;
01576 case SIG_FXOKS:
01577 return ANALOG_SIG_FXOKS;
01578 case SIG_FXSLS:
01579 return ANALOG_SIG_FXSLS;
01580 case SIG_FXSGS:
01581 return ANALOG_SIG_FXSGS;
01582 case SIG_FXSKS:
01583 return ANALOG_SIG_FXSKS;
01584 case SIG_EMWINK:
01585 return ANALOG_SIG_EMWINK;
01586 case SIG_EM:
01587 return ANALOG_SIG_EM;
01588 case SIG_EM_E1:
01589 return ANALOG_SIG_EM_E1;
01590 case SIG_FEATD:
01591 return ANALOG_SIG_FEATD;
01592 case SIG_FEATDMF:
01593 return ANALOG_SIG_FEATDMF;
01594 case SIG_E911:
01595 return SIG_E911;
01596 case SIG_FGC_CAMA:
01597 return ANALOG_SIG_FGC_CAMA;
01598 case SIG_FGC_CAMAMF:
01599 return ANALOG_SIG_FGC_CAMAMF;
01600 case SIG_FEATB:
01601 return ANALOG_SIG_FEATB;
01602 case SIG_SFWINK:
01603 return ANALOG_SIG_SFWINK;
01604 case SIG_SF:
01605 return ANALOG_SIG_SF;
01606 case SIG_SF_FEATD:
01607 return ANALOG_SIG_SF_FEATD;
01608 case SIG_SF_FEATDMF:
01609 return ANALOG_SIG_SF_FEATDMF;
01610 case SIG_FEATDMF_TA:
01611 return ANALOG_SIG_FEATDMF_TA;
01612 case SIG_SF_FEATB:
01613 return ANALOG_SIG_FEATB;
01614 default:
01615 return -1;
01616 }
01617 }
01618
01619
01620 static int analog_tone_to_dahditone(enum analog_tone tone)
01621 {
01622 switch (tone) {
01623 case ANALOG_TONE_RINGTONE:
01624 return DAHDI_TONE_RINGTONE;
01625 case ANALOG_TONE_STUTTER:
01626 return DAHDI_TONE_STUTTER;
01627 case ANALOG_TONE_CONGESTION:
01628 return DAHDI_TONE_CONGESTION;
01629 case ANALOG_TONE_DIALTONE:
01630 return DAHDI_TONE_DIALTONE;
01631 case ANALOG_TONE_DIALRECALL:
01632 return DAHDI_TONE_DIALRECALL;
01633 case ANALOG_TONE_INFO:
01634 return DAHDI_TONE_INFO;
01635 default:
01636 return -1;
01637 }
01638 }
01639
01640 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01641 {
01642 int index;
01643
01644 switch (analogsub) {
01645 case ANALOG_SUB_REAL:
01646 index = SUB_REAL;
01647 break;
01648 case ANALOG_SUB_CALLWAIT:
01649 index = SUB_CALLWAIT;
01650 break;
01651 case ANALOG_SUB_THREEWAY:
01652 index = SUB_THREEWAY;
01653 break;
01654 default:
01655 ast_log(LOG_ERROR, "Unidentified sub!\n");
01656 index = SUB_REAL;
01657 }
01658
01659 return index;
01660 }
01661
01662 static enum analog_event dahdievent_to_analogevent(int event);
01663 static int bump_gains(struct dahdi_pvt *p);
01664 static int dahdi_setlinear(int dfd, int linear);
01665
01666 static int my_start_cid_detect(void *pvt, int cid_signalling)
01667 {
01668 struct dahdi_pvt *p = pvt;
01669 int index = SUB_REAL;
01670 p->cs = callerid_new(cid_signalling);
01671 if (!p->cs) {
01672 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01673 return -1;
01674 }
01675 bump_gains(p);
01676 dahdi_setlinear(p->subs[index].dfd, 0);
01677
01678 return 0;
01679 }
01680
01681 static int my_stop_cid_detect(void *pvt)
01682 {
01683 struct dahdi_pvt *p = pvt;
01684 int index = SUB_REAL;
01685 if (p->cs)
01686 callerid_free(p->cs);
01687 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01688 return 0;
01689 }
01690
01691 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01692 {
01693 struct dahdi_pvt *p = pvt;
01694 struct analog_pvt *analog_p = p->sig_pvt;
01695 struct pollfd poller;
01696 char *name, *num;
01697 int index = SUB_REAL;
01698 int res;
01699 unsigned char buf[256];
01700 int flags;
01701
01702 poller.fd = p->subs[SUB_REAL].dfd;
01703 poller.events = POLLPRI | POLLIN;
01704 poller.revents = 0;
01705
01706 res = poll(&poller, 1, timeout);
01707
01708 if (poller.revents & POLLPRI) {
01709 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01710 return 1;
01711 }
01712
01713 if (poller.revents & POLLIN) {
01714
01715
01716
01717
01718
01719 res = read(p->subs[index].dfd, buf, sizeof(buf));
01720 if (res < 0) {
01721 if (errno != ELAST) {
01722 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01723 callerid_free(p->cs);
01724 return -1;
01725 }
01726 }
01727
01728 if (analog_p->ringt > 0) {
01729 if (!(--analog_p->ringt)) {
01730
01731 return -1;
01732 }
01733 }
01734
01735 if (p->cid_signalling == CID_SIG_V23_JP) {
01736 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01737 } else {
01738 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01739 }
01740 if (res < 0) {
01741
01742
01743
01744
01745 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01746 return -1;
01747 }
01748
01749 if (res == 1) {
01750 callerid_get(p->cs, &name, &num, &flags);
01751 if (name)
01752 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01753 if (num)
01754 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01755
01756 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01757 return 0;
01758 }
01759 }
01760
01761 *ev = ANALOG_EVENT_NONE;
01762 return 2;
01763 }
01764
01765 static const char *event2str(int event);
01766 static int restore_gains(struct dahdi_pvt *p);
01767
01768 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01769 {
01770 unsigned char buf[256];
01771 int distMatches;
01772 int curRingData[RING_PATTERNS];
01773 int receivedRingT;
01774 int counter1;
01775 int counter;
01776 int i;
01777 int res;
01778 int checkaftercid = 0;
01779
01780 struct dahdi_pvt *p = pvt;
01781 struct analog_pvt *analog_p = p->sig_pvt;
01782
01783 if (ringdata == NULL) {
01784 ringdata = curRingData;
01785 } else {
01786 checkaftercid = 1;
01787 }
01788
01789
01790
01791 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01792
01793 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01794 ringdata[receivedRingT] = 0;
01795 receivedRingT = 0;
01796 if (checkaftercid && distinctiveringaftercid)
01797 ast_verb(3, "Detecting post-CID distinctive ring\n");
01798
01799 else if (strcmp(p->context,p->defcontext) != 0) {
01800 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01801 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01802 }
01803
01804 for (;;) {
01805 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01806 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01807 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01808 ast_hangup(chan);
01809 return 1;
01810 }
01811 if (i & DAHDI_IOMUX_SIGEVENT) {
01812 res = dahdi_get_event(p->subs[idx].dfd);
01813 if (res == DAHDI_EVENT_NOALARM) {
01814 p->inalarm = 0;
01815 analog_p->inalarm = 0;
01816 }
01817 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01818 res = 0;
01819
01820
01821 ringdata[receivedRingT] = analog_p->ringt;
01822
01823 if (analog_p->ringt < analog_p->ringt_base/2)
01824 break;
01825
01826
01827 if (++receivedRingT == RING_PATTERNS)
01828 break;
01829 } else if (i & DAHDI_IOMUX_READ) {
01830 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01831 if (res < 0) {
01832 if (errno != ELAST) {
01833 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01834 ast_hangup(chan);
01835 return 1;
01836 }
01837 break;
01838 }
01839 if (analog_p->ringt > 0) {
01840 if (!(--analog_p->ringt)) {
01841 res = -1;
01842 break;
01843 }
01844 }
01845 }
01846 }
01847 }
01848 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01849
01850 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01851 for (counter = 0; counter < 3; counter++) {
01852
01853 distMatches = 0;
01854
01855 ast_verb(3, "Checking %d,%d,%d\n",
01856 p->drings.ringnum[counter].ring[0],
01857 p->drings.ringnum[counter].ring[1],
01858 p->drings.ringnum[counter].ring[2]);
01859 for (counter1 = 0; counter1 < 3; counter1++) {
01860 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01861 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01862 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01863 ringdata[counter1]);
01864 distMatches++;
01865 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01866 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01867 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01868 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01869 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01870 distMatches++;
01871 }
01872 }
01873
01874 if (distMatches == 3) {
01875
01876 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01877 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01878 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01879 break;
01880 }
01881 }
01882 }
01883
01884 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01885 restore_gains(p);
01886
01887 return 0;
01888 }
01889
01890 static int my_stop_callwait(void *pvt)
01891 {
01892 struct dahdi_pvt *p = pvt;
01893 p->callwaitingrepeat = 0;
01894 p->cidcwexpire = 0;
01895 p->cid_suppress_expire = 0;
01896
01897 return 0;
01898 }
01899
01900 static int send_callerid(struct dahdi_pvt *p);
01901 static int save_conference(struct dahdi_pvt *p);
01902 static int restore_conference(struct dahdi_pvt *p);
01903
01904 static int my_callwait(void *pvt)
01905 {
01906 struct dahdi_pvt *p = pvt;
01907 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01908 if (p->cidspill) {
01909 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01910 ast_free(p->cidspill);
01911 }
01912
01913
01914
01915
01916
01917 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01918 return -1;
01919 save_conference(p);
01920
01921 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01922 if (!p->callwaitrings && p->callwaitingcallerid) {
01923 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01924 p->callwaitcas = 1;
01925 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01926 } else {
01927 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01928 p->callwaitcas = 0;
01929 p->cidlen = 2400 + READ_SIZE * 4;
01930 }
01931 p->cidpos = 0;
01932 send_callerid(p);
01933
01934 return 0;
01935 }
01936
01937 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01938 {
01939 struct dahdi_pvt *p = pvt;
01940
01941 ast_debug(2, "Starting cid spill\n");
01942
01943 if (p->cidspill) {
01944 ast_log(LOG_WARNING, "cidspill already exists??\n");
01945 ast_free(p->cidspill);
01946 }
01947
01948 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01949 if (cwcid == 0) {
01950 p->cidlen = ast_callerid_generate(p->cidspill,
01951 caller->id.name.str,
01952 caller->id.number.str,
01953 AST_LAW(p));
01954 } else {
01955 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01956 caller->id.name.str, caller->id.number.str);
01957 p->callwaitcas = 0;
01958 p->cidcwexpire = 0;
01959 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01960 caller->id.name.str,
01961 caller->id.number.str,
01962 AST_LAW(p));
01963 p->cidlen += READ_SIZE * 4;
01964 }
01965 p->cidpos = 0;
01966 p->cid_suppress_expire = 0;
01967 send_callerid(p);
01968 }
01969 return 0;
01970 }
01971
01972 static int my_dsp_reset_and_flush_digits(void *pvt)
01973 {
01974 struct dahdi_pvt *p = pvt;
01975 if (p->dsp)
01976 ast_dsp_digitreset(p->dsp);
01977
01978 return 0;
01979 }
01980
01981 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01982 {
01983 struct dahdi_pvt *p = pvt;
01984
01985 if (p->channel == CHAN_PSEUDO)
01986 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01987
01988 if (mode == ANALOG_DIGITMODE_DTMF) {
01989
01990 if (p->hardwaredtmf) {
01991 if (p->dsp) {
01992 ast_dsp_free(p->dsp);
01993 p->dsp = NULL;
01994 }
01995 return 0;
01996 }
01997
01998 if (!p->dsp) {
01999 p->dsp = ast_dsp_new();
02000 if (!p->dsp) {
02001 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02002 return -1;
02003 }
02004 }
02005
02006 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02007 } else if (mode == ANALOG_DIGITMODE_MF) {
02008 if (!p->dsp) {
02009 p->dsp = ast_dsp_new();
02010 if (!p->dsp) {
02011 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02012 return -1;
02013 }
02014 }
02015 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02016 }
02017 return 0;
02018 }
02019
02020 static int dahdi_wink(struct dahdi_pvt *p, int index);
02021
02022 static int my_wink(void *pvt, enum analog_sub sub)
02023 {
02024 struct dahdi_pvt *p = pvt;
02025 int index = analogsub_to_dahdisub(sub);
02026 if (index != SUB_REAL) {
02027 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02028 }
02029 return dahdi_wink(p, index);
02030 }
02031
02032 static void wakeup_sub(struct dahdi_pvt *p, int a);
02033
02034 static int reset_conf(struct dahdi_pvt *p);
02035
02036 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02037
02038 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02039 {
02040 struct ast_frame *f = *dest;
02041 struct dahdi_pvt *p = pvt;
02042 int idx = analogsub_to_dahdisub(analog_index);
02043
02044 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02045 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02046 f->subclass.integer, f->subclass.integer, ast->name);
02047
02048 if (f->subclass.integer == 'f') {
02049 if (f->frametype == AST_FRAME_DTMF_END) {
02050
02051 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02052
02053 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02054 struct dahdi_bufferinfo bi = {
02055 .txbufpolicy = p->faxbuf_policy,
02056 .bufsize = p->bufsize,
02057 .numbufs = p->faxbuf_no
02058 };
02059 int res;
02060
02061 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02062 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02063 } else {
02064 p->bufferoverrideinuse = 1;
02065 }
02066 }
02067 p->faxhandled = 1;
02068 if (p->dsp) {
02069 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02070 ast_dsp_set_features(p->dsp, p->dsp_features);
02071 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02072 }
02073 if (strcmp(ast->exten, "fax")) {
02074 const char *target_context = S_OR(ast->macrocontext, ast->context);
02075
02076
02077
02078
02079
02080 ast_mutex_unlock(&p->lock);
02081 ast_channel_unlock(ast);
02082 if (ast_exists_extension(ast, target_context, "fax", 1,
02083 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02084 ast_channel_lock(ast);
02085 ast_mutex_lock(&p->lock);
02086 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02087
02088 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02089 if (ast_async_goto(ast, target_context, "fax", 1))
02090 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02091 } else {
02092 ast_channel_lock(ast);
02093 ast_mutex_lock(&p->lock);
02094 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02095 }
02096 } else {
02097 ast_debug(1, "Already in a fax extension, not redirecting\n");
02098 }
02099 } else {
02100 ast_debug(1, "Fax already handled\n");
02101 }
02102 dahdi_confmute(p, 0);
02103 }
02104 p->subs[idx].f.frametype = AST_FRAME_NULL;
02105 p->subs[idx].f.subclass.integer = 0;
02106 *dest = &p->subs[idx].f;
02107 }
02108 }
02109
02110 static void my_lock_private(void *pvt)
02111 {
02112 struct dahdi_pvt *p = pvt;
02113 ast_mutex_lock(&p->lock);
02114 }
02115
02116 static void my_unlock_private(void *pvt)
02117 {
02118 struct dahdi_pvt *p = pvt;
02119 ast_mutex_unlock(&p->lock);
02120 }
02121
02122 static void my_deadlock_avoidance_private(void *pvt)
02123 {
02124 struct dahdi_pvt *p = pvt;
02125
02126 DEADLOCK_AVOIDANCE(&p->lock);
02127 }
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02140 {
02141 char ch_name[20];
02142
02143 if (p->channel < CHAN_PSEUDO) {
02144
02145 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02146 } else if (p->channel == CHAN_PSEUDO) {
02147
02148 strcpy(ch_name, "pseudo");
02149 } else {
02150
02151 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02152 }
02153 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02154 "Channel: %s\r\n"
02155 "Uniqueid: %s\r\n"
02156 "DAHDISpan: %d\r\n"
02157 "DAHDIChannel: %s\r\n",
02158 chan->name,
02159 chan->uniqueid,
02160 p->span,
02161 ch_name);
02162 }
02163
02164 #ifdef HAVE_PRI
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02176 {
02177 struct dahdi_pvt *p = pvt;
02178
02179 dahdi_ami_channel_event(p, chan);
02180 }
02181 #endif
02182
02183
02184
02185
02186 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02187 {
02188 struct dahdi_pvt *p = pvt;
02189 int oldval;
02190 int idx = analogsub_to_dahdisub(sub);
02191
02192 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02193 oldval = p->subs[idx].linear;
02194 p->subs[idx].linear = linear_mode ? 1 : 0;
02195 return oldval;
02196 }
02197
02198 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02199 {
02200 struct dahdi_pvt *p = pvt;
02201 int idx = analogsub_to_dahdisub(sub);
02202
02203 p->subs[idx].inthreeway = inthreeway;
02204 }
02205
02206 static int get_alarms(struct dahdi_pvt *p);
02207 static void handle_alarms(struct dahdi_pvt *p, int alms);
02208 static void my_get_and_handle_alarms(void *pvt)
02209 {
02210 int res;
02211 struct dahdi_pvt *p = pvt;
02212
02213 res = get_alarms(p);
02214 handle_alarms(p, res);
02215 }
02216
02217 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02218 {
02219 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02220 if (p)
02221 return p->sig_pvt;
02222 else
02223 return NULL;
02224 }
02225
02226 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02227 {
02228 struct dahdi_pvt *p = pvt;
02229 int dahdi_sub = analogsub_to_dahdisub(sub);
02230 return p->subs[dahdi_sub].dfd;
02231 }
02232
02233 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02234 {
02235 struct dahdi_pvt *p = pvt;
02236
02237
02238 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02239 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02240 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02241 *cidrings = cidrings[p->distinctivering - 1];
02242 } else {
02243 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02244 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02245 *cidrings = p->sendcalleridafter;
02246 }
02247 }
02248
02249 static void my_set_alarm(void *pvt, int in_alarm)
02250 {
02251 struct dahdi_pvt *p = pvt;
02252
02253 p->inalarm = in_alarm;
02254 }
02255
02256 static void my_set_dialing(void *pvt, int is_dialing)
02257 {
02258 struct dahdi_pvt *p = pvt;
02259
02260 p->dialing = is_dialing;
02261 }
02262
02263 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02264 static void my_set_digital(void *pvt, int is_digital)
02265 {
02266 struct dahdi_pvt *p = pvt;
02267
02268 p->digital = is_digital;
02269 }
02270 #endif
02271
02272 #if defined(HAVE_SS7)
02273 static void my_set_inservice(void *pvt, int is_inservice)
02274 {
02275 struct dahdi_pvt *p = pvt;
02276
02277 p->inservice = is_inservice;
02278 }
02279 #endif
02280
02281 #if defined(HAVE_SS7)
02282 static void my_set_locallyblocked(void *pvt, int is_blocked)
02283 {
02284 struct dahdi_pvt *p = pvt;
02285
02286 p->locallyblocked = is_blocked;
02287 }
02288 #endif
02289
02290 #if defined(HAVE_SS7)
02291 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02292 {
02293 struct dahdi_pvt *p = pvt;
02294
02295 p->remotelyblocked = is_blocked;
02296 }
02297 #endif
02298
02299 static void my_set_ringtimeout(void *pvt, int ringt)
02300 {
02301 struct dahdi_pvt *p = pvt;
02302 p->ringt = ringt;
02303 }
02304
02305 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02306 {
02307 struct dahdi_pvt *p = pvt;
02308
02309 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02310 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02311 gettimeofday(&p->waitingfordt, NULL);
02312 ast_setstate(ast, AST_STATE_OFFHOOK);
02313 }
02314 }
02315
02316 static int my_check_waitingfordt(void *pvt)
02317 {
02318 struct dahdi_pvt *p = pvt;
02319
02320 if (p->waitingfordt.tv_usec) {
02321 return 1;
02322 }
02323
02324 return 0;
02325 }
02326
02327 static void my_set_confirmanswer(void *pvt, int flag)
02328 {
02329 struct dahdi_pvt *p = pvt;
02330 p->confirmanswer = flag;
02331 }
02332
02333 static int my_check_confirmanswer(void *pvt)
02334 {
02335 struct dahdi_pvt *p = pvt;
02336 if (p->confirmanswer) {
02337 return 1;
02338 }
02339
02340 return 0;
02341 }
02342
02343 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02344 {
02345 struct dahdi_pvt *p = pvt;
02346
02347 p->callwaiting = callwaiting_enable;
02348 }
02349
02350 static void my_cancel_cidspill(void *pvt)
02351 {
02352 struct dahdi_pvt *p = pvt;
02353
02354 ast_free(p->cidspill);
02355 p->cidspill = NULL;
02356 restore_conference(p);
02357 }
02358
02359 static int my_confmute(void *pvt, int mute)
02360 {
02361 struct dahdi_pvt *p = pvt;
02362 return dahdi_confmute(p, mute);
02363 }
02364
02365 static void my_set_pulsedial(void *pvt, int flag)
02366 {
02367 struct dahdi_pvt *p = pvt;
02368 p->pulsedial = flag;
02369 }
02370
02371 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02372 {
02373 struct dahdi_pvt *p = pvt;
02374
02375 p->owner = new_owner;
02376 }
02377
02378 static const char *my_get_orig_dialstring(void *pvt)
02379 {
02380 struct dahdi_pvt *p = pvt;
02381
02382 return p->dialstring;
02383 }
02384
02385 static void my_increase_ss_count(void)
02386 {
02387 ast_mutex_lock(&ss_thread_lock);
02388 ss_thread_count++;
02389 ast_mutex_unlock(&ss_thread_lock);
02390 }
02391
02392 static void my_decrease_ss_count(void)
02393 {
02394 ast_mutex_lock(&ss_thread_lock);
02395 ss_thread_count--;
02396 ast_cond_signal(&ss_thread_complete);
02397 ast_mutex_unlock(&ss_thread_lock);
02398 }
02399
02400 static void my_all_subchannels_hungup(void *pvt)
02401 {
02402 struct dahdi_pvt *p = pvt;
02403 int res, law;
02404
02405 p->faxhandled = 0;
02406 p->didtdd = 0;
02407
02408 if (p->dsp) {
02409 ast_dsp_free(p->dsp);
02410 p->dsp = NULL;
02411 }
02412
02413 p->law = p->law_default;
02414 law = p->law_default;
02415 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02416 if (res < 0)
02417 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02418
02419 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02420
02421 #if 1
02422 {
02423 int i;
02424 p->owner = NULL;
02425
02426 for (i = 0; i < 3; i++) {
02427 p->subs[i].owner = NULL;
02428 }
02429 }
02430 #endif
02431
02432 reset_conf(p);
02433 if (num_restart_pending == 0) {
02434 restart_monitor();
02435 }
02436 }
02437
02438 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02439
02440 static int my_conf_del(void *pvt, enum analog_sub sub)
02441 {
02442 struct dahdi_pvt *p = pvt;
02443 int x = analogsub_to_dahdisub(sub);
02444
02445 return conf_del(p, &p->subs[x], x);
02446 }
02447
02448 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02449
02450 static int my_conf_add(void *pvt, enum analog_sub sub)
02451 {
02452 struct dahdi_pvt *p = pvt;
02453 int x = analogsub_to_dahdisub(sub);
02454
02455 return conf_add(p, &p->subs[x], x, 0);
02456 }
02457
02458 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02459
02460 static int my_complete_conference_update(void *pvt, int needconference)
02461 {
02462 struct dahdi_pvt *p = pvt;
02463 int needconf = needconference;
02464 int x;
02465 int useslavenative;
02466 struct dahdi_pvt *slave = NULL;
02467
02468 useslavenative = isslavenative(p, &slave);
02469
02470
02471
02472 for (x = 0; x < MAX_SLAVES; x++) {
02473 if (p->slaves[x]) {
02474 if (useslavenative)
02475 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02476 else {
02477 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02478 needconf++;
02479 }
02480 }
02481 }
02482
02483 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02484 if (useslavenative)
02485 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02486 else {
02487 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02488 needconf++;
02489 }
02490 }
02491
02492 if (p->master) {
02493 if (isslavenative(p->master, NULL)) {
02494 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02495 } else {
02496 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02497 }
02498 }
02499 if (!needconf) {
02500
02501
02502 p->confno = -1;
02503 }
02504
02505 return 0;
02506 }
02507
02508 static int check_for_conference(struct dahdi_pvt *p);
02509
02510 static int my_check_for_conference(void *pvt)
02511 {
02512 struct dahdi_pvt *p = pvt;
02513 return check_for_conference(p);
02514 }
02515
02516 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)
02517 {
02518 struct dahdi_pvt *p = pvt;
02519 int da, db;
02520 int tchan;
02521 int tinthreeway;
02522
02523 da = analogsub_to_dahdisub(a);
02524 db = analogsub_to_dahdisub(b);
02525
02526 tchan = p->subs[da].chan;
02527 p->subs[da].chan = p->subs[db].chan;
02528 p->subs[db].chan = tchan;
02529
02530 tinthreeway = p->subs[da].inthreeway;
02531 p->subs[da].inthreeway = p->subs[db].inthreeway;
02532 p->subs[db].inthreeway = tinthreeway;
02533
02534 p->subs[da].owner = ast_a;
02535 p->subs[db].owner = ast_b;
02536
02537 if (ast_a)
02538 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02539 if (ast_b)
02540 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02541
02542 wakeup_sub(p, a);
02543 wakeup_sub(p, b);
02544
02545 return;
02546 }
02547
02548 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02549
02550 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02551 {
02552 struct dahdi_pvt *p = pvt;
02553 int dsub = analogsub_to_dahdisub(sub);
02554
02555 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02556 }
02557
02558 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02559 static int dahdi_setlaw(int dfd, int law)
02560 {
02561 int res;
02562 res = ioctl(dfd, DAHDI_SETLAW, &law);
02563 if (res)
02564 return res;
02565 return 0;
02566 }
02567 #endif
02568
02569 #if defined(HAVE_PRI)
02570 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)
02571 {
02572 struct dahdi_pvt *p = pvt;
02573 int audio;
02574 int newlaw = -1;
02575
02576 switch (p->sig) {
02577 case SIG_PRI_LIB_HANDLE_CASES:
02578 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02579
02580 break;
02581 }
02582
02583 default:
02584
02585 audio = 1;
02586 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02587 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02588 p->channel, audio, strerror(errno));
02589 }
02590 break;
02591 }
02592
02593 if (law != SIG_PRI_DEFLAW) {
02594 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02595 }
02596
02597 ast_copy_string(p->exten, exten, sizeof(p->exten));
02598
02599 switch (law) {
02600 case SIG_PRI_DEFLAW:
02601 newlaw = 0;
02602 break;
02603 case SIG_PRI_ALAW:
02604 newlaw = DAHDI_LAW_ALAW;
02605 break;
02606 case SIG_PRI_ULAW:
02607 newlaw = DAHDI_LAW_MULAW;
02608 break;
02609 }
02610 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02611 }
02612 #endif
02613
02614 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02615
02616 #if defined(HAVE_PRI)
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626 static void my_pri_open_media(void *p)
02627 {
02628 struct dahdi_pvt *pvt = p;
02629 int res;
02630 int dfd;
02631 int set_val;
02632
02633 dfd = pvt->subs[SUB_REAL].dfd;
02634
02635
02636 set_val = 1;
02637 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02638 if (res < 0) {
02639 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02640 pvt->channel, strerror(errno));
02641 }
02642
02643
02644 res = dahdi_setlaw(dfd, pvt->law);
02645 if (res < 0) {
02646 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02647 }
02648
02649
02650 if (pvt->digital) {
02651 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02652 } else {
02653 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02654 pvt->law);
02655 }
02656 if (res < 0) {
02657 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02658 }
02659
02660 if (pvt->dsp_features && pvt->dsp) {
02661 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02662 pvt->dsp_features = 0;
02663 }
02664 }
02665 #endif
02666
02667 static int unalloc_sub(struct dahdi_pvt *p, int x);
02668
02669 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02670 {
02671 struct dahdi_pvt *p = pvt;
02672
02673 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02674 }
02675
02676 static int alloc_sub(struct dahdi_pvt *p, int x);
02677
02678 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02679 {
02680 struct dahdi_pvt *p = pvt;
02681
02682 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02683 }
02684
02685 static int has_voicemail(struct dahdi_pvt *p);
02686
02687 static int my_has_voicemail(void *pvt)
02688 {
02689 struct dahdi_pvt *p = pvt;
02690
02691 return has_voicemail(p);
02692 }
02693
02694 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02695 {
02696 struct dahdi_pvt *p = pvt;
02697 int index;
02698
02699 index = analogsub_to_dahdisub(sub);
02700
02701 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02702 }
02703
02704 static enum analog_event dahdievent_to_analogevent(int event)
02705 {
02706 enum analog_event res;
02707
02708 switch (event) {
02709 case DAHDI_EVENT_ONHOOK:
02710 res = ANALOG_EVENT_ONHOOK;
02711 break;
02712 case DAHDI_EVENT_RINGOFFHOOK:
02713 res = ANALOG_EVENT_RINGOFFHOOK;
02714 break;
02715 case DAHDI_EVENT_WINKFLASH:
02716 res = ANALOG_EVENT_WINKFLASH;
02717 break;
02718 case DAHDI_EVENT_ALARM:
02719 res = ANALOG_EVENT_ALARM;
02720 break;
02721 case DAHDI_EVENT_NOALARM:
02722 res = ANALOG_EVENT_NOALARM;
02723 break;
02724 case DAHDI_EVENT_DIALCOMPLETE:
02725 res = ANALOG_EVENT_DIALCOMPLETE;
02726 break;
02727 case DAHDI_EVENT_RINGERON:
02728 res = ANALOG_EVENT_RINGERON;
02729 break;
02730 case DAHDI_EVENT_RINGEROFF:
02731 res = ANALOG_EVENT_RINGEROFF;
02732 break;
02733 case DAHDI_EVENT_HOOKCOMPLETE:
02734 res = ANALOG_EVENT_HOOKCOMPLETE;
02735 break;
02736 case DAHDI_EVENT_PULSE_START:
02737 res = ANALOG_EVENT_PULSE_START;
02738 break;
02739 case DAHDI_EVENT_POLARITY:
02740 res = ANALOG_EVENT_POLARITY;
02741 break;
02742 case DAHDI_EVENT_RINGBEGIN:
02743 res = ANALOG_EVENT_RINGBEGIN;
02744 break;
02745 case DAHDI_EVENT_EC_DISABLED:
02746 res = ANALOG_EVENT_EC_DISABLED;
02747 break;
02748 case DAHDI_EVENT_REMOVED:
02749 res = ANALOG_EVENT_REMOVED;
02750 break;
02751 case DAHDI_EVENT_NEONMWI_ACTIVE:
02752 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02753 break;
02754 case DAHDI_EVENT_NEONMWI_INACTIVE:
02755 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02756 break;
02757 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02758 case DAHDI_EVENT_TX_CED_DETECTED:
02759 res = ANALOG_EVENT_TX_CED_DETECTED;
02760 break;
02761 case DAHDI_EVENT_RX_CED_DETECTED:
02762 res = ANALOG_EVENT_RX_CED_DETECTED;
02763 break;
02764 case DAHDI_EVENT_EC_NLP_DISABLED:
02765 res = ANALOG_EVENT_EC_NLP_DISABLED;
02766 break;
02767 case DAHDI_EVENT_EC_NLP_ENABLED:
02768 res = ANALOG_EVENT_EC_NLP_ENABLED;
02769 break;
02770 #endif
02771 case DAHDI_EVENT_PULSEDIGIT:
02772 res = ANALOG_EVENT_PULSEDIGIT;
02773 break;
02774 case DAHDI_EVENT_DTMFDOWN:
02775 res = ANALOG_EVENT_DTMFDOWN;
02776 break;
02777 case DAHDI_EVENT_DTMFUP:
02778 res = ANALOG_EVENT_DTMFUP;
02779 break;
02780 default:
02781 switch(event & 0xFFFF0000) {
02782 case DAHDI_EVENT_PULSEDIGIT:
02783 case DAHDI_EVENT_DTMFDOWN:
02784 case DAHDI_EVENT_DTMFUP:
02785
02786
02787
02788
02789 return event;
02790 }
02791
02792 res = ANALOG_EVENT_ERROR;
02793 break;
02794 }
02795
02796 return res;
02797 }
02798
02799 static inline int dahdi_wait_event(int fd);
02800
02801 static int my_wait_event(void *pvt)
02802 {
02803 struct dahdi_pvt *p = pvt;
02804
02805 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02806 }
02807
02808 static int my_get_event(void *pvt)
02809 {
02810 struct dahdi_pvt *p = pvt;
02811 int res;
02812
02813 if (p->fake_event) {
02814 res = p->fake_event;
02815 p->fake_event = 0;
02816 } else
02817 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02818
02819 return dahdievent_to_analogevent(res);
02820 }
02821
02822 static int my_is_off_hook(void *pvt)
02823 {
02824 struct dahdi_pvt *p = pvt;
02825 int res;
02826 struct dahdi_params par;
02827
02828 memset(&par, 0, sizeof(par));
02829
02830 if (p->subs[SUB_REAL].dfd > -1)
02831 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02832 else {
02833
02834 res = 0;
02835 par.rxisoffhook = 0;
02836 }
02837 if (res) {
02838 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02839 }
02840
02841 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02842
02843
02844
02845 return (par.rxbits > -1) || par.rxisoffhook;
02846 }
02847
02848 return par.rxisoffhook;
02849 }
02850
02851 static void dahdi_enable_ec(struct dahdi_pvt *p);
02852 static void dahdi_disable_ec(struct dahdi_pvt *p);
02853
02854 static int my_set_echocanceller(void *pvt, int enable)
02855 {
02856 struct dahdi_pvt *p = pvt;
02857
02858 if (enable)
02859 dahdi_enable_ec(p);
02860 else
02861 dahdi_disable_ec(p);
02862
02863 return 0;
02864 }
02865
02866 static int dahdi_ring_phone(struct dahdi_pvt *p);
02867
02868 static int my_ring(void *pvt)
02869 {
02870 struct dahdi_pvt *p = pvt;
02871
02872 return dahdi_ring_phone(p);
02873 }
02874
02875 static int my_flash(void *pvt)
02876 {
02877 struct dahdi_pvt *p = pvt;
02878 int func = DAHDI_FLASH;
02879 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02880 }
02881
02882 static inline int dahdi_set_hook(int fd, int hs);
02883
02884 static int my_off_hook(void *pvt)
02885 {
02886 struct dahdi_pvt *p = pvt;
02887 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02888 }
02889
02890 static void my_set_needringing(void *pvt, int value)
02891 {
02892 struct dahdi_pvt *p = pvt;
02893 p->subs[SUB_REAL].needringing = value;
02894 }
02895
02896 static void my_set_polarity(void *pvt, int value)
02897 {
02898 struct dahdi_pvt *p = pvt;
02899
02900 if (p->channel == CHAN_PSEUDO) {
02901 return;
02902 }
02903 p->polarity = value;
02904 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02905 }
02906
02907 static void my_start_polarityswitch(void *pvt)
02908 {
02909 struct dahdi_pvt *p = pvt;
02910
02911 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02912 my_set_polarity(pvt, 0);
02913 }
02914 }
02915
02916 static void my_answer_polarityswitch(void *pvt)
02917 {
02918 struct dahdi_pvt *p = pvt;
02919
02920 if (!p->answeronpolarityswitch) {
02921 return;
02922 }
02923
02924 my_set_polarity(pvt, 1);
02925 }
02926
02927 static void my_hangup_polarityswitch(void *pvt)
02928 {
02929 struct dahdi_pvt *p = pvt;
02930
02931 if (!p->hanguponpolarityswitch) {
02932 return;
02933 }
02934
02935 if (p->answeronpolarityswitch) {
02936 my_set_polarity(pvt, 0);
02937 } else {
02938 my_set_polarity(pvt, 1);
02939 }
02940 }
02941
02942 static int my_start(void *pvt)
02943 {
02944 struct dahdi_pvt *p = pvt;
02945 int x = DAHDI_START;
02946
02947 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02948 }
02949
02950 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02951 {
02952 int index = analogsub_to_dahdisub(sub);
02953 int res;
02954 struct dahdi_pvt *p = pvt;
02955 struct dahdi_dialoperation ddop;
02956
02957 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02958 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02959 return -1;
02960 }
02961
02962 if (sub != ANALOG_SUB_REAL) {
02963 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
02964 dop->dialstr, p->channel, sub);
02965 return -1;
02966 }
02967
02968 ddop.op = DAHDI_DIAL_OP_REPLACE;
02969 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02970
02971 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
02972
02973 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02974 if (res == -1) {
02975 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02976 }
02977
02978 return res;
02979 }
02980
02981 static void dahdi_train_ec(struct dahdi_pvt *p);
02982
02983 static int my_train_echocanceller(void *pvt)
02984 {
02985 struct dahdi_pvt *p = pvt;
02986
02987 dahdi_train_ec(p);
02988
02989 return 0;
02990 }
02991
02992 static int my_is_dialing(void *pvt, enum analog_sub sub)
02993 {
02994 struct dahdi_pvt *p = pvt;
02995 int index;
02996 int x;
02997
02998 index = analogsub_to_dahdisub(sub);
02999
03000 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03001 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03002 return -1;
03003 }
03004
03005 return x;
03006 }
03007
03008 static int my_on_hook(void *pvt)
03009 {
03010 struct dahdi_pvt *p = pvt;
03011 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03012 }
03013
03014 #if defined(HAVE_PRI)
03015 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03016 {
03017 struct dahdi_pvt *old_chan = chan_old;
03018 struct dahdi_pvt *new_chan = chan_new;
03019
03020 new_chan->owner = old_chan->owner;
03021 old_chan->owner = NULL;
03022 if (new_chan->owner) {
03023 new_chan->owner->tech_pvt = new_chan;
03024 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03025 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03026 old_chan->subs[SUB_REAL].owner = NULL;
03027 }
03028
03029 new_chan->dsp = old_chan->dsp;
03030 new_chan->dsp_features = old_chan->dsp_features;
03031 old_chan->dsp = NULL;
03032 old_chan->dsp_features = 0;
03033
03034
03035 new_chan->dialing = old_chan->dialing;
03036 new_chan->digital = old_chan->digital;
03037 new_chan->outgoing = old_chan->outgoing;
03038 old_chan->dialing = 0;
03039 old_chan->digital = 0;
03040 old_chan->outgoing = 0;
03041
03042
03043 new_chan->law = old_chan->law;
03044 strcpy(new_chan->dialstring, old_chan->dialstring);
03045 }
03046 #endif
03047
03048 #if defined(HAVE_PRI)
03049 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03050 {
03051 switch (tone) {
03052 case SIG_PRI_TONE_RINGTONE:
03053 return DAHDI_TONE_RINGTONE;
03054 case SIG_PRI_TONE_STUTTER:
03055 return DAHDI_TONE_STUTTER;
03056 case SIG_PRI_TONE_CONGESTION:
03057 return DAHDI_TONE_CONGESTION;
03058 case SIG_PRI_TONE_DIALTONE:
03059 return DAHDI_TONE_DIALTONE;
03060 case SIG_PRI_TONE_DIALRECALL:
03061 return DAHDI_TONE_DIALRECALL;
03062 case SIG_PRI_TONE_INFO:
03063 return DAHDI_TONE_INFO;
03064 case SIG_PRI_TONE_BUSY:
03065 return DAHDI_TONE_BUSY;
03066 default:
03067 return -1;
03068 }
03069 }
03070 #endif
03071
03072 #if defined(HAVE_PRI)
03073 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03074 {
03075 int x;
03076
03077 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03078 if (x) {
03079 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03080 }
03081
03082 switch (x) {
03083 case DAHDI_EVENT_ALARM:
03084 pri_event_alarm(pri, index, 0);
03085 break;
03086 case DAHDI_EVENT_NOALARM:
03087 pri_event_noalarm(pri, index, 0);
03088 break;
03089 default:
03090 break;
03091 }
03092 }
03093 #endif
03094
03095 #if defined(HAVE_PRI)
03096 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03097 {
03098 struct dahdi_pvt *p = pvt;
03099
03100 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03101 }
03102 #endif
03103
03104 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03116 {
03117 struct dahdi_pvt *p = pvt;
03118
03119 ast_copy_string(p->cid_num,
03120 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03121 sizeof(p->cid_num));
03122 ast_copy_string(p->cid_name,
03123 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03124 sizeof(p->cid_name));
03125 ast_copy_string(p->cid_subaddr,
03126 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03127 sizeof(p->cid_subaddr));
03128 p->cid_ton = caller->id.number.plan;
03129 p->callingpres = ast_party_id_presentation(&caller->id);
03130 if (caller->id.tag) {
03131 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03132 }
03133 ast_copy_string(p->cid_ani,
03134 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03135 sizeof(p->cid_ani));
03136 p->cid_ani2 = caller->ani2;
03137 }
03138 #endif
03139
03140 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151 static void my_set_dnid(void *pvt, const char *dnid)
03152 {
03153 struct dahdi_pvt *p = pvt;
03154
03155 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03156 }
03157 #endif
03158
03159 #if defined(HAVE_PRI)
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170 static void my_set_rdnis(void *pvt, const char *rdnis)
03171 {
03172 struct dahdi_pvt *p = pvt;
03173
03174 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03175 }
03176 #endif
03177
03178 #if defined(HAVE_PRI)
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03204 {
03205 char *dial;
03206 struct dahdi_pvt *pvt;
03207 AST_DECLARE_APP_ARGS(args,
03208 AST_APP_ARG(tech);
03209 AST_APP_ARG(group);
03210
03211
03212
03213 );
03214
03215 pvt = priv;
03216 dial = ast_strdupa(pvt->dialstring);
03217 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03218 if (!args.tech) {
03219 ast_copy_string(buf, pvt->dialstring, buf_size);
03220 return;
03221 }
03222 if (!args.group) {
03223
03224 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03225 return;
03226 }
03227 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03228
03229
03230 ast_copy_string(buf, pvt->dialstring, buf_size);
03231 return;
03232 }
03233
03234 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03235 }
03236 #endif
03237
03238 #if defined(HAVE_PRI)
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03251 {
03252 unsigned idx;
03253 unsigned num_b_chans;
03254 unsigned in_use;
03255 unsigned in_alarm;
03256 enum ast_device_state new_state;
03257
03258
03259 num_b_chans = 0;
03260 in_use = 0;
03261 in_alarm = 1;
03262 for (idx = pri->numchans; idx--;) {
03263 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03264
03265 ++num_b_chans;
03266 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03267 ++in_use;
03268 }
03269 if (!pri->pvts[idx]->inalarm) {
03270
03271 in_alarm = 0;
03272 }
03273 }
03274 }
03275
03276
03277 if (in_alarm) {
03278 new_state = AST_DEVICE_UNAVAILABLE;
03279 } else {
03280 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03281 }
03282 if (pri->congestion_devstate != new_state) {
03283 pri->congestion_devstate = new_state;
03284 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03285 }
03286 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03287
03288 if (in_alarm) {
03289 new_state = AST_DEVICE_UNAVAILABLE;
03290 } else if (!in_use) {
03291 new_state = AST_DEVICE_NOT_INUSE;
03292 } else if (!pri->user_busy_threshold) {
03293 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03294 } else {
03295 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03296 : AST_DEVICE_BUSY;
03297 }
03298 if (pri->threshold_devstate != new_state) {
03299 pri->threshold_devstate = new_state;
03300 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03301 }
03302 #endif
03303 }
03304 #endif
03305
03306 #if defined(HAVE_PRI)
03307
03308
03309
03310
03311
03312
03313
03314 static void my_module_ref(void)
03315 {
03316 ast_module_ref(ast_module_info->self);
03317 }
03318 #endif
03319
03320 #if defined(HAVE_PRI)
03321
03322
03323
03324
03325
03326
03327
03328 static void my_module_unref(void)
03329 {
03330 ast_module_unref(ast_module_info->self);
03331 }
03332 #endif
03333
03334 #if defined(HAVE_PRI)
03335 #if defined(HAVE_PRI_CALL_WAITING)
03336 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03337 #endif
03338 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03339
03340 static struct sig_pri_callback dahdi_pri_callbacks =
03341 {
03342 .handle_dchan_exception = my_handle_dchan_exception,
03343 .play_tone = my_pri_play_tone,
03344 .set_echocanceller = my_set_echocanceller,
03345 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03346 .lock_private = my_lock_private,
03347 .unlock_private = my_unlock_private,
03348 .new_ast_channel = my_new_pri_ast_channel,
03349 .fixup_chans = my_pri_fixup_chans,
03350 .set_alarm = my_set_alarm,
03351 .set_dialing = my_set_dialing,
03352 .set_digital = my_set_digital,
03353 .set_callerid = my_set_callerid,
03354 .set_dnid = my_set_dnid,
03355 .set_rdnis = my_set_rdnis,
03356 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03357 #if defined(HAVE_PRI_CALL_WAITING)
03358 .init_config = my_pri_init_config,
03359 #endif
03360 .get_orig_dialstring = my_get_orig_dialstring,
03361 .make_cc_dialstring = my_pri_make_cc_dialstring,
03362 .update_span_devstate = dahdi_pri_update_span_devstate,
03363 .module_ref = my_module_ref,
03364 .module_unref = my_module_unref,
03365 .open_media = my_pri_open_media,
03366 .ami_channel_event = my_ami_channel_event,
03367 };
03368 #endif
03369
03370 #if defined(HAVE_SS7)
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03382 {
03383 int event;
03384
03385 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03386 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03387 linkset->span, which);
03388 return;
03389 }
03390 switch (event) {
03391 case DAHDI_EVENT_NONE:
03392 break;
03393 case DAHDI_EVENT_ALARM:
03394 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03395 event2str(event), event, linkset->span, which);
03396 sig_ss7_link_alarm(linkset, which);
03397 break;
03398 case DAHDI_EVENT_NOALARM:
03399 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03400 event2str(event), event, linkset->span, which);
03401 sig_ss7_link_noalarm(linkset, which);
03402 break;
03403 default:
03404 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03405 event2str(event), event, linkset->span, which);
03406 break;
03407 }
03408 }
03409 #endif
03410
03411 #if defined(HAVE_SS7)
03412 static void my_ss7_set_loopback(void *pvt, int enable)
03413 {
03414 struct dahdi_pvt *p = pvt;
03415
03416 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03417 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03418 strerror(errno));
03419 }
03420 }
03421 #endif
03422
03423 #if defined(HAVE_SS7)
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438 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)
03439 {
03440 struct dahdi_pvt *p = pvt;
03441 int audio;
03442 int newlaw;
03443
03444
03445 audio = 1;
03446 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03447 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03448 p->channel, audio, strerror(errno));
03449
03450 if (law != SIG_SS7_DEFLAW) {
03451 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03452 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03453 }
03454
03455 ast_copy_string(p->exten, exten, sizeof(p->exten));
03456
03457 newlaw = -1;
03458 switch (law) {
03459 case SIG_SS7_DEFLAW:
03460 newlaw = 0;
03461 break;
03462 case SIG_SS7_ALAW:
03463 newlaw = DAHDI_LAW_ALAW;
03464 break;
03465 case SIG_SS7_ULAW:
03466 newlaw = DAHDI_LAW_MULAW;
03467 break;
03468 }
03469 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03470 }
03471 #endif
03472
03473 #if defined(HAVE_SS7)
03474 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03475 {
03476 switch (tone) {
03477 case SIG_SS7_TONE_RINGTONE:
03478 return DAHDI_TONE_RINGTONE;
03479 case SIG_SS7_TONE_STUTTER:
03480 return DAHDI_TONE_STUTTER;
03481 case SIG_SS7_TONE_CONGESTION:
03482 return DAHDI_TONE_CONGESTION;
03483 case SIG_SS7_TONE_DIALTONE:
03484 return DAHDI_TONE_DIALTONE;
03485 case SIG_SS7_TONE_DIALRECALL:
03486 return DAHDI_TONE_DIALRECALL;
03487 case SIG_SS7_TONE_INFO:
03488 return DAHDI_TONE_INFO;
03489 case SIG_SS7_TONE_BUSY:
03490 return DAHDI_TONE_BUSY;
03491 default:
03492 return -1;
03493 }
03494 }
03495 #endif
03496
03497 #if defined(HAVE_SS7)
03498 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03499 {
03500 struct dahdi_pvt *p = pvt;
03501
03502 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03503 }
03504 #endif
03505
03506 #if defined(HAVE_SS7)
03507 static struct sig_ss7_callback dahdi_ss7_callbacks =
03508 {
03509 .lock_private = my_lock_private,
03510 .unlock_private = my_unlock_private,
03511
03512 .set_echocanceller = my_set_echocanceller,
03513 .set_loopback = my_ss7_set_loopback,
03514
03515 .new_ast_channel = my_new_ss7_ast_channel,
03516 .play_tone = my_ss7_play_tone,
03517
03518 .handle_link_exception = my_handle_link_exception,
03519 .set_alarm = my_set_alarm,
03520 .set_dialing = my_set_dialing,
03521 .set_digital = my_set_digital,
03522 .set_inservice = my_set_inservice,
03523 .set_locallyblocked = my_set_locallyblocked,
03524 .set_remotelyblocked = my_set_remotelyblocked,
03525 .set_callerid = my_set_callerid,
03526 .set_dnid = my_set_dnid,
03527 };
03528 #endif
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548 static void notify_message(char *mailbox_full, int thereornot)
03549 {
03550 char s[sizeof(mwimonitornotify) + 80];
03551 struct ast_event *event;
03552 char *mailbox, *context;
03553
03554
03555 context = mailbox = ast_strdupa(mailbox_full);
03556 strsep(&context, "@");
03557 if (ast_strlen_zero(context))
03558 context = "default";
03559
03560 if (!(event = ast_event_new(AST_EVENT_MWI,
03561 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03562 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03563 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03564 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03565 AST_EVENT_IE_END))) {
03566 return;
03567 }
03568
03569 ast_event_queue_and_cache(event);
03570
03571 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03572 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03573 ast_safe_system(s);
03574 }
03575 }
03576
03577 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03578 {
03579 struct dahdi_pvt *p = pvt;
03580
03581 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03582 return;
03583
03584 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03585 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03586 notify_message(p->mailbox, 1);
03587 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03588 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03589 notify_message(p->mailbox, 0);
03590 }
03591
03592
03593 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03594 ast_hangup(chan);
03595 return;
03596 }
03597 }
03598
03599 static int my_have_progressdetect(void *pvt)
03600 {
03601 struct dahdi_pvt *p = pvt;
03602
03603 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03604 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03605 return 1;
03606 } else {
03607
03608 return 0;
03609 }
03610 }
03611
03612 static struct analog_callback dahdi_analog_callbacks =
03613 {
03614 .play_tone = my_play_tone,
03615 .get_event = my_get_event,
03616 .wait_event = my_wait_event,
03617 .is_off_hook = my_is_off_hook,
03618 .set_echocanceller = my_set_echocanceller,
03619 .ring = my_ring,
03620 .flash = my_flash,
03621 .off_hook = my_off_hook,
03622 .dial_digits = my_dial_digits,
03623 .train_echocanceller = my_train_echocanceller,
03624 .on_hook = my_on_hook,
03625 .is_dialing = my_is_dialing,
03626 .allocate_sub = my_allocate_sub,
03627 .unallocate_sub = my_unallocate_sub,
03628 .swap_subs = my_swap_subchannels,
03629 .has_voicemail = my_has_voicemail,
03630 .check_for_conference = my_check_for_conference,
03631 .conf_add = my_conf_add,
03632 .conf_del = my_conf_del,
03633 .complete_conference_update = my_complete_conference_update,
03634 .start = my_start,
03635 .all_subchannels_hungup = my_all_subchannels_hungup,
03636 .lock_private = my_lock_private,
03637 .unlock_private = my_unlock_private,
03638 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03639 .handle_dtmf = my_handle_dtmf,
03640 .wink = my_wink,
03641 .new_ast_channel = my_new_analog_ast_channel,
03642 .dsp_set_digitmode = my_dsp_set_digitmode,
03643 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03644 .send_callerid = my_send_callerid,
03645 .callwait = my_callwait,
03646 .stop_callwait = my_stop_callwait,
03647 .get_callerid = my_get_callerid,
03648 .start_cid_detect = my_start_cid_detect,
03649 .stop_cid_detect = my_stop_cid_detect,
03650 .handle_notify_message = my_handle_notify_message,
03651 .increase_ss_count = my_increase_ss_count,
03652 .decrease_ss_count = my_decrease_ss_count,
03653 .distinctive_ring = my_distinctive_ring,
03654 .set_linear_mode = my_set_linear_mode,
03655 .set_inthreeway = my_set_inthreeway,
03656 .get_and_handle_alarms = my_get_and_handle_alarms,
03657 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03658 .get_sub_fd = my_get_sub_fd,
03659 .set_cadence = my_set_cadence,
03660 .set_alarm = my_set_alarm,
03661 .set_dialing = my_set_dialing,
03662 .set_ringtimeout = my_set_ringtimeout,
03663 .set_waitingfordt = my_set_waitingfordt,
03664 .check_waitingfordt = my_check_waitingfordt,
03665 .set_confirmanswer = my_set_confirmanswer,
03666 .check_confirmanswer = my_check_confirmanswer,
03667 .set_callwaiting = my_set_callwaiting,
03668 .cancel_cidspill = my_cancel_cidspill,
03669 .confmute = my_confmute,
03670 .set_pulsedial = my_set_pulsedial,
03671 .set_new_owner = my_set_new_owner,
03672 .get_orig_dialstring = my_get_orig_dialstring,
03673 .set_needringing = my_set_needringing,
03674 .set_polarity = my_set_polarity,
03675 .start_polarityswitch = my_start_polarityswitch,
03676 .answer_polarityswitch = my_answer_polarityswitch,
03677 .hangup_polarityswitch = my_hangup_polarityswitch,
03678 .have_progressdetect = my_have_progressdetect,
03679 };
03680
03681
03682 static struct dahdi_pvt *round_robin[32];
03683
03684 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03685 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03686 {
03687 int res;
03688 if (p->subs[SUB_REAL].owner == ast)
03689 res = 0;
03690 else if (p->subs[SUB_CALLWAIT].owner == ast)
03691 res = 1;
03692 else if (p->subs[SUB_THREEWAY].owner == ast)
03693 res = 2;
03694 else {
03695 res = -1;
03696 if (!nullok)
03697 ast_log(LOG_WARNING,
03698 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03699 ast ? ast->name : "", p->channel, fname, line);
03700 }
03701 return res;
03702 }
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03720 {
03721 for (;;) {
03722 if (!pvt->subs[sub_idx].owner) {
03723
03724 break;
03725 }
03726 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03727
03728 break;
03729 }
03730
03731 DEADLOCK_AVOIDANCE(&pvt->lock);
03732 }
03733 }
03734
03735 static void wakeup_sub(struct dahdi_pvt *p, int a)
03736 {
03737 dahdi_lock_sub_owner(p, a);
03738 if (p->subs[a].owner) {
03739 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03740 ast_channel_unlock(p->subs[a].owner);
03741 }
03742 }
03743
03744 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03745 {
03746 for (;;) {
03747 if (p->owner) {
03748 if (ast_channel_trylock(p->owner)) {
03749 DEADLOCK_AVOIDANCE(&p->lock);
03750 } else {
03751 ast_queue_frame(p->owner, f);
03752 ast_channel_unlock(p->owner);
03753 break;
03754 }
03755 } else
03756 break;
03757 }
03758 }
03759
03760 static void handle_clear_alarms(struct dahdi_pvt *p)
03761 {
03762 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03763 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03764 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03765 }
03766 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03767 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03768 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03769 }
03770 }
03771
03772 #ifdef HAVE_OPENR2
03773
03774 static int dahdi_r2_answer(struct dahdi_pvt *p)
03775 {
03776 int res = 0;
03777
03778
03779
03780 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03781 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03782 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03783 if (!double_answer) {
03784
03785
03786 res = openr2_chan_answer_call(p->r2chan);
03787 } else if (wants_double_answer) {
03788 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03789 } else {
03790 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03791 }
03792 #else
03793 res = openr2_chan_answer_call(p->r2chan);
03794 #endif
03795 return res;
03796 }
03797
03798
03799
03800
03801 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03802 {
03803 openr2_calling_party_category_t cat;
03804 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03805 struct dahdi_pvt *p = c->tech_pvt;
03806 if (ast_strlen_zero(catstr)) {
03807 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03808 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03809 return p->mfcr2_category;
03810 }
03811 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03812 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03813 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03814 return p->mfcr2_category;
03815 }
03816 ast_debug(1, "Using category %s\n", catstr);
03817 return cat;
03818 }
03819
03820 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03821 {
03822 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03823 ast_mutex_lock(&p->lock);
03824 if (p->mfcr2call) {
03825 ast_mutex_unlock(&p->lock);
03826
03827
03828
03829
03830
03831 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03832 return;
03833 }
03834 p->mfcr2call = 1;
03835
03836 p->cid_name[0] = '\0';
03837 p->cid_num[0] = '\0';
03838 p->cid_subaddr[0] = '\0';
03839 p->rdnis[0] = '\0';
03840 p->exten[0] = '\0';
03841 p->mfcr2_ani_index = '\0';
03842 p->mfcr2_dnis_index = '\0';
03843 p->mfcr2_dnis_matched = 0;
03844 p->mfcr2_answer_pending = 0;
03845 p->mfcr2_call_accepted = 0;
03846 ast_mutex_unlock(&p->lock);
03847 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03848 }
03849
03850 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03851 {
03852 int res;
03853 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03854 ast_mutex_lock(&p->lock);
03855 p->inalarm = alarm ? 1 : 0;
03856 if (p->inalarm) {
03857 res = get_alarms(p);
03858 handle_alarms(p, res);
03859 } else {
03860 handle_clear_alarms(p);
03861 }
03862 ast_mutex_unlock(&p->lock);
03863 }
03864
03865 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03866 {
03867 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03868 }
03869
03870 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03871 {
03872 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03873 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03874 if (p->owner) {
03875 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03876 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03877 }
03878 ast_mutex_lock(&p->lock);
03879 p->mfcr2call = 0;
03880 ast_mutex_unlock(&p->lock);
03881 }
03882
03883 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03884 {
03885 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03886 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03887 p->channel, openr2_proto_get_disconnect_string(cause));
03888
03889 openr2_chan_set_idle(p->r2chan);
03890 ast_mutex_lock(&p->lock);
03891 p->mfcr2call = 0;
03892 ast_mutex_unlock(&p->lock);
03893 }
03894 }
03895
03896 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03897 {
03898 struct dahdi_pvt *p;
03899 struct ast_channel *c;
03900 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03901 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03902 openr2_proto_get_category_string(category));
03903 p = openr2_chan_get_client_data(r2chan);
03904
03905 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03906 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03907 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03908 return;
03909 }
03910 ast_mutex_lock(&p->lock);
03911 p->mfcr2_recvd_category = category;
03912
03913 if (!p->use_callerid) {
03914 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03915 p->cid_num[0] = 0;
03916 p->cid_name[0] = 0;
03917 }
03918
03919 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03920 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03921 p->exten[0] = 's';
03922 p->exten[1] = 0;
03923 }
03924 ast_mutex_unlock(&p->lock);
03925 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03926 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03927 p->channel, p->exten, p->context);
03928 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03929 return;
03930 }
03931 if (!p->mfcr2_accept_on_offer) {
03932
03933 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03934 if (c) {
03935
03936
03937
03938 return;
03939 }
03940 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03941 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03942 } else if (p->mfcr2_charge_calls) {
03943 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03944 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03945 } else {
03946 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03947 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03948 }
03949 }
03950
03951 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03952 {
03953 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03954 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03955 ast_mutex_lock(&p->lock);
03956 p->mfcr2call = 0;
03957 ast_mutex_unlock(&p->lock);
03958 }
03959
03960 static void dahdi_enable_ec(struct dahdi_pvt *p);
03961 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03962 {
03963 struct dahdi_pvt *p = NULL;
03964 struct ast_channel *c = NULL;
03965 p = openr2_chan_get_client_data(r2chan);
03966 dahdi_enable_ec(p);
03967 p->mfcr2_call_accepted = 1;
03968
03969 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03970 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03971
03972
03973
03974
03975 if (!p->mfcr2_accept_on_offer) {
03976 openr2_chan_disable_read(r2chan);
03977 if (p->mfcr2_answer_pending) {
03978 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03979 dahdi_r2_answer(p);
03980 }
03981 return;
03982 }
03983 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03984 if (c) {
03985
03986
03987 openr2_chan_disable_read(r2chan);
03988 return;
03989 }
03990 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03991
03992 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03993 return;
03994 }
03995
03996 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03997 p->subs[SUB_REAL].needringing = 1;
03998 p->dialing = 0;
03999
04000 openr2_chan_disable_read(r2chan);
04001 }
04002
04003 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04004 {
04005 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04006 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04007 p->subs[SUB_REAL].needanswer = 1;
04008 }
04009
04010 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04011 {
04012
04013 }
04014
04015 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04016 {
04017 switch (cause) {
04018 case OR2_CAUSE_BUSY_NUMBER:
04019 return AST_CAUSE_BUSY;
04020 case OR2_CAUSE_NETWORK_CONGESTION:
04021 return AST_CAUSE_CONGESTION;
04022 case OR2_CAUSE_OUT_OF_ORDER:
04023 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04024 case OR2_CAUSE_UNALLOCATED_NUMBER:
04025 return AST_CAUSE_UNREGISTERED;
04026 case OR2_CAUSE_NO_ANSWER:
04027 return AST_CAUSE_NO_ANSWER;
04028 case OR2_CAUSE_NORMAL_CLEARING:
04029 return AST_CAUSE_NORMAL_CLEARING;
04030 case OR2_CAUSE_UNSPECIFIED:
04031 default:
04032 return AST_CAUSE_NOTDEFINED;
04033 }
04034 }
04035
04036 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04037 {
04038 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04039 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04040 ast_mutex_lock(&p->lock);
04041 if (!p->owner) {
04042 ast_mutex_unlock(&p->lock);
04043
04044 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04045 return;
04046 }
04047
04048
04049 if (p->owner->_state == AST_STATE_UP) {
04050 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04051 ast_mutex_unlock(&p->lock);
04052 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04053
04054 switch (cause) {
04055 case OR2_CAUSE_BUSY_NUMBER:
04056 p->subs[SUB_REAL].needbusy = 1;
04057 break;
04058 case OR2_CAUSE_NETWORK_CONGESTION:
04059 case OR2_CAUSE_OUT_OF_ORDER:
04060 case OR2_CAUSE_UNALLOCATED_NUMBER:
04061 case OR2_CAUSE_NO_ANSWER:
04062 case OR2_CAUSE_UNSPECIFIED:
04063 case OR2_CAUSE_NORMAL_CLEARING:
04064 p->subs[SUB_REAL].needcongestion = 1;
04065 break;
04066 default:
04067 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04068 }
04069 ast_mutex_unlock(&p->lock);
04070 } else {
04071 ast_mutex_unlock(&p->lock);
04072
04073
04074 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04075 }
04076 }
04077
04078 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04079 {
04080 switch (level) {
04081 case OR2_LOG_NOTICE:
04082 ast_verbose("%s", logmessage);
04083 break;
04084 case OR2_LOG_WARNING:
04085 ast_log(LOG_WARNING, "%s", logmessage);
04086 break;
04087 case OR2_LOG_ERROR:
04088 ast_log(LOG_ERROR, "%s", logmessage);
04089 break;
04090 case OR2_LOG_STACK_TRACE:
04091 case OR2_LOG_MF_TRACE:
04092 case OR2_LOG_CAS_TRACE:
04093 case OR2_LOG_DEBUG:
04094 case OR2_LOG_EX_DEBUG:
04095 ast_log(LOG_DEBUG, "%s", logmessage);
04096 break;
04097 default:
04098 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04099 ast_log(LOG_DEBUG, "%s", logmessage);
04100 break;
04101 }
04102 }
04103
04104 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04105 {
04106 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04107 ast_mutex_lock(&p->lock);
04108 p->remotelyblocked = 1;
04109 ast_mutex_unlock(&p->lock);
04110 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04111 }
04112
04113 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04114 {
04115 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04116 ast_mutex_lock(&p->lock);
04117 p->remotelyblocked = 0;
04118 ast_mutex_unlock(&p->lock);
04119 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04120 }
04121
04122 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04123 __attribute__((format (printf, 3, 0)));
04124 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04125 {
04126 #define CONTEXT_TAG "Context - "
04127 char logmsg[256];
04128 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04129 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04130 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04131 dahdi_r2_write_log(level, completemsg);
04132 #undef CONTEXT_TAG
04133 }
04134
04135 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04136 __attribute__((format (printf, 3, 0)));
04137 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04138 {
04139 #define CHAN_TAG "Chan "
04140 char logmsg[256];
04141 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04142 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04143 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04144 dahdi_r2_write_log(level, completemsg);
04145 }
04146
04147 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04148 {
04149 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04150
04151 if (p->immediate) {
04152 return 0;
04153 }
04154 p->exten[p->mfcr2_dnis_index] = digit;
04155 p->rdnis[p->mfcr2_dnis_index] = digit;
04156 p->mfcr2_dnis_index++;
04157 p->exten[p->mfcr2_dnis_index] = 0;
04158 p->rdnis[p->mfcr2_dnis_index] = 0;
04159
04160 if ((p->mfcr2_dnis_matched ||
04161 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04162 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04163 return 0;
04164 }
04165
04166 return 1;
04167 }
04168
04169 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04170 {
04171 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04172 p->cid_num[p->mfcr2_ani_index] = digit;
04173 p->cid_name[p->mfcr2_ani_index] = digit;
04174 p->mfcr2_ani_index++;
04175 p->cid_num[p->mfcr2_ani_index] = 0;
04176 p->cid_name[p->mfcr2_ani_index] = 0;
04177 }
04178
04179 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04180 {
04181 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04182 }
04183
04184 static openr2_event_interface_t dahdi_r2_event_iface = {
04185 .on_call_init = dahdi_r2_on_call_init,
04186 .on_call_offered = dahdi_r2_on_call_offered,
04187 .on_call_accepted = dahdi_r2_on_call_accepted,
04188 .on_call_answered = dahdi_r2_on_call_answered,
04189 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04190 .on_call_end = dahdi_r2_on_call_end,
04191 .on_call_read = dahdi_r2_on_call_read,
04192 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04193 .on_os_error = dahdi_r2_on_os_error,
04194 .on_protocol_error = dahdi_r2_on_protocol_error,
04195 .on_line_blocked = dahdi_r2_on_line_blocked,
04196 .on_line_idle = dahdi_r2_on_line_idle,
04197
04198 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04199 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04200 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04201
04202 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04203 };
04204
04205 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04206 {
04207 return AST_ALAW(sample);
04208 }
04209
04210 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04211 {
04212 return AST_LIN2A(sample);
04213 }
04214
04215 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04216 dahdi_r2_alaw_to_linear,
04217 dahdi_r2_linear_to_alaw
04218 };
04219
04220 #endif
04221
04222 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04223 {
04224 int tchan;
04225 int tinthreeway;
04226 struct ast_channel *towner;
04227
04228 ast_debug(1, "Swapping %d and %d\n", a, b);
04229
04230 tchan = p->subs[a].chan;
04231 towner = p->subs[a].owner;
04232 tinthreeway = p->subs[a].inthreeway;
04233
04234 p->subs[a].chan = p->subs[b].chan;
04235 p->subs[a].owner = p->subs[b].owner;
04236 p->subs[a].inthreeway = p->subs[b].inthreeway;
04237
04238 p->subs[b].chan = tchan;
04239 p->subs[b].owner = towner;
04240 p->subs[b].inthreeway = tinthreeway;
04241
04242 if (p->subs[a].owner)
04243 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04244 if (p->subs[b].owner)
04245 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04246 wakeup_sub(p, a);
04247 wakeup_sub(p, b);
04248 }
04249
04250 static int dahdi_open(char *fn)
04251 {
04252 int fd;
04253 int isnum;
04254 int chan = 0;
04255 int bs;
04256 int x;
04257 isnum = 1;
04258 for (x = 0; x < strlen(fn); x++) {
04259 if (!isdigit(fn[x])) {
04260 isnum = 0;
04261 break;
04262 }
04263 }
04264 if (isnum) {
04265 chan = atoi(fn);
04266 if (chan < 1) {
04267 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04268 return -1;
04269 }
04270 fn = "/dev/dahdi/channel";
04271 }
04272 fd = open(fn, O_RDWR | O_NONBLOCK);
04273 if (fd < 0) {
04274 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04275 return -1;
04276 }
04277 if (chan) {
04278 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04279 x = errno;
04280 close(fd);
04281 errno = x;
04282 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04283 return -1;
04284 }
04285 }
04286 bs = READ_SIZE;
04287 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04288 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04289 x = errno;
04290 close(fd);
04291 errno = x;
04292 return -1;
04293 }
04294 return fd;
04295 }
04296
04297 static void dahdi_close(int fd)
04298 {
04299 if (fd > 0)
04300 close(fd);
04301 }
04302
04303 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04304 {
04305 dahdi_close(chan_pvt->subs[sub_num].dfd);
04306 chan_pvt->subs[sub_num].dfd = -1;
04307 }
04308
04309 #if defined(HAVE_PRI)
04310 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04311 {
04312 dahdi_close(pri->pri.fds[fd_num]);
04313 pri->pri.fds[fd_num] = -1;
04314 }
04315 #endif
04316
04317 #if defined(HAVE_SS7)
04318 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04319 {
04320 dahdi_close(ss7->ss7.fds[fd_num]);
04321 ss7->ss7.fds[fd_num] = -1;
04322 }
04323 #endif
04324
04325 static int dahdi_setlinear(int dfd, int linear)
04326 {
04327 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04328 }
04329
04330
04331 static int alloc_sub(struct dahdi_pvt *p, int x)
04332 {
04333 struct dahdi_bufferinfo bi;
04334 int res;
04335 if (p->subs[x].dfd >= 0) {
04336 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04337 return -1;
04338 }
04339
04340 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04341 if (p->subs[x].dfd <= -1) {
04342 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04343 return -1;
04344 }
04345
04346 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04347 if (!res) {
04348 bi.txbufpolicy = p->buf_policy;
04349 bi.rxbufpolicy = p->buf_policy;
04350 bi.numbufs = p->buf_no;
04351 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04352 if (res < 0) {
04353 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04354 }
04355 } else
04356 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04357
04358 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04359 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04360 dahdi_close_sub(p, x);
04361 p->subs[x].dfd = -1;
04362 return -1;
04363 }
04364 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04365 return 0;
04366 }
04367
04368 static int unalloc_sub(struct dahdi_pvt *p, int x)
04369 {
04370 if (!x) {
04371 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04372 return -1;
04373 }
04374 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04375 dahdi_close_sub(p, x);
04376 p->subs[x].linear = 0;
04377 p->subs[x].chan = 0;
04378 p->subs[x].owner = NULL;
04379 p->subs[x].inthreeway = 0;
04380 p->polarity = POLARITY_IDLE;
04381 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04382 return 0;
04383 }
04384
04385 static int digit_to_dtmfindex(char digit)
04386 {
04387 if (isdigit(digit))
04388 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04389 else if (digit >= 'A' && digit <= 'D')
04390 return DAHDI_TONE_DTMF_A + (digit - 'A');
04391 else if (digit >= 'a' && digit <= 'd')
04392 return DAHDI_TONE_DTMF_A + (digit - 'a');
04393 else if (digit == '*')
04394 return DAHDI_TONE_DTMF_s;
04395 else if (digit == '#')
04396 return DAHDI_TONE_DTMF_p;
04397 else
04398 return -1;
04399 }
04400
04401 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04402 {
04403 struct dahdi_pvt *pvt;
04404 int idx;
04405 int dtmf = -1;
04406 int res;
04407
04408 pvt = chan->tech_pvt;
04409
04410 ast_mutex_lock(&pvt->lock);
04411
04412 idx = dahdi_get_index(chan, pvt, 0);
04413
04414 if ((idx != SUB_REAL) || !pvt->owner)
04415 goto out;
04416
04417 #ifdef HAVE_PRI
04418 switch (pvt->sig) {
04419 case SIG_PRI_LIB_HANDLE_CASES:
04420 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04421 if (!res)
04422 goto out;
04423 break;
04424 default:
04425 break;
04426 }
04427 #endif
04428 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04429 goto out;
04430
04431 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04432 struct dahdi_dialoperation zo = {
04433 .op = DAHDI_DIAL_OP_APPEND,
04434 };
04435
04436 zo.dialstr[0] = 'T';
04437 zo.dialstr[1] = digit;
04438 zo.dialstr[2] = '\0';
04439 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04440 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04441 else
04442 pvt->dialing = 1;
04443 } else {
04444 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04445 pvt->dialing = 1;
04446 pvt->begindigit = digit;
04447 }
04448
04449 out:
04450 ast_mutex_unlock(&pvt->lock);
04451
04452 return 0;
04453 }
04454
04455 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04456 {
04457 struct dahdi_pvt *pvt;
04458 int res = 0;
04459 int idx;
04460 int x;
04461
04462 pvt = chan->tech_pvt;
04463
04464 ast_mutex_lock(&pvt->lock);
04465
04466 idx = dahdi_get_index(chan, pvt, 0);
04467
04468 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04469 goto out;
04470
04471 #ifdef HAVE_PRI
04472
04473 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04474 goto out;
04475 }
04476 #endif
04477
04478 if (pvt->begindigit) {
04479 x = -1;
04480 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04481 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04482 pvt->dialing = 0;
04483 pvt->begindigit = 0;
04484 }
04485
04486 out:
04487 ast_mutex_unlock(&pvt->lock);
04488
04489 return res;
04490 }
04491
04492 static const char * const events[] = {
04493 "No event",
04494 "On hook",
04495 "Ring/Answered",
04496 "Wink/Flash",
04497 "Alarm",
04498 "No more alarm",
04499 "HDLC Abort",
04500 "HDLC Overrun",
04501 "HDLC Bad FCS",
04502 "Dial Complete",
04503 "Ringer On",
04504 "Ringer Off",
04505 "Hook Transition Complete",
04506 "Bits Changed",
04507 "Pulse Start",
04508 "Timer Expired",
04509 "Timer Ping",
04510 "Polarity Reversal",
04511 "Ring Begin",
04512 };
04513
04514 static struct {
04515 int alarm;
04516 char *name;
04517 } alarms[] = {
04518 { DAHDI_ALARM_RED, "Red Alarm" },
04519 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04520 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04521 { DAHDI_ALARM_RECOVER, "Recovering" },
04522 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04523 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04524 { DAHDI_ALARM_NONE, "None" },
04525 };
04526
04527 static char *alarm2str(int alm)
04528 {
04529 int x;
04530 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04531 if (alarms[x].alarm & alm)
04532 return alarms[x].name;
04533 }
04534 return alm ? "Unknown Alarm" : "No Alarm";
04535 }
04536
04537 static const char *event2str(int event)
04538 {
04539 static char buf[256];
04540 if ((event < (ARRAY_LEN(events))) && (event > -1))
04541 return events[event];
04542 sprintf(buf, "Event %d", event);
04543 return buf;
04544 }
04545
04546 static char *dahdi_sig2str(int sig)
04547 {
04548 static char buf[256];
04549 switch (sig) {
04550 case SIG_EM:
04551 return "E & M Immediate";
04552 case SIG_EMWINK:
04553 return "E & M Wink";
04554 case SIG_EM_E1:
04555 return "E & M E1";
04556 case SIG_FEATD:
04557 return "Feature Group D (DTMF)";
04558 case SIG_FEATDMF:
04559 return "Feature Group D (MF)";
04560 case SIG_FEATDMF_TA:
04561 return "Feature Groud D (MF) Tandem Access";
04562 case SIG_FEATB:
04563 return "Feature Group B (MF)";
04564 case SIG_E911:
04565 return "E911 (MF)";
04566 case SIG_FGC_CAMA:
04567 return "FGC/CAMA (Dialpulse)";
04568 case SIG_FGC_CAMAMF:
04569 return "FGC/CAMA (MF)";
04570 case SIG_FXSLS:
04571 return "FXS Loopstart";
04572 case SIG_FXSGS:
04573 return "FXS Groundstart";
04574 case SIG_FXSKS:
04575 return "FXS Kewlstart";
04576 case SIG_FXOLS:
04577 return "FXO Loopstart";
04578 case SIG_FXOGS:
04579 return "FXO Groundstart";
04580 case SIG_FXOKS:
04581 return "FXO Kewlstart";
04582 case SIG_PRI:
04583 return "ISDN PRI";
04584 case SIG_BRI:
04585 return "ISDN BRI Point to Point";
04586 case SIG_BRI_PTMP:
04587 return "ISDN BRI Point to MultiPoint";
04588 case SIG_SS7:
04589 return "SS7";
04590 case SIG_MFCR2:
04591 return "MFC/R2";
04592 case SIG_SF:
04593 return "SF (Tone) Immediate";
04594 case SIG_SFWINK:
04595 return "SF (Tone) Wink";
04596 case SIG_SF_FEATD:
04597 return "SF (Tone) with Feature Group D (DTMF)";
04598 case SIG_SF_FEATDMF:
04599 return "SF (Tone) with Feature Group D (MF)";
04600 case SIG_SF_FEATB:
04601 return "SF (Tone) with Feature Group B (MF)";
04602 case 0:
04603 return "Pseudo";
04604 default:
04605 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04606 return buf;
04607 }
04608 }
04609
04610 #define sig2str dahdi_sig2str
04611
04612 static int analog_lib_handles(int signalling, int radio, int oprmode)
04613 {
04614 switch (signalling) {
04615 case SIG_FXOLS:
04616 case SIG_FXOGS:
04617 case SIG_FXOKS:
04618 case SIG_FXSLS:
04619 case SIG_FXSGS:
04620 case SIG_FXSKS:
04621 case SIG_EMWINK:
04622 case SIG_EM:
04623 case SIG_EM_E1:
04624 case SIG_FEATD:
04625 case SIG_FEATDMF:
04626 case SIG_E911:
04627 case SIG_FGC_CAMA:
04628 case SIG_FGC_CAMAMF:
04629 case SIG_FEATB:
04630 case SIG_SFWINK:
04631 case SIG_SF:
04632 case SIG_SF_FEATD:
04633 case SIG_SF_FEATDMF:
04634 case SIG_FEATDMF_TA:
04635 case SIG_SF_FEATB:
04636 break;
04637 default:
04638
04639 return 0;
04640 }
04641
04642 if (radio)
04643 return 0;
04644
04645 if (oprmode)
04646 return 0;
04647
04648 return 1;
04649 }
04650
04651 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04652 {
04653
04654
04655 struct dahdi_confinfo zi;
04656
04657 memset(&zi, 0, sizeof(zi));
04658 zi.chan = 0;
04659
04660 if (slavechannel > 0) {
04661
04662 zi.confmode = DAHDI_CONF_DIGITALMON;
04663 zi.confno = slavechannel;
04664 } else {
04665 if (!idx) {
04666
04667 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04668 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04669 } else
04670 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04671 zi.confno = p->confno;
04672 }
04673 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04674 return 0;
04675 if (c->dfd < 0)
04676 return 0;
04677 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04678 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04679 return -1;
04680 }
04681 if (slavechannel < 1) {
04682 p->confno = zi.confno;
04683 }
04684 c->curconf = zi;
04685 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04686 return 0;
04687 }
04688
04689 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04690 {
04691
04692 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04693 return 1;
04694
04695 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04696 return 1;
04697 return 0;
04698 }
04699
04700 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04701 {
04702 struct dahdi_confinfo zi;
04703 if (
04704 (c->dfd < 0) ||
04705
04706 !isourconf(p, c)
04707
04708 ) return 0;
04709 memset(&zi, 0, sizeof(zi));
04710 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04711 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04712 return -1;
04713 }
04714 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04715 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04716 return 0;
04717 }
04718
04719 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04720 {
04721 int x;
04722 int useslavenative;
04723 struct dahdi_pvt *slave = NULL;
04724
04725 useslavenative = 1;
04726
04727 for (x = 0; x < 3; x++) {
04728
04729
04730 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04731 useslavenative = 0;
04732 }
04733
04734
04735 if (useslavenative) {
04736 for (x = 0; x < MAX_SLAVES; x++) {
04737 if (p->slaves[x]) {
04738 if (slave) {
04739
04740
04741 slave = NULL;
04742 useslavenative = 0;
04743 break;
04744 } else {
04745
04746 slave = p->slaves[x];
04747 }
04748 }
04749 }
04750 }
04751
04752 if (!slave)
04753 useslavenative = 0;
04754 else if (slave->law != p->law) {
04755 useslavenative = 0;
04756 slave = NULL;
04757 }
04758 if (out)
04759 *out = slave;
04760 return useslavenative;
04761 }
04762
04763 static int reset_conf(struct dahdi_pvt *p)
04764 {
04765 p->confno = -1;
04766 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04767 if (p->subs[SUB_REAL].dfd > -1) {
04768 struct dahdi_confinfo zi;
04769
04770 memset(&zi, 0, sizeof(zi));
04771 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04772 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04773 }
04774 return 0;
04775 }
04776
04777 static int update_conf(struct dahdi_pvt *p)
04778 {
04779 int needconf = 0;
04780 int x;
04781 int useslavenative;
04782 struct dahdi_pvt *slave = NULL;
04783
04784 useslavenative = isslavenative(p, &slave);
04785
04786 for (x = 0; x < 3; x++) {
04787
04788 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04789 conf_add(p, &p->subs[x], x, 0);
04790 needconf++;
04791 } else {
04792 conf_del(p, &p->subs[x], x);
04793 }
04794 }
04795
04796
04797 for (x = 0; x < MAX_SLAVES; x++) {
04798 if (p->slaves[x]) {
04799 if (useslavenative)
04800 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04801 else {
04802 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04803 needconf++;
04804 }
04805 }
04806 }
04807
04808 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04809 if (useslavenative)
04810 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04811 else {
04812 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04813 needconf++;
04814 }
04815 }
04816
04817 if (p->master) {
04818 if (isslavenative(p->master, NULL)) {
04819 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04820 } else {
04821 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04822 }
04823 }
04824 if (!needconf) {
04825
04826
04827 p->confno = -1;
04828 }
04829 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04830 return 0;
04831 }
04832
04833 static void dahdi_enable_ec(struct dahdi_pvt *p)
04834 {
04835 int res;
04836 if (!p)
04837 return;
04838 if (p->echocanon) {
04839 ast_debug(1, "Echo cancellation already on\n");
04840 return;
04841 }
04842 if (p->digital) {
04843 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04844 return;
04845 }
04846 if (p->echocancel.head.tap_length) {
04847 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04848 switch (p->sig) {
04849 #if defined(HAVE_PRI)
04850 case SIG_PRI_LIB_HANDLE_CASES:
04851 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04852
04853
04854
04855
04856 return;
04857 }
04858
04859 #endif
04860 #if defined(HAVE_SS7)
04861 case SIG_SS7:
04862 #endif
04863 {
04864 int x = 1;
04865
04866 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04867 if (res)
04868 ast_log(LOG_WARNING,
04869 "Unable to enable audio mode on channel %d (%s)\n",
04870 p->channel, strerror(errno));
04871 }
04872 break;
04873 default:
04874 break;
04875 }
04876 #endif
04877 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04878 if (res) {
04879 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04880 } else {
04881 p->echocanon = 1;
04882 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04883 }
04884 } else
04885 ast_debug(1, "No echo cancellation requested\n");
04886 }
04887
04888 static void dahdi_train_ec(struct dahdi_pvt *p)
04889 {
04890 int x;
04891 int res;
04892
04893 if (p && p->echocanon && p->echotraining) {
04894 x = p->echotraining;
04895 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04896 if (res)
04897 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04898 else
04899 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04900 } else {
04901 ast_debug(1, "No echo training requested\n");
04902 }
04903 }
04904
04905 static void dahdi_disable_ec(struct dahdi_pvt *p)
04906 {
04907 int res;
04908
04909 if (p->echocanon) {
04910 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04911
04912 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04913
04914 if (res)
04915 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04916 else
04917 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04918 }
04919
04920 p->echocanon = 0;
04921 }
04922
04923
04924 static int drc_sample(int sample, float drc)
04925 {
04926 float neg;
04927 float shallow, steep;
04928 float max = SHRT_MAX;
04929
04930 neg = (sample < 0 ? -1 : 1);
04931 steep = drc*sample;
04932 shallow = neg*(max-max/drc)+(float)sample/drc;
04933 if (abs(steep) < abs(shallow)) {
04934 sample = steep;
04935 }
04936 else {
04937 sample = shallow;
04938 }
04939
04940 return sample;
04941 }
04942
04943
04944 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04945 {
04946 int j;
04947 int k;
04948
04949 float linear_gain = pow(10.0, gain / 20.0);
04950
04951 switch (law) {
04952 case DAHDI_LAW_ALAW:
04953 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04954 if (gain || drc) {
04955 k = AST_ALAW(j);
04956 if (drc) {
04957 k = drc_sample(k, drc);
04958 }
04959 k = (float)k*linear_gain;
04960 if (k > 32767) k = 32767;
04961 if (k < -32767) k = -32767;
04962 g->txgain[j] = AST_LIN2A(k);
04963 } else {
04964 g->txgain[j] = j;
04965 }
04966 }
04967 break;
04968 case DAHDI_LAW_MULAW:
04969 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04970 if (gain || drc) {
04971 k = AST_MULAW(j);
04972 if (drc) {
04973 k = drc_sample(k, drc);
04974 }
04975 k = (float)k*linear_gain;
04976 if (k > 32767) k = 32767;
04977 if (k < -32767) k = -32767;
04978 g->txgain[j] = AST_LIN2MU(k);
04979
04980 } else {
04981 g->txgain[j] = j;
04982 }
04983 }
04984 break;
04985 }
04986 }
04987
04988 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04989 {
04990 int j;
04991 int k;
04992 float linear_gain = pow(10.0, gain / 20.0);
04993
04994 switch (law) {
04995 case DAHDI_LAW_ALAW:
04996 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04997 if (gain || drc) {
04998 k = AST_ALAW(j);
04999 if (drc) {
05000 k = drc_sample(k, drc);
05001 }
05002 k = (float)k*linear_gain;
05003 if (k > 32767) k = 32767;
05004 if (k < -32767) k = -32767;
05005 g->rxgain[j] = AST_LIN2A(k);
05006 } else {
05007 g->rxgain[j] = j;
05008 }
05009 }
05010 break;
05011 case DAHDI_LAW_MULAW:
05012 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05013 if (gain || drc) {
05014 k = AST_MULAW(j);
05015 if (drc) {
05016 k = drc_sample(k, drc);
05017 }
05018 k = (float)k*linear_gain;
05019 if (k > 32767) k = 32767;
05020 if (k < -32767) k = -32767;
05021 g->rxgain[j] = AST_LIN2MU(k);
05022 } else {
05023 g->rxgain[j] = j;
05024 }
05025 }
05026 break;
05027 }
05028 }
05029
05030 static int set_actual_txgain(int fd, float gain, float drc, int law)
05031 {
05032 struct dahdi_gains g;
05033 int res;
05034
05035 memset(&g, 0, sizeof(g));
05036 res = ioctl(fd, DAHDI_GETGAINS, &g);
05037 if (res) {
05038 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05039 return res;
05040 }
05041
05042 fill_txgain(&g, gain, drc, law);
05043
05044 return ioctl(fd, DAHDI_SETGAINS, &g);
05045 }
05046
05047 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05048 {
05049 struct dahdi_gains g;
05050 int res;
05051
05052 memset(&g, 0, sizeof(g));
05053 res = ioctl(fd, DAHDI_GETGAINS, &g);
05054 if (res) {
05055 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05056 return res;
05057 }
05058
05059 fill_rxgain(&g, gain, drc, law);
05060
05061 return ioctl(fd, DAHDI_SETGAINS, &g);
05062 }
05063
05064 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05065 {
05066 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05067 }
05068
05069 static int bump_gains(struct dahdi_pvt *p)
05070 {
05071 int res;
05072
05073
05074 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05075 if (res) {
05076 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05077 return -1;
05078 }
05079
05080 return 0;
05081 }
05082
05083 static int restore_gains(struct dahdi_pvt *p)
05084 {
05085 int res;
05086
05087 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05088 if (res) {
05089 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05090 return -1;
05091 }
05092
05093 return 0;
05094 }
05095
05096 static inline int dahdi_set_hook(int fd, int hs)
05097 {
05098 int x, res;
05099
05100 x = hs;
05101 res = ioctl(fd, DAHDI_HOOK, &x);
05102
05103 if (res < 0) {
05104 if (errno == EINPROGRESS)
05105 return 0;
05106 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05107
05108 }
05109
05110 return res;
05111 }
05112
05113 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05114 {
05115 int x, res;
05116
05117 x = muted;
05118 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05119 switch (p->sig) {
05120 #if defined(HAVE_PRI)
05121 case SIG_PRI_LIB_HANDLE_CASES:
05122 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05123
05124 break;
05125 }
05126
05127 #endif
05128 #if defined(HAVE_SS7)
05129 case SIG_SS7:
05130 #endif
05131 {
05132 int y = 1;
05133
05134 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05135 if (res)
05136 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05137 p->channel, strerror(errno));
05138 }
05139 break;
05140 default:
05141 break;
05142 }
05143 #endif
05144 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05145 if (res < 0)
05146 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05147 return res;
05148 }
05149
05150 static int save_conference(struct dahdi_pvt *p)
05151 {
05152 struct dahdi_confinfo c;
05153 int res;
05154 if (p->saveconf.confmode) {
05155 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05156 return -1;
05157 }
05158 p->saveconf.chan = 0;
05159 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05160 if (res) {
05161 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05162 p->saveconf.confmode = 0;
05163 return -1;
05164 }
05165 memset(&c, 0, sizeof(c));
05166 c.confmode = DAHDI_CONF_NORMAL;
05167 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05168 if (res) {
05169 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05170 return -1;
05171 }
05172 ast_debug(1, "Disabled conferencing\n");
05173 return 0;
05174 }
05175
05176 static int restore_conference(struct dahdi_pvt *p)
05177 {
05178 int res;
05179 if (p->saveconf.confmode) {
05180 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05181 p->saveconf.confmode = 0;
05182 if (res) {
05183 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05184 return -1;
05185 }
05186 ast_debug(1, "Restored conferencing\n");
05187 }
05188 return 0;
05189 }
05190
05191 static int send_cwcidspill(struct dahdi_pvt *p)
05192 {
05193 p->callwaitcas = 0;
05194 p->cidcwexpire = 0;
05195 p->cid_suppress_expire = 0;
05196 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05197 return -1;
05198 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05199
05200 p->cidlen += READ_SIZE * 4;
05201 p->cidpos = 0;
05202 send_callerid(p);
05203 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05204 return 0;
05205 }
05206
05207 static int has_voicemail(struct dahdi_pvt *p)
05208 {
05209 int new_msgs;
05210 struct ast_event *event;
05211 char *mailbox, *context;
05212
05213 mailbox = context = ast_strdupa(p->mailbox);
05214 strsep(&context, "@");
05215 if (ast_strlen_zero(context))
05216 context = "default";
05217
05218 event = ast_event_get_cached(AST_EVENT_MWI,
05219 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05220 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05221 AST_EVENT_IE_END);
05222
05223 if (event) {
05224 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05225 ast_event_destroy(event);
05226 } else
05227 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05228
05229 return new_msgs;
05230 }
05231
05232
05233
05234 static int send_callerid(struct dahdi_pvt *p)
05235 {
05236
05237 int res;
05238
05239 if (p->subs[SUB_REAL].linear) {
05240 p->subs[SUB_REAL].linear = 0;
05241 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05242 }
05243 while (p->cidpos < p->cidlen) {
05244 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05245 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05246 if (res < 0) {
05247 if (errno == EAGAIN)
05248 return 0;
05249 else {
05250 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05251 return -1;
05252 }
05253 }
05254 if (!res)
05255 return 0;
05256 p->cidpos += res;
05257 }
05258 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05259 ast_free(p->cidspill);
05260 p->cidspill = NULL;
05261 if (p->callwaitcas) {
05262
05263 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05264 p->cid_suppress_expire = p->cidcwexpire;
05265 } else
05266 restore_conference(p);
05267 return 0;
05268 }
05269
05270 static int dahdi_callwait(struct ast_channel *ast)
05271 {
05272 struct dahdi_pvt *p = ast->tech_pvt;
05273 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05274 if (p->cidspill) {
05275 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05276 ast_free(p->cidspill);
05277 }
05278
05279
05280
05281
05282
05283 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05284 return -1;
05285 save_conference(p);
05286
05287 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05288 if (!p->callwaitrings && p->callwaitingcallerid) {
05289 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05290 p->callwaitcas = 1;
05291 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05292 } else {
05293 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05294 p->callwaitcas = 0;
05295 p->cidlen = 2400 + READ_SIZE * 4;
05296 }
05297 p->cidpos = 0;
05298 send_callerid(p);
05299
05300 return 0;
05301 }
05302
05303 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05304 {
05305 struct dahdi_pvt *p = ast->tech_pvt;
05306 int x, res, mysig;
05307 char dest[256];
05308
05309 ast_mutex_lock(&p->lock);
05310 ast_copy_string(dest, rdest, sizeof(dest));
05311 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05312 if ((ast->_state == AST_STATE_BUSY)) {
05313 p->subs[SUB_REAL].needbusy = 1;
05314 ast_mutex_unlock(&p->lock);
05315 return 0;
05316 }
05317 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05318 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05319 ast_mutex_unlock(&p->lock);
05320 return -1;
05321 }
05322 p->waitingfordt.tv_sec = 0;
05323 p->dialednone = 0;
05324 if ((p->radio || (p->oprmode < 0)))
05325 {
05326
05327 ast_setstate(ast, AST_STATE_UP);
05328 ast_mutex_unlock(&p->lock);
05329 return 0;
05330 }
05331 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05332 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05333 if (res)
05334 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05335 p->outgoing = 1;
05336
05337 if (IS_DIGITAL(ast->transfercapability)){
05338 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05339 } else {
05340 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05341 }
05342
05343 #ifdef HAVE_PRI
05344 if (dahdi_sig_pri_lib_handles(p->sig)) {
05345 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05346 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05347 ast_mutex_unlock(&p->lock);
05348 return res;
05349 }
05350 #endif
05351
05352 #if defined(HAVE_SS7)
05353 if (p->sig == SIG_SS7) {
05354 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05355 ast_mutex_unlock(&p->lock);
05356 return res;
05357 }
05358 #endif
05359
05360
05361 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05362 p->callwaitrings = 0;
05363 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05364 ast_mutex_unlock(&p->lock);
05365 return res;
05366 }
05367
05368 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05369 switch (mysig) {
05370 case 0:
05371
05372 ast_setstate(ast, AST_STATE_UP);
05373 break;
05374 case SIG_MFCR2:
05375 break;
05376 default:
05377 ast_debug(1, "not yet implemented\n");
05378 ast_mutex_unlock(&p->lock);
05379 return -1;
05380 }
05381
05382 #ifdef HAVE_OPENR2
05383 if (p->mfcr2) {
05384 openr2_calling_party_category_t chancat;
05385 int callres = 0;
05386 char *c, *l;
05387
05388
05389 p->dialdest[0] = '\0';
05390
05391 c = strchr(dest, '/');
05392 if (c) {
05393 c++;
05394 } else {
05395 c = "";
05396 }
05397 if (!p->hidecallerid) {
05398 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05399 } else {
05400 l = NULL;
05401 }
05402 if (strlen(c) < p->stripmsd) {
05403 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05404 ast_mutex_unlock(&p->lock);
05405 return -1;
05406 }
05407 p->dialing = 1;
05408 chancat = dahdi_r2_get_channel_category(ast);
05409 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05410 if (-1 == callres) {
05411 ast_mutex_unlock(&p->lock);
05412 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05413 return -1;
05414 }
05415 p->mfcr2_call_accepted = 0;
05416 p->mfcr2_progress = 0;
05417 ast_setstate(ast, AST_STATE_DIALING);
05418 }
05419 #endif
05420 ast_mutex_unlock(&p->lock);
05421 return 0;
05422 }
05423
05424
05425
05426
05427
05428
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05440 {
05441 struct dahdi_pvt *cur;
05442
05443 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05444
05445
05446 for (cur = iflist; cur; cur = cur->next) {
05447 if (pvt->channel < cur->channel) {
05448
05449 pvt->prev = cur->prev;
05450 pvt->next = cur;
05451 if (cur->prev) {
05452
05453 cur->prev->next = pvt;
05454 } else {
05455
05456 iflist = pvt;
05457 }
05458 cur->prev = pvt;
05459 return;
05460 }
05461 }
05462
05463
05464 pvt->prev = ifend;
05465 pvt->next = NULL;
05466 if (ifend) {
05467 ifend->next = pvt;
05468 }
05469 ifend = pvt;
05470 if (!iflist) {
05471
05472 iflist = pvt;
05473 }
05474 }
05475
05476
05477
05478
05479
05480
05481
05482
05483
05484
05485
05486
05487
05488
05489 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05490 {
05491
05492 if (pvt->prev) {
05493 pvt->prev->next = pvt->next;
05494 } else if (iflist == pvt) {
05495
05496 iflist = pvt->next;
05497 }
05498
05499
05500 if (pvt->next) {
05501 pvt->next->prev = pvt->prev;
05502 } else if (ifend == pvt) {
05503
05504 ifend = pvt->prev;
05505 }
05506
05507
05508 pvt->which_iflist = DAHDI_IFLIST_NONE;
05509 pvt->prev = NULL;
05510 pvt->next = NULL;
05511 }
05512
05513 #if defined(HAVE_PRI)
05514
05515
05516
05517
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05531 {
05532 struct dahdi_pvt *cur;
05533
05534 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05535
05536
05537 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05538 if (pvt->channel < cur->channel) {
05539
05540 pvt->prev = cur->prev;
05541 pvt->next = cur;
05542 if (cur->prev) {
05543
05544 cur->prev->next = pvt;
05545 } else {
05546
05547 pri->no_b_chan_iflist = pvt;
05548 }
05549 cur->prev = pvt;
05550 return;
05551 }
05552 }
05553
05554
05555 pvt->prev = pri->no_b_chan_end;
05556 pvt->next = NULL;
05557 if (pri->no_b_chan_end) {
05558 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05559 }
05560 pri->no_b_chan_end = pvt;
05561 if (!pri->no_b_chan_iflist) {
05562
05563 pri->no_b_chan_iflist = pvt;
05564 }
05565 }
05566 #endif
05567
05568 #if defined(HAVE_PRI)
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05584 {
05585
05586 if (pvt->prev) {
05587 pvt->prev->next = pvt->next;
05588 } else if (pri->no_b_chan_iflist == pvt) {
05589
05590 pri->no_b_chan_iflist = pvt->next;
05591 }
05592
05593
05594 if (pvt->next) {
05595 pvt->next->prev = pvt->prev;
05596 } else if (pri->no_b_chan_end == pvt) {
05597
05598 pri->no_b_chan_end = pvt->prev;
05599 }
05600
05601
05602 pvt->which_iflist = DAHDI_IFLIST_NONE;
05603 pvt->prev = NULL;
05604 pvt->next = NULL;
05605 }
05606 #endif
05607
05608 #if defined(HAVE_PRI)
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05619 {
05620 unsigned idx;
05621 struct sig_pri_span *pri;
05622
05623 pri = pvt->pri;
05624 if (!pri) {
05625
05626 return;
05627 }
05628 ast_mutex_lock(&pri->lock);
05629 for (idx = 0; idx < pri->numchans; ++idx) {
05630 if (pri->pvts[idx] == pvt->sig_pvt) {
05631 pri->pvts[idx] = NULL;
05632 ast_mutex_unlock(&pri->lock);
05633 return;
05634 }
05635 }
05636 ast_mutex_unlock(&pri->lock);
05637 }
05638 #endif
05639
05640 #if defined(HAVE_SS7)
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05651 {
05652 unsigned idx;
05653 struct sig_ss7_linkset *ss7;
05654
05655 ss7 = pvt->ss7;
05656 if (!ss7) {
05657
05658 return;
05659 }
05660 ast_mutex_lock(&ss7->lock);
05661 for (idx = 0; idx < ss7->numchans; ++idx) {
05662 if (ss7->pvts[idx] == pvt->sig_pvt) {
05663 ss7->pvts[idx] = NULL;
05664 ast_mutex_unlock(&ss7->lock);
05665 return;
05666 }
05667 }
05668 ast_mutex_unlock(&ss7->lock);
05669 }
05670 #endif
05671
05672 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05673 {
05674 if (cur->next && cur->next->span == cur->span) {
05675 return cur->next;
05676 } else if (cur->prev && cur->prev->span == cur->span) {
05677 return cur->prev;
05678 }
05679
05680 return NULL;
05681 }
05682
05683 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05684 {
05685 struct dahdi_pvt *p = pvt;
05686
05687 if (p->manages_span_alarms) {
05688 struct dahdi_pvt *next = find_next_iface_in_span(p);
05689 if (next) {
05690 next->manages_span_alarms = 1;
05691 }
05692 }
05693
05694
05695 #if defined(HAVE_PRI)
05696 dahdi_unlink_pri_pvt(p);
05697 #endif
05698 #if defined(HAVE_SS7)
05699 dahdi_unlink_ss7_pvt(p);
05700 #endif
05701 switch (pvt->which_iflist) {
05702 case DAHDI_IFLIST_NONE:
05703 break;
05704 case DAHDI_IFLIST_MAIN:
05705 dahdi_iflist_extract(p);
05706 break;
05707 #if defined(HAVE_PRI)
05708 case DAHDI_IFLIST_NO_B_CHAN:
05709 if (p->pri) {
05710 dahdi_nobch_extract(p->pri, p);
05711 }
05712 break;
05713 #endif
05714 }
05715
05716 if (p->sig_pvt) {
05717 if (analog_lib_handles(p->sig, 0, 0)) {
05718 analog_delete(p->sig_pvt);
05719 }
05720 switch (p->sig) {
05721 #if defined(HAVE_PRI)
05722 case SIG_PRI_LIB_HANDLE_CASES:
05723 sig_pri_chan_delete(p->sig_pvt);
05724 break;
05725 #endif
05726 #if defined(HAVE_SS7)
05727 case SIG_SS7:
05728 sig_ss7_chan_delete(p->sig_pvt);
05729 break;
05730 #endif
05731 default:
05732 break;
05733 }
05734 }
05735 ast_free(p->cidspill);
05736 if (p->use_smdi)
05737 ast_smdi_interface_unref(p->smdi_iface);
05738 if (p->mwi_event_sub)
05739 ast_event_unsubscribe(p->mwi_event_sub);
05740 if (p->vars) {
05741 ast_variables_destroy(p->vars);
05742 }
05743 if (p->cc_params) {
05744 ast_cc_config_params_destroy(p->cc_params);
05745 }
05746 ast_mutex_destroy(&p->lock);
05747 dahdi_close_sub(p, SUB_REAL);
05748 if (p->owner)
05749 p->owner->tech_pvt = NULL;
05750 ast_free(p);
05751 }
05752
05753 static void destroy_channel(struct dahdi_pvt *cur, int now)
05754 {
05755 int i;
05756
05757 if (!now) {
05758
05759 if (cur->owner) {
05760 return;
05761 }
05762 for (i = 0; i < 3; i++) {
05763 if (cur->subs[i].owner) {
05764 return;
05765 }
05766 }
05767 }
05768 destroy_dahdi_pvt(cur);
05769 }
05770
05771 static void destroy_all_channels(void)
05772 {
05773 int chan;
05774 #if defined(HAVE_PRI)
05775 unsigned span;
05776 struct sig_pri_span *pri;
05777 #endif
05778 struct dahdi_pvt *p;
05779
05780 while (num_restart_pending) {
05781 usleep(1);
05782 }
05783
05784 ast_mutex_lock(&iflock);
05785
05786 while (iflist) {
05787 p = iflist;
05788
05789 chan = p->channel;
05790 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05791 {
05792 char db_chan_name[20];
05793 char db_answer[5];
05794 char state;
05795 int why = -1;
05796
05797 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05798 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05799 sscanf(db_answer, "%1c:%30d", &state, &why);
05800 }
05801 if (!why) {
05802
05803 ast_db_del(db_chan_name, SRVST_DBKEY);
05804 }
05805 }
05806 #endif
05807
05808 destroy_dahdi_pvt(p);
05809 ast_verb(3, "Unregistered channel %d\n", chan);
05810 }
05811 ifcount = 0;
05812 ast_mutex_unlock(&iflock);
05813
05814 #if defined(HAVE_PRI)
05815
05816 for (span = 0; span < NUM_SPANS; ++span) {
05817 if (!pris[span].dchannels[0]) {
05818 break;
05819 }
05820 pri = &pris[span].pri;
05821 ast_mutex_lock(&pri->lock);
05822 while (pri->no_b_chan_iflist) {
05823 p = pri->no_b_chan_iflist;
05824
05825
05826 destroy_dahdi_pvt(p);
05827 }
05828 ast_mutex_unlock(&pri->lock);
05829 }
05830 #endif
05831 }
05832
05833 #if defined(HAVE_PRI)
05834 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05835
05836 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05837 {
05838
05839 struct dahdi_pvt *p;
05840
05841 if (ast_strlen_zero(digits)) {
05842 ast_debug(1, "No digit string sent to application!\n");
05843 return -1;
05844 }
05845
05846 p = (struct dahdi_pvt *)chan->tech_pvt;
05847
05848 if (!p) {
05849 ast_debug(1, "Unable to find technology private\n");
05850 return -1;
05851 }
05852
05853 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05854
05855 return 0;
05856 }
05857 #endif
05858
05859 #if defined(HAVE_PRI)
05860 #if defined(HAVE_PRI_PROG_W_CAUSE)
05861 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05862
05863 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05864 {
05865
05866 struct dahdi_pvt *pvt;
05867 char *parse;
05868 int res = -1;
05869 AST_DECLARE_APP_ARGS(args,
05870 AST_APP_ARG(destination);
05871 AST_APP_ARG(original);
05872 AST_APP_ARG(reason);
05873 );
05874
05875 if (ast_strlen_zero(data)) {
05876 ast_log(LOG_DEBUG, "No data sent to application!\n");
05877 return -1;
05878 }
05879 if (chan->tech != &dahdi_tech) {
05880 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05881 return -1;
05882 }
05883 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05884 if (!pvt) {
05885 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05886 return -1;
05887 }
05888 switch (pvt->sig) {
05889 case SIG_PRI_LIB_HANDLE_CASES:
05890 break;
05891 default:
05892 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05893 chan->name);
05894 return -1;
05895 }
05896
05897 parse = ast_strdupa(data);
05898 AST_STANDARD_APP_ARGS(args, parse);
05899
05900 if (ast_strlen_zero(args.destination)) {
05901 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05902 return -1;
05903 }
05904
05905 if (ast_strlen_zero(args.original)) {
05906 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05907 args.original = NULL;
05908 }
05909
05910 if (ast_strlen_zero(args.reason)) {
05911 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05912 args.reason = NULL;
05913 }
05914
05915 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05916 args.original, args.reason);
05917
05918 return res;
05919 }
05920 #endif
05921 #endif
05922
05923 #if defined(HAVE_OPENR2)
05924 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05925
05926 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05927 {
05928
05929 openr2_call_mode_t accept_mode;
05930 int res, timeout, maxloops;
05931 struct ast_frame *f;
05932 struct dahdi_pvt *p;
05933 char *parse;
05934 AST_DECLARE_APP_ARGS(args,
05935 AST_APP_ARG(charge);
05936 );
05937
05938 if (ast_strlen_zero(data)) {
05939 ast_log(LOG_DEBUG, "No data sent to application!\n");
05940 return -1;
05941 }
05942
05943 if (chan->tech != &dahdi_tech) {
05944 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05945 return -1;
05946 }
05947
05948 p = (struct dahdi_pvt *)chan->tech_pvt;
05949 if (!p) {
05950 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05951 return -1;
05952 }
05953
05954 parse = ast_strdupa(data);
05955 AST_STANDARD_APP_ARGS(args, parse);
05956
05957 if (ast_strlen_zero(args.charge)) {
05958 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05959 return -1;
05960 }
05961
05962 ast_mutex_lock(&p->lock);
05963 if (!p->mfcr2 || !p->mfcr2call) {
05964 ast_mutex_unlock(&p->lock);
05965 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05966 return -1;
05967 }
05968
05969 if (p->mfcr2_call_accepted) {
05970 ast_mutex_unlock(&p->lock);
05971 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05972 return 0;
05973 }
05974 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05975 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05976 ast_mutex_unlock(&p->lock);
05977 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05978 return -1;
05979 }
05980 ast_mutex_unlock(&p->lock);
05981
05982 res = 0;
05983 timeout = 100;
05984 maxloops = 50;
05985
05986 while (maxloops > 0) {
05987 maxloops--;
05988 if (ast_check_hangup(chan)) {
05989 break;
05990 }
05991 res = ast_waitfor(chan, timeout);
05992 if (res < 0) {
05993 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05994 res = -1;
05995 break;
05996 }
05997 if (res == 0) {
05998 continue;
05999 }
06000 f = ast_read(chan);
06001 if (!f) {
06002 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06003 res = -1;
06004 break;
06005 }
06006 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06007 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06008 ast_frfree(f);
06009 res = -1;
06010 break;
06011 }
06012 ast_frfree(f);
06013 ast_mutex_lock(&p->lock);
06014 if (p->mfcr2_call_accepted) {
06015 ast_mutex_unlock(&p->lock);
06016 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06017 break;
06018 }
06019 ast_mutex_unlock(&p->lock);
06020 }
06021 if (res == -1) {
06022 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06023 }
06024 return res;
06025 }
06026
06027 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06028 {
06029 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06030 switch (cause) {
06031 case AST_CAUSE_USER_BUSY:
06032 case AST_CAUSE_CALL_REJECTED:
06033 case AST_CAUSE_INTERWORKING:
06034 r2cause = OR2_CAUSE_BUSY_NUMBER;
06035 break;
06036
06037 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06038 case AST_CAUSE_SWITCH_CONGESTION:
06039 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06040 break;
06041
06042 case AST_CAUSE_UNALLOCATED:
06043 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06044 break;
06045
06046 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06047 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06048 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06049 break;
06050
06051 case AST_CAUSE_NO_ANSWER:
06052 case AST_CAUSE_NO_USER_RESPONSE:
06053 r2cause = OR2_CAUSE_NO_ANSWER;
06054 break;
06055
06056 default:
06057 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06058 break;
06059 }
06060 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06061 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06062 return r2cause;
06063 }
06064 #endif
06065
06066 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06067 {
06068 if (p->bufferoverrideinuse) {
06069
06070 struct dahdi_bufferinfo bi = {
06071 .txbufpolicy = p->buf_policy,
06072 .rxbufpolicy = p->buf_policy,
06073 .bufsize = p->bufsize,
06074 .numbufs = p->buf_no
06075 };
06076 int bpres;
06077
06078 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06079 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06080 }
06081 p->bufferoverrideinuse = 0;
06082 return bpres;
06083 }
06084
06085 return -1;
06086 }
06087
06088 static int dahdi_hangup(struct ast_channel *ast)
06089 {
06090 int res = 0;
06091 int idx,x;
06092 int law;
06093
06094 struct dahdi_pvt *p = ast->tech_pvt;
06095 struct dahdi_params par;
06096
06097 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06098 if (!ast->tech_pvt) {
06099 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06100 return 0;
06101 }
06102
06103 ast_mutex_lock(&p->lock);
06104 p->exten[0] = '\0';
06105 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06106 dahdi_confmute(p, 0);
06107 restore_gains(p);
06108 p->ignoredtmf = 0;
06109 p->waitingfordt.tv_sec = 0;
06110
06111 res = analog_hangup(p->sig_pvt, ast);
06112 revert_fax_buffers(p, ast);
06113
06114 goto hangup_out;
06115 } else {
06116 p->cid_num[0] = '\0';
06117 p->cid_name[0] = '\0';
06118 p->cid_subaddr[0] = '\0';
06119 }
06120
06121 #if defined(HAVE_PRI)
06122 if (dahdi_sig_pri_lib_handles(p->sig)) {
06123 x = 1;
06124 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06125
06126 dahdi_confmute(p, 0);
06127 p->muting = 0;
06128 restore_gains(p);
06129 if (p->dsp) {
06130 ast_dsp_free(p->dsp);
06131 p->dsp = NULL;
06132 }
06133 p->ignoredtmf = 0;
06134
06135
06136 p->subs[SUB_REAL].owner = NULL;
06137 p->subs[SUB_REAL].needbusy = 0;
06138 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06139
06140 p->owner = NULL;
06141 p->cid_tag[0] = '\0';
06142 p->ringt = 0;
06143 p->distinctivering = 0;
06144 p->confirmanswer = 0;
06145 p->outgoing = 0;
06146 p->digital = 0;
06147 p->faxhandled = 0;
06148 p->pulsedial = 0;
06149
06150 revert_fax_buffers(p, ast);
06151
06152 p->law = p->law_default;
06153 law = p->law_default;
06154 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06155 if (res < 0) {
06156 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06157 p->channel, strerror(errno));
06158 }
06159
06160 sig_pri_hangup(p->sig_pvt, ast);
06161
06162 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06163 dahdi_disable_ec(p);
06164
06165 x = 0;
06166 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06167 p->didtdd = 0;
06168
06169 p->rdnis[0] = '\0';
06170 update_conf(p);
06171 reset_conf(p);
06172
06173
06174 x = 0;
06175 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06176
06177 if (num_restart_pending == 0) {
06178 restart_monitor();
06179 }
06180 goto hangup_out;
06181 }
06182 #endif
06183
06184 #if defined(HAVE_SS7)
06185 if (p->sig == SIG_SS7) {
06186 x = 1;
06187 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06188
06189 dahdi_confmute(p, 0);
06190 p->muting = 0;
06191 restore_gains(p);
06192 if (p->dsp) {
06193 ast_dsp_free(p->dsp);
06194 p->dsp = NULL;
06195 }
06196 p->ignoredtmf = 0;
06197
06198
06199 p->subs[SUB_REAL].owner = NULL;
06200 p->subs[SUB_REAL].needbusy = 0;
06201 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06202
06203 p->owner = NULL;
06204 p->ringt = 0;
06205 p->distinctivering = 0;
06206 p->confirmanswer = 0;
06207 p->outgoing = 0;
06208 p->digital = 0;
06209 p->faxhandled = 0;
06210 p->pulsedial = 0;
06211
06212 revert_fax_buffers(p, ast);
06213
06214 p->law = p->law_default;
06215 law = p->law_default;
06216 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06217 if (res < 0) {
06218 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06219 p->channel, strerror(errno));
06220 }
06221
06222 sig_ss7_hangup(p->sig_pvt, ast);
06223
06224 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06225 dahdi_disable_ec(p);
06226
06227 x = 0;
06228 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06229 p->didtdd = 0;
06230
06231 update_conf(p);
06232 reset_conf(p);
06233
06234
06235 x = 0;
06236 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06237
06238 if (num_restart_pending == 0) {
06239 restart_monitor();
06240 }
06241 goto hangup_out;
06242 }
06243 #endif
06244
06245 idx = dahdi_get_index(ast, p, 1);
06246
06247 dahdi_confmute(p, 0);
06248 p->muting = 0;
06249 restore_gains(p);
06250 if (p->origcid_num) {
06251 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06252 ast_free(p->origcid_num);
06253 p->origcid_num = NULL;
06254 }
06255 if (p->origcid_name) {
06256 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06257 ast_free(p->origcid_name);
06258 p->origcid_name = NULL;
06259 }
06260 if (p->dsp)
06261 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06262
06263 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06264 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06265 p->ignoredtmf = 0;
06266
06267 if (idx > -1) {
06268
06269 p->subs[idx].owner = NULL;
06270 p->subs[idx].needanswer = 0;
06271 p->subs[idx].needflash = 0;
06272 p->subs[idx].needringing = 0;
06273 p->subs[idx].needbusy = 0;
06274 p->subs[idx].needcongestion = 0;
06275 p->subs[idx].linear = 0;
06276 p->polarity = POLARITY_IDLE;
06277 dahdi_setlinear(p->subs[idx].dfd, 0);
06278 if (idx == SUB_REAL) {
06279 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06280 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06281 if (p->subs[SUB_CALLWAIT].inthreeway) {
06282
06283 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06284
06285 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06286 unalloc_sub(p, SUB_CALLWAIT);
06287 p->owner = NULL;
06288 } else {
06289
06290 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06291 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06292 unalloc_sub(p, SUB_THREEWAY);
06293 if (p->subs[SUB_REAL].inthreeway) {
06294
06295
06296 ast_debug(1, "Call was complete, setting owner to former third call\n");
06297 p->owner = p->subs[SUB_REAL].owner;
06298 } else {
06299
06300 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06301 p->owner = NULL;
06302 }
06303 p->subs[SUB_REAL].inthreeway = 0;
06304 }
06305 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06306
06307 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06308 unalloc_sub(p, SUB_CALLWAIT);
06309 p->owner = p->subs[SUB_REAL].owner;
06310 if (p->owner->_state != AST_STATE_UP)
06311 p->subs[SUB_REAL].needanswer = 1;
06312 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06313 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06314 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06315 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06316 unalloc_sub(p, SUB_THREEWAY);
06317 if (p->subs[SUB_REAL].inthreeway) {
06318
06319
06320 ast_debug(1, "Call was complete, setting owner to former third call\n");
06321 p->owner = p->subs[SUB_REAL].owner;
06322 } else {
06323
06324 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06325 p->owner = NULL;
06326 }
06327 p->subs[SUB_REAL].inthreeway = 0;
06328 }
06329 } else if (idx == SUB_CALLWAIT) {
06330
06331 if (p->subs[SUB_CALLWAIT].inthreeway) {
06332
06333
06334 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06335 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06336 S_OR(p->mohsuggest, NULL),
06337 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06338 }
06339 p->subs[SUB_THREEWAY].inthreeway = 0;
06340
06341 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06342 unalloc_sub(p, SUB_THREEWAY);
06343 } else
06344 unalloc_sub(p, SUB_CALLWAIT);
06345 } else if (idx == SUB_THREEWAY) {
06346 if (p->subs[SUB_CALLWAIT].inthreeway) {
06347
06348
06349 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06350 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06351 S_OR(p->mohsuggest, NULL),
06352 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06353 }
06354 p->subs[SUB_CALLWAIT].inthreeway = 0;
06355 }
06356 p->subs[SUB_REAL].inthreeway = 0;
06357
06358
06359 unalloc_sub(p, SUB_THREEWAY);
06360 } else {
06361
06362 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06363 }
06364 }
06365
06366 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06367 p->owner = NULL;
06368 p->ringt = 0;
06369 p->distinctivering = 0;
06370 p->confirmanswer = 0;
06371 p->outgoing = 0;
06372 p->digital = 0;
06373 p->faxhandled = 0;
06374 p->pulsedial = 0;
06375 if (p->dsp) {
06376 ast_dsp_free(p->dsp);
06377 p->dsp = NULL;
06378 }
06379
06380 revert_fax_buffers(p, ast);
06381
06382 p->law = p->law_default;
06383 law = p->law_default;
06384 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06385 if (res < 0)
06386 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06387
06388 #ifdef HAVE_OPENR2
06389 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06390 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06391
06392 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06393 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06394 } else {
06395 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06396 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06397 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06398 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06399 dahdi_r2_disconnect_call(p, r2cause);
06400 }
06401 } else if (p->mfcr2call) {
06402 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06403
06404
06405
06406
06407 p->mfcr2call = 0;
06408 }
06409 #endif
06410 switch (p->sig) {
06411 case SIG_SS7:
06412 case SIG_MFCR2:
06413 case SIG_PRI_LIB_HANDLE_CASES:
06414 case 0:
06415 break;
06416 default:
06417 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06418 break;
06419 }
06420 if (res < 0) {
06421 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06422 }
06423 switch (p->sig) {
06424 case SIG_FXOGS:
06425 case SIG_FXOLS:
06426 case SIG_FXOKS:
06427 memset(&par, 0, sizeof(par));
06428 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06429 if (!res) {
06430 struct analog_pvt *analog_p = p->sig_pvt;
06431 #if 0
06432 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06433 #endif
06434
06435 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06436 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06437 else
06438 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06439 analog_p->fxsoffhookstate = par.rxisoffhook;
06440 }
06441 break;
06442 case SIG_FXSGS:
06443 case SIG_FXSLS:
06444 case SIG_FXSKS:
06445
06446
06447 if (ast->_state != AST_STATE_RESERVED) {
06448 time(&p->guardtime);
06449 p->guardtime += 2;
06450 }
06451 break;
06452 default:
06453 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06454 break;
06455 }
06456 if (p->sig)
06457 dahdi_disable_ec(p);
06458 x = 0;
06459 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06460 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06461 p->didtdd = 0;
06462 p->callwaitcas = 0;
06463 p->callwaiting = p->permcallwaiting;
06464 p->hidecallerid = p->permhidecallerid;
06465 p->waitingfordt.tv_sec = 0;
06466 p->dialing = 0;
06467 p->rdnis[0] = '\0';
06468 update_conf(p);
06469 reset_conf(p);
06470
06471 switch (p->sig) {
06472 case SIG_PRI_LIB_HANDLE_CASES:
06473 case SIG_SS7:
06474 x = 0;
06475 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06476 break;
06477 default:
06478 break;
06479 }
06480 if (num_restart_pending == 0)
06481 restart_monitor();
06482 }
06483
06484 p->callwaitingrepeat = 0;
06485 p->cidcwexpire = 0;
06486 p->cid_suppress_expire = 0;
06487 p->oprmode = 0;
06488 hangup_out:
06489 ast->tech_pvt = NULL;
06490 ast_free(p->cidspill);
06491 p->cidspill = NULL;
06492
06493 ast_mutex_unlock(&p->lock);
06494 ast_verb(3, "Hungup '%s'\n", ast->name);
06495
06496 ast_mutex_lock(&iflock);
06497 if (p->restartpending) {
06498 num_restart_pending--;
06499 }
06500
06501 if (p->destroy) {
06502 destroy_channel(p, 0);
06503 }
06504 ast_mutex_unlock(&iflock);
06505
06506 ast_module_unref(ast_module_info->self);
06507 return 0;
06508 }
06509
06510 static int dahdi_answer(struct ast_channel *ast)
06511 {
06512 struct dahdi_pvt *p = ast->tech_pvt;
06513 int res = 0;
06514 int idx;
06515 ast_setstate(ast, AST_STATE_UP);
06516 ast_mutex_lock(&p->lock);
06517 idx = dahdi_get_index(ast, p, 0);
06518 if (idx < 0)
06519 idx = SUB_REAL;
06520
06521 if ((p->radio || (p->oprmode < 0))) {
06522 ast_mutex_unlock(&p->lock);
06523 return 0;
06524 }
06525
06526 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06527 res = analog_answer(p->sig_pvt, ast);
06528 ast_mutex_unlock(&p->lock);
06529 return res;
06530 }
06531
06532 switch (p->sig) {
06533 #if defined(HAVE_PRI)
06534 case SIG_PRI_LIB_HANDLE_CASES:
06535 res = sig_pri_answer(p->sig_pvt, ast);
06536 break;
06537 #endif
06538 #if defined(HAVE_SS7)
06539 case SIG_SS7:
06540 res = sig_ss7_answer(p->sig_pvt, ast);
06541 break;
06542 #endif
06543 #ifdef HAVE_OPENR2
06544 case SIG_MFCR2:
06545 if (!p->mfcr2_call_accepted) {
06546
06547
06548 p->mfcr2_answer_pending = 1;
06549 if (p->mfcr2_charge_calls) {
06550 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06551 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06552 } else {
06553 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06554 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06555 }
06556 } else {
06557 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06558 dahdi_r2_answer(p);
06559 }
06560 break;
06561 #endif
06562 case 0:
06563 ast_mutex_unlock(&p->lock);
06564 return 0;
06565 default:
06566 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06567 res = -1;
06568 break;
06569 }
06570 ast_mutex_unlock(&p->lock);
06571 return res;
06572 }
06573
06574 static void disable_dtmf_detect(struct dahdi_pvt *p)
06575 {
06576 int val = 0;
06577
06578 p->ignoredtmf = 1;
06579
06580 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06581
06582 if (!p->hardwaredtmf && p->dsp) {
06583 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06584 ast_dsp_set_features(p->dsp, p->dsp_features);
06585 }
06586 }
06587
06588 static void enable_dtmf_detect(struct dahdi_pvt *p)
06589 {
06590 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06591
06592 if (p->channel == CHAN_PSEUDO)
06593 return;
06594
06595 p->ignoredtmf = 0;
06596
06597 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06598
06599 if (!p->hardwaredtmf && p->dsp) {
06600 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06601 ast_dsp_set_features(p->dsp, p->dsp_features);
06602 }
06603 }
06604
06605 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06606 {
06607 char *cp;
06608 struct dahdi_pvt *p = chan->tech_pvt;
06609
06610
06611 if (!p || !data || (*datalen < 1)) {
06612 errno = EINVAL;
06613 return -1;
06614 }
06615
06616 switch (option) {
06617 case AST_OPTION_DIGIT_DETECT:
06618 cp = (char *) data;
06619 *cp = p->ignoredtmf ? 0 : 1;
06620 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06621 break;
06622 case AST_OPTION_FAX_DETECT:
06623 cp = (char *) data;
06624 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06625 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06626 break;
06627 case AST_OPTION_CC_AGENT_TYPE:
06628 #if defined(HAVE_PRI)
06629 #if defined(HAVE_PRI_CCSS)
06630 if (dahdi_sig_pri_lib_handles(p->sig)) {
06631 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06632 break;
06633 }
06634 #endif
06635 #endif
06636 return -1;
06637 default:
06638 return -1;
06639 }
06640
06641 errno = 0;
06642
06643 return 0;
06644 }
06645
06646 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06647 {
06648 char *cp;
06649 signed char *scp;
06650 int x;
06651 int idx;
06652 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06653 struct oprmode *oprmode;
06654
06655
06656
06657 if (!p || !data || (datalen < 1)) {
06658 errno = EINVAL;
06659 return -1;
06660 }
06661
06662 switch (option) {
06663 case AST_OPTION_TXGAIN:
06664 scp = (signed char *) data;
06665 idx = dahdi_get_index(chan, p, 0);
06666 if (idx < 0) {
06667 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06668 return -1;
06669 }
06670 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06671 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06672 case AST_OPTION_RXGAIN:
06673 scp = (signed char *) data;
06674 idx = dahdi_get_index(chan, p, 0);
06675 if (idx < 0) {
06676 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06677 return -1;
06678 }
06679 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06680 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06681 case AST_OPTION_TONE_VERIFY:
06682 if (!p->dsp)
06683 break;
06684 cp = (char *) data;
06685 switch (*cp) {
06686 case 1:
06687 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06688 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06689 break;
06690 case 2:
06691 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06692 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06693 break;
06694 default:
06695 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06696 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06697 break;
06698 }
06699 break;
06700 case AST_OPTION_TDD:
06701
06702 cp = (char *) data;
06703 p->mate = 0;
06704 if (!*cp) {
06705 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06706 if (p->tdd)
06707 tdd_free(p->tdd);
06708 p->tdd = 0;
06709 break;
06710 }
06711 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06712 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06713 dahdi_disable_ec(p);
06714
06715 if (!p->didtdd) {
06716 unsigned char mybuf[41000];
06717 unsigned char *buf;
06718 int size, res, fd, len;
06719 struct pollfd fds[1];
06720
06721 buf = mybuf;
06722 memset(buf, 0x7f, sizeof(mybuf));
06723 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06724 len = 40000;
06725 idx = dahdi_get_index(chan, p, 0);
06726 if (idx < 0) {
06727 ast_log(LOG_WARNING, "No index in TDD?\n");
06728 return -1;
06729 }
06730 fd = p->subs[idx].dfd;
06731 while (len) {
06732 if (ast_check_hangup(chan))
06733 return -1;
06734 size = len;
06735 if (size > READ_SIZE)
06736 size = READ_SIZE;
06737 fds[0].fd = fd;
06738 fds[0].events = POLLPRI | POLLOUT;
06739 fds[0].revents = 0;
06740 res = poll(fds, 1, -1);
06741 if (!res) {
06742 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06743 continue;
06744 }
06745
06746 if (fds[0].revents & POLLPRI)
06747 return -1;
06748 if (!(fds[0].revents & POLLOUT)) {
06749 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06750 continue;
06751 }
06752 res = write(fd, buf, size);
06753 if (res != size) {
06754 if (res == -1) return -1;
06755 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06756 break;
06757 }
06758 len -= size;
06759 buf += size;
06760 }
06761 p->didtdd = 1;
06762 }
06763 if (*cp == 2) {
06764 if (p->tdd)
06765 tdd_free(p->tdd);
06766 p->tdd = 0;
06767 p->mate = 1;
06768 break;
06769 }
06770 if (!p->tdd) {
06771 p->tdd = tdd_new();
06772 }
06773 break;
06774 case AST_OPTION_RELAXDTMF:
06775 if (!p->dsp)
06776 break;
06777 cp = (char *) data;
06778 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06779 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06780 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06781 break;
06782 case AST_OPTION_AUDIO_MODE:
06783 #if defined(HAVE_PRI)
06784 if (dahdi_sig_pri_lib_handles(p->sig)
06785 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06786
06787 break;
06788 }
06789 #endif
06790
06791 cp = (char *) data;
06792 if (!*cp) {
06793 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06794 x = 0;
06795 dahdi_disable_ec(p);
06796 } else {
06797 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06798 x = 1;
06799 }
06800 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06801 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06802 break;
06803 case AST_OPTION_OPRMODE:
06804 oprmode = (struct oprmode *) data;
06805
06806 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06807 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06808 chan->tech->type, oprmode->peer->tech->type);
06809 errno = EINVAL;
06810 return -1;
06811 }
06812 pp = oprmode->peer->tech_pvt;
06813 p->oprmode = pp->oprmode = 0;
06814
06815 p->oprpeer = pp;
06816 pp->oprpeer = p;
06817
06818 if (oprmode->mode)
06819 {
06820 pp->oprmode = oprmode->mode;
06821 p->oprmode = -oprmode->mode;
06822 }
06823 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06824 oprmode->mode, chan->name,oprmode->peer->name);
06825 break;
06826 case AST_OPTION_ECHOCAN:
06827 cp = (char *) data;
06828 if (*cp) {
06829 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06830 dahdi_enable_ec(p);
06831 } else {
06832 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06833 dahdi_disable_ec(p);
06834 }
06835 break;
06836 case AST_OPTION_DIGIT_DETECT:
06837 cp = (char *) data;
06838 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06839 if (*cp) {
06840 enable_dtmf_detect(p);
06841 } else {
06842 disable_dtmf_detect(p);
06843 }
06844 break;
06845 case AST_OPTION_FAX_DETECT:
06846 cp = (char *) data;
06847 if (p->dsp) {
06848 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06849 if (*cp) {
06850 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06851 } else {
06852 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06853 }
06854 ast_dsp_set_features(p->dsp, p->dsp_features);
06855 }
06856 break;
06857 default:
06858 return -1;
06859 }
06860 errno = 0;
06861
06862 return 0;
06863 }
06864
06865 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06866 {
06867 struct dahdi_pvt *p = chan->tech_pvt;
06868 int res = 0;
06869
06870 if (!p) {
06871
06872 *buf = '\0';
06873 return -1;
06874 }
06875
06876 if (!strcasecmp(data, "rxgain")) {
06877 ast_mutex_lock(&p->lock);
06878 snprintf(buf, len, "%f", p->rxgain);
06879 ast_mutex_unlock(&p->lock);
06880 } else if (!strcasecmp(data, "txgain")) {
06881 ast_mutex_lock(&p->lock);
06882 snprintf(buf, len, "%f", p->txgain);
06883 ast_mutex_unlock(&p->lock);
06884 } else if (!strcasecmp(data, "dahdi_channel")) {
06885 ast_mutex_lock(&p->lock);
06886 snprintf(buf, len, "%d", p->channel);
06887 ast_mutex_unlock(&p->lock);
06888 } else if (!strcasecmp(data, "dahdi_span")) {
06889 ast_mutex_lock(&p->lock);
06890 snprintf(buf, len, "%d", p->span);
06891 ast_mutex_unlock(&p->lock);
06892 } else if (!strcasecmp(data, "dahdi_type")) {
06893 ast_mutex_lock(&p->lock);
06894 switch (p->sig) {
06895 #if defined(HAVE_OPENR2)
06896 case SIG_MFCR2:
06897 ast_copy_string(buf, "mfc/r2", len);
06898 break;
06899 #endif
06900 #if defined(HAVE_PRI)
06901 case SIG_PRI_LIB_HANDLE_CASES:
06902 ast_copy_string(buf, "pri", len);
06903 break;
06904 #endif
06905 case 0:
06906 ast_copy_string(buf, "pseudo", len);
06907 break;
06908 #if defined(HAVE_SS7)
06909 case SIG_SS7:
06910 ast_copy_string(buf, "ss7", len);
06911 break;
06912 #endif
06913 default:
06914
06915 ast_copy_string(buf, "analog", len);
06916 break;
06917 }
06918 ast_mutex_unlock(&p->lock);
06919 #if defined(HAVE_PRI)
06920 #if defined(HAVE_PRI_REVERSE_CHARGE)
06921 } else if (!strcasecmp(data, "reversecharge")) {
06922 ast_mutex_lock(&p->lock);
06923 switch (p->sig) {
06924 case SIG_PRI_LIB_HANDLE_CASES:
06925 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06926 break;
06927 default:
06928 *buf = '\0';
06929 res = -1;
06930 break;
06931 }
06932 ast_mutex_unlock(&p->lock);
06933 #endif
06934 #if defined(HAVE_PRI_SETUP_KEYPAD)
06935 } else if (!strcasecmp(data, "keypad_digits")) {
06936 ast_mutex_lock(&p->lock);
06937 switch (p->sig) {
06938 case SIG_PRI_LIB_HANDLE_CASES:
06939 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06940 len);
06941 break;
06942 default:
06943 *buf = '\0';
06944 res = -1;
06945 break;
06946 }
06947 ast_mutex_unlock(&p->lock);
06948 #endif
06949 } else if (!strcasecmp(data, "no_media_path")) {
06950 ast_mutex_lock(&p->lock);
06951 switch (p->sig) {
06952 case SIG_PRI_LIB_HANDLE_CASES:
06953
06954
06955
06956
06957 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06958 break;
06959 default:
06960 *buf = '\0';
06961 res = -1;
06962 break;
06963 }
06964 ast_mutex_unlock(&p->lock);
06965 #endif
06966 } else {
06967 *buf = '\0';
06968 res = -1;
06969 }
06970
06971 return res;
06972 }
06973
06974
06975 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06976 {
06977 int res;
06978 char policy_str[21] = "";
06979
06980 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06981 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06982 return 1;
06983 }
06984 if (*num_buffers < 0) {
06985 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06986 return -1;
06987 }
06988 if (!strcasecmp(policy_str, "full")) {
06989 *policy = DAHDI_POLICY_WHEN_FULL;
06990 } else if (!strcasecmp(policy_str, "immediate")) {
06991 *policy = DAHDI_POLICY_IMMEDIATE;
06992 #if defined(HAVE_DAHDI_HALF_FULL)
06993 } else if (!strcasecmp(policy_str, "half")) {
06994 *policy = DAHDI_POLICY_HALF_FULL;
06995 #endif
06996 } else {
06997 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06998 return -1;
06999 }
07000
07001 return 0;
07002 }
07003
07004 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07005 {
07006 struct dahdi_pvt *p = chan->tech_pvt;
07007 int res = 0;
07008
07009 if (!p) {
07010
07011 return -1;
07012 }
07013
07014 if (!strcasecmp(data, "buffers")) {
07015 int num_bufs, policy;
07016
07017 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07018 struct dahdi_bufferinfo bi = {
07019 .txbufpolicy = policy,
07020 .rxbufpolicy = policy,
07021 .bufsize = p->bufsize,
07022 .numbufs = num_bufs,
07023 };
07024 int bpres;
07025
07026 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07027 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07028 } else {
07029 p->bufferoverrideinuse = 1;
07030 }
07031 } else {
07032 res = -1;
07033 }
07034 } else if (!strcasecmp(data, "echocan_mode")) {
07035 if (!strcasecmp(value, "on")) {
07036 ast_mutex_lock(&p->lock);
07037 dahdi_enable_ec(p);
07038 ast_mutex_unlock(&p->lock);
07039 } else if (!strcasecmp(value, "off")) {
07040 ast_mutex_lock(&p->lock);
07041 dahdi_disable_ec(p);
07042 ast_mutex_unlock(&p->lock);
07043 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07044 } else if (!strcasecmp(value, "fax")) {
07045 int blah = 1;
07046
07047 ast_mutex_lock(&p->lock);
07048 if (!p->echocanon) {
07049 dahdi_enable_ec(p);
07050 }
07051 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07052 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07053 }
07054 ast_mutex_unlock(&p->lock);
07055 } else if (!strcasecmp(value, "voice")) {
07056 int blah = 0;
07057
07058 ast_mutex_lock(&p->lock);
07059 if (!p->echocanon) {
07060 dahdi_enable_ec(p);
07061 }
07062 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07063 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07064 }
07065 ast_mutex_unlock(&p->lock);
07066 #endif
07067 } else {
07068 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07069 res = -1;
07070 }
07071 } else {
07072 res = -1;
07073 }
07074
07075 return res;
07076 }
07077
07078 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07079 {
07080
07081 int x;
07082 int hasslaves;
07083 if (!master)
07084 return;
07085 if (needlock) {
07086 ast_mutex_lock(&master->lock);
07087 if (slave) {
07088 while (ast_mutex_trylock(&slave->lock)) {
07089 DEADLOCK_AVOIDANCE(&master->lock);
07090 }
07091 }
07092 }
07093 hasslaves = 0;
07094 for (x = 0; x < MAX_SLAVES; x++) {
07095 if (master->slaves[x]) {
07096 if (!slave || (master->slaves[x] == slave)) {
07097
07098 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07099 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07100 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07101 master->slaves[x]->master = NULL;
07102 master->slaves[x] = NULL;
07103 } else
07104 hasslaves = 1;
07105 }
07106 if (!hasslaves)
07107 master->inconference = 0;
07108 }
07109 if (!slave) {
07110 if (master->master) {
07111
07112 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07113 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07114 hasslaves = 0;
07115 for (x = 0; x < MAX_SLAVES; x++) {
07116 if (master->master->slaves[x] == master)
07117 master->master->slaves[x] = NULL;
07118 else if (master->master->slaves[x])
07119 hasslaves = 1;
07120 }
07121 if (!hasslaves)
07122 master->master->inconference = 0;
07123 }
07124 master->master = NULL;
07125 }
07126 update_conf(master);
07127 if (needlock) {
07128 if (slave)
07129 ast_mutex_unlock(&slave->lock);
07130 ast_mutex_unlock(&master->lock);
07131 }
07132 }
07133
07134 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07135 int x;
07136 if (!slave || !master) {
07137 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07138 return;
07139 }
07140 for (x = 0; x < MAX_SLAVES; x++) {
07141 if (!master->slaves[x]) {
07142 master->slaves[x] = slave;
07143 break;
07144 }
07145 }
07146 if (x >= MAX_SLAVES) {
07147 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07148 master->slaves[MAX_SLAVES - 1] = slave;
07149 }
07150 if (slave->master)
07151 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07152 slave->master = master;
07153
07154 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07155 }
07156
07157 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)
07158 {
07159 struct ast_channel *who;
07160 struct dahdi_pvt *p0, *p1, *op0, *op1;
07161 struct dahdi_pvt *master = NULL, *slave = NULL;
07162 struct ast_frame *f;
07163 int inconf = 0;
07164 int nothingok = 1;
07165 int ofd0, ofd1;
07166 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07167 int os0 = -1, os1 = -1;
07168 int priority = 0;
07169 struct ast_channel *oc0, *oc1;
07170 enum ast_bridge_result res;
07171 #ifdef PRI_2BCT
07172 int triedtopribridge = 0;
07173 q931_call *q931c0;
07174 q931_call *q931c1;
07175 #endif
07176
07177
07178
07179
07180
07181
07182 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07183 return AST_BRIDGE_FAILED_NOWARN;
07184
07185 ast_channel_lock(c0);
07186 while (ast_channel_trylock(c1)) {
07187 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07188 }
07189
07190 p0 = c0->tech_pvt;
07191 p1 = c1->tech_pvt;
07192
07193 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07194 ast_channel_unlock(c0);
07195 ast_channel_unlock(c1);
07196 return AST_BRIDGE_FAILED_NOWARN;
07197 }
07198
07199 oi0 = dahdi_get_index(c0, p0, 0);
07200 oi1 = dahdi_get_index(c1, p1, 0);
07201 if ((oi0 < 0) || (oi1 < 0)) {
07202 ast_channel_unlock(c0);
07203 ast_channel_unlock(c1);
07204 return AST_BRIDGE_FAILED;
07205 }
07206
07207 op0 = p0 = c0->tech_pvt;
07208 op1 = p1 = c1->tech_pvt;
07209 ofd0 = c0->fds[0];
07210 ofd1 = c1->fds[0];
07211 oc0 = p0->owner;
07212 oc1 = p1->owner;
07213
07214 if (ast_mutex_trylock(&p0->lock)) {
07215
07216 ast_channel_unlock(c0);
07217 ast_channel_unlock(c1);
07218 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07219 return AST_BRIDGE_RETRY;
07220 }
07221 if (ast_mutex_trylock(&p1->lock)) {
07222
07223 ast_mutex_unlock(&p0->lock);
07224 ast_channel_unlock(c0);
07225 ast_channel_unlock(c1);
07226 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07227 return AST_BRIDGE_RETRY;
07228 }
07229
07230 if ((p0->callwaiting && p0->callwaitingcallerid)
07231 || (p1->callwaiting && p1->callwaitingcallerid)) {
07232
07233
07234
07235
07236
07237
07238
07239
07240
07241 ast_mutex_unlock(&p0->lock);
07242 ast_mutex_unlock(&p1->lock);
07243 ast_channel_unlock(c0);
07244 ast_channel_unlock(c1);
07245 return AST_BRIDGE_FAILED_NOWARN;
07246 }
07247
07248 #if defined(HAVE_PRI)
07249 if ((dahdi_sig_pri_lib_handles(p0->sig)
07250 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07251 || (dahdi_sig_pri_lib_handles(p1->sig)
07252 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07253
07254
07255
07256
07257 ast_mutex_unlock(&p0->lock);
07258 ast_mutex_unlock(&p1->lock);
07259 ast_channel_unlock(c0);
07260 ast_channel_unlock(c1);
07261 return AST_BRIDGE_FAILED_NOWARN;
07262 }
07263 #endif
07264
07265 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07266 if (p0->owner && p1->owner) {
07267
07268 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07269 master = p0;
07270 slave = p1;
07271 inconf = 1;
07272 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07273 master = p1;
07274 slave = p0;
07275 inconf = 1;
07276 } else {
07277 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07278 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07279 p0->channel,
07280 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07281 p0->subs[SUB_REAL].inthreeway, p0->channel,
07282 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07283 p1->subs[SUB_REAL].inthreeway);
07284 }
07285 nothingok = 0;
07286 }
07287 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07288 if (p1->subs[SUB_THREEWAY].inthreeway) {
07289 master = p1;
07290 slave = p0;
07291 nothingok = 0;
07292 }
07293 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07294 if (p0->subs[SUB_THREEWAY].inthreeway) {
07295 master = p0;
07296 slave = p1;
07297 nothingok = 0;
07298 }
07299 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07300
07301
07302 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07303 master = p1;
07304 slave = p0;
07305 nothingok = 0;
07306 }
07307 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07308
07309 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07310 master = p0;
07311 slave = p1;
07312 nothingok = 0;
07313 }
07314 }
07315 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07316 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07317 if (master && slave) {
07318
07319
07320
07321 if ((oi1 == SUB_THREEWAY) &&
07322 p1->subs[SUB_THREEWAY].inthreeway &&
07323 p1->subs[SUB_REAL].owner &&
07324 p1->subs[SUB_REAL].inthreeway &&
07325 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07326 ast_debug(1,
07327 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07328 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07329 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07330 os1 = p1->subs[SUB_REAL].owner->_state;
07331 } else {
07332 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07333 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07334 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07335 }
07336 if ((oi0 == SUB_THREEWAY) &&
07337 p0->subs[SUB_THREEWAY].inthreeway &&
07338 p0->subs[SUB_REAL].owner &&
07339 p0->subs[SUB_REAL].inthreeway &&
07340 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07341 ast_debug(1,
07342 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07343 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07344 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07345 os0 = p0->subs[SUB_REAL].owner->_state;
07346 } else {
07347 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07348 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07349 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07350 }
07351 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07352 if (!p0->echocanbridged || !p1->echocanbridged) {
07353
07354 dahdi_disable_ec(p0);
07355 dahdi_disable_ec(p1);
07356 }
07357 }
07358 dahdi_link(slave, master);
07359 master->inconference = inconf;
07360 } else if (!nothingok)
07361 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07362
07363 update_conf(p0);
07364 update_conf(p1);
07365 t0 = p0->subs[SUB_REAL].inthreeway;
07366 t1 = p1->subs[SUB_REAL].inthreeway;
07367
07368 ast_mutex_unlock(&p0->lock);
07369 ast_mutex_unlock(&p1->lock);
07370
07371 ast_channel_unlock(c0);
07372 ast_channel_unlock(c1);
07373
07374
07375 if ((!master || !slave) && !nothingok) {
07376 dahdi_enable_ec(p0);
07377 dahdi_enable_ec(p1);
07378 return AST_BRIDGE_FAILED;
07379 }
07380
07381 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07382
07383 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07384 disable_dtmf_detect(op0);
07385
07386 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07387 disable_dtmf_detect(op1);
07388
07389 for (;;) {
07390 struct ast_channel *c0_priority[2] = {c0, c1};
07391 struct ast_channel *c1_priority[2] = {c1, c0};
07392
07393
07394
07395
07396 ast_channel_lock(c0);
07397 while (ast_channel_trylock(c1)) {
07398 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07399 }
07400
07401 p0 = c0->tech_pvt;
07402 p1 = c1->tech_pvt;
07403
07404 if (op0 == p0)
07405 i0 = dahdi_get_index(c0, p0, 1);
07406 if (op1 == p1)
07407 i1 = dahdi_get_index(c1, p1, 1);
07408
07409 ast_channel_unlock(c0);
07410 ast_channel_unlock(c1);
07411
07412 if (!timeoutms ||
07413 (op0 != p0) ||
07414 (op1 != p1) ||
07415 (ofd0 != c0->fds[0]) ||
07416 (ofd1 != c1->fds[0]) ||
07417 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07418 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07419 (oc0 != p0->owner) ||
07420 (oc1 != p1->owner) ||
07421 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07422 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07423 (oi0 != i0) ||
07424 (oi1 != i1)) {
07425 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07426 op0->channel, oi0, op1->channel, oi1);
07427 res = AST_BRIDGE_RETRY;
07428 goto return_from_bridge;
07429 }
07430
07431 #ifdef PRI_2BCT
07432 if (!triedtopribridge) {
07433 triedtopribridge = 1;
07434 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07435 ast_mutex_lock(&p0->pri->lock);
07436 switch (p0->sig) {
07437 case SIG_PRI_LIB_HANDLE_CASES:
07438 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07439 break;
07440 default:
07441 q931c0 = NULL;
07442 break;
07443 }
07444 switch (p1->sig) {
07445 case SIG_PRI_LIB_HANDLE_CASES:
07446 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07447 break;
07448 default:
07449 q931c1 = NULL;
07450 break;
07451 }
07452 if (q931c0 && q931c1) {
07453 pri_channel_bridge(q931c0, q931c1);
07454 }
07455 ast_mutex_unlock(&p0->pri->lock);
07456 }
07457 }
07458 #endif
07459
07460 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07461 if (!who) {
07462 ast_debug(1, "Ooh, empty read...\n");
07463 continue;
07464 }
07465 f = ast_read(who);
07466 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07467 *fo = f;
07468 *rc = who;
07469 res = AST_BRIDGE_COMPLETE;
07470 goto return_from_bridge;
07471 }
07472 if (f->frametype == AST_FRAME_DTMF) {
07473 if ((who == c0) && p0->pulsedial) {
07474 ast_write(c1, f);
07475 } else if ((who == c1) && p1->pulsedial) {
07476 ast_write(c0, f);
07477 } else {
07478 *fo = f;
07479 *rc = who;
07480 res = AST_BRIDGE_COMPLETE;
07481 goto return_from_bridge;
07482 }
07483 }
07484 ast_frfree(f);
07485
07486
07487 priority = !priority;
07488 }
07489
07490 return_from_bridge:
07491 if (op0 == p0)
07492 dahdi_enable_ec(p0);
07493
07494 if (op1 == p1)
07495 dahdi_enable_ec(p1);
07496
07497 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07498 enable_dtmf_detect(op0);
07499
07500 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07501 enable_dtmf_detect(op1);
07502
07503 dahdi_unlink(slave, master, 1);
07504
07505 return res;
07506 }
07507
07508 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07509 {
07510 struct dahdi_pvt *p = newchan->tech_pvt;
07511 int x;
07512
07513 ast_mutex_lock(&p->lock);
07514
07515 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07516 if (p->owner == oldchan) {
07517 p->owner = newchan;
07518 }
07519 for (x = 0; x < 3; x++) {
07520 if (p->subs[x].owner == oldchan) {
07521 if (!x) {
07522 dahdi_unlink(NULL, p, 0);
07523 }
07524 p->subs[x].owner = newchan;
07525 }
07526 }
07527 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07528 analog_fixup(oldchan, newchan, p->sig_pvt);
07529 #if defined(HAVE_PRI)
07530 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07531 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07532 #endif
07533 #if defined(HAVE_SS7)
07534 } else if (p->sig == SIG_SS7) {
07535 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07536 #endif
07537 }
07538 update_conf(p);
07539
07540 ast_mutex_unlock(&p->lock);
07541
07542 if (newchan->_state == AST_STATE_RINGING) {
07543 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07544 }
07545 return 0;
07546 }
07547
07548 static int dahdi_ring_phone(struct dahdi_pvt *p)
07549 {
07550 int x;
07551 int res;
07552
07553 x = 0;
07554 x = DAHDI_ONHOOK;
07555 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07556 do {
07557 x = DAHDI_RING;
07558 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07559 if (res) {
07560 switch (errno) {
07561 case EBUSY:
07562 case EINTR:
07563
07564 usleep(10000);
07565 continue;
07566 case EINPROGRESS:
07567 res = 0;
07568 break;
07569 default:
07570 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07571 res = 0;
07572 }
07573 }
07574 } while (res);
07575 return res;
07576 }
07577
07578 static void *analog_ss_thread(void *data);
07579
07580 static int attempt_transfer(struct dahdi_pvt *p)
07581 {
07582
07583
07584
07585 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07586
07587
07588 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07589 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07590 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07591 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07592 }
07593 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07594 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07595 }
07596 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07597 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07598 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07599 return -1;
07600 }
07601
07602 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07603 unalloc_sub(p, SUB_THREEWAY);
07604 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07605 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07606 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07607 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07608 }
07609 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07610 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07611 }
07612 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07613 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07614 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07615 return -1;
07616 }
07617
07618 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07619 ast_channel_unlock(p->subs[SUB_REAL].owner);
07620 unalloc_sub(p, SUB_THREEWAY);
07621
07622 return 1;
07623 } else {
07624 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07625 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07626 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07627 return -1;
07628 }
07629 return 0;
07630 }
07631
07632 static int check_for_conference(struct dahdi_pvt *p)
07633 {
07634 struct dahdi_confinfo ci;
07635
07636 if (p->master || (p->confno > -1))
07637 return 0;
07638 memset(&ci, 0, sizeof(ci));
07639 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07640 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07641 return 0;
07642 }
07643
07644
07645
07646 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07647 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07648 return 1;
07649 }
07650 return 0;
07651 }
07652
07653
07654
07655
07656
07657
07658 static int get_alarms(struct dahdi_pvt *p)
07659 {
07660 int res;
07661 struct dahdi_spaninfo zi;
07662 struct dahdi_params params;
07663
07664 memset(&zi, 0, sizeof(zi));
07665 zi.spanno = p->span;
07666
07667 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07668 if (zi.alarms != DAHDI_ALARM_NONE)
07669 return zi.alarms;
07670 } else {
07671 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07672 return 0;
07673 }
07674
07675
07676 memset(¶ms, 0, sizeof(params));
07677 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07678 return params.chan_alarms;
07679
07680 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07681
07682 return DAHDI_ALARM_NONE;
07683 }
07684
07685 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07686 {
07687 struct dahdi_pvt *p = ast->tech_pvt;
07688 struct ast_frame *f = *dest;
07689
07690 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07691 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07692 f->subclass.integer, f->subclass.integer, ast->name);
07693
07694 if (p->confirmanswer) {
07695 if (f->frametype == AST_FRAME_DTMF_END) {
07696 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07697
07698
07699 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07700 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07701
07702 p->confirmanswer = 0;
07703 } else {
07704 p->subs[idx].f.frametype = AST_FRAME_NULL;
07705 p->subs[idx].f.subclass.integer = 0;
07706 }
07707 *dest = &p->subs[idx].f;
07708 } else if (p->callwaitcas) {
07709 if (f->frametype == AST_FRAME_DTMF_END) {
07710 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07711 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07712 ast_free(p->cidspill);
07713 p->cidspill = NULL;
07714 send_cwcidspill(p);
07715 }
07716 p->callwaitcas = 0;
07717 }
07718 p->subs[idx].f.frametype = AST_FRAME_NULL;
07719 p->subs[idx].f.subclass.integer = 0;
07720 *dest = &p->subs[idx].f;
07721 } else if (f->subclass.integer == 'f') {
07722 if (f->frametype == AST_FRAME_DTMF_END) {
07723
07724 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07725
07726 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07727 struct dahdi_bufferinfo bi = {
07728 .txbufpolicy = p->faxbuf_policy,
07729 .bufsize = p->bufsize,
07730 .numbufs = p->faxbuf_no
07731 };
07732 int res;
07733
07734 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07735 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07736 } else {
07737 p->bufferoverrideinuse = 1;
07738 }
07739 }
07740 p->faxhandled = 1;
07741 if (p->dsp) {
07742 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07743 ast_dsp_set_features(p->dsp, p->dsp_features);
07744 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07745 }
07746 if (strcmp(ast->exten, "fax")) {
07747 const char *target_context = S_OR(ast->macrocontext, ast->context);
07748
07749
07750
07751
07752
07753 ast_mutex_unlock(&p->lock);
07754 ast_channel_unlock(ast);
07755 if (ast_exists_extension(ast, target_context, "fax", 1,
07756 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07757 ast_channel_lock(ast);
07758 ast_mutex_lock(&p->lock);
07759 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07760
07761 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07762 if (ast_async_goto(ast, target_context, "fax", 1))
07763 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07764 } else {
07765 ast_channel_lock(ast);
07766 ast_mutex_lock(&p->lock);
07767 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07768 }
07769 } else {
07770 ast_debug(1, "Already in a fax extension, not redirecting\n");
07771 }
07772 } else {
07773 ast_debug(1, "Fax already handled\n");
07774 }
07775 dahdi_confmute(p, 0);
07776 }
07777 p->subs[idx].f.frametype = AST_FRAME_NULL;
07778 p->subs[idx].f.subclass.integer = 0;
07779 *dest = &p->subs[idx].f;
07780 }
07781 }
07782
07783 static void handle_alarms(struct dahdi_pvt *p, int alms)
07784 {
07785 const char *alarm_str = alarm2str(alms);
07786
07787 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07788 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07789 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07790 "Alarm: %s\r\n"
07791 "Channel: %d\r\n",
07792 alarm_str, p->channel);
07793 }
07794
07795 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07796 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07797 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07798 "Alarm: %s\r\n"
07799 "Span: %d\r\n",
07800 alarm_str, p->span);
07801 }
07802 }
07803
07804 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07805 {
07806 int res, x;
07807 int idx, mysig;
07808 char *c;
07809 struct dahdi_pvt *p = ast->tech_pvt;
07810 pthread_t threadid;
07811 struct ast_channel *chan;
07812 struct ast_frame *f;
07813
07814 idx = dahdi_get_index(ast, p, 0);
07815 mysig = p->sig;
07816 if (p->outsigmod > -1)
07817 mysig = p->outsigmod;
07818 p->subs[idx].f.frametype = AST_FRAME_NULL;
07819 p->subs[idx].f.subclass.integer = 0;
07820 p->subs[idx].f.datalen = 0;
07821 p->subs[idx].f.samples = 0;
07822 p->subs[idx].f.mallocd = 0;
07823 p->subs[idx].f.offset = 0;
07824 p->subs[idx].f.src = "dahdi_handle_event";
07825 p->subs[idx].f.data.ptr = NULL;
07826 f = &p->subs[idx].f;
07827
07828 if (idx < 0)
07829 return &p->subs[idx].f;
07830 if (p->fake_event) {
07831 res = p->fake_event;
07832 p->fake_event = 0;
07833 } else
07834 res = dahdi_get_event(p->subs[idx].dfd);
07835
07836 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07837
07838 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07839 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07840 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07841 #if defined(HAVE_PRI)
07842 if (dahdi_sig_pri_lib_handles(p->sig)
07843 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07844 && p->pri
07845 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07846
07847 } else
07848 #endif
07849 {
07850
07851 dahdi_confmute(p, 0);
07852 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07853 p->subs[idx].f.subclass.integer = res & 0xff;
07854 dahdi_handle_dtmf(ast, idx, &f);
07855 }
07856 return f;
07857 }
07858
07859 if (res & DAHDI_EVENT_DTMFDOWN) {
07860 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07861 #if defined(HAVE_PRI)
07862 if (dahdi_sig_pri_lib_handles(p->sig)
07863 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07864 && p->pri
07865 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07866
07867 } else
07868 #endif
07869 {
07870
07871 dahdi_confmute(p, 1);
07872 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07873 p->subs[idx].f.subclass.integer = res & 0xff;
07874 dahdi_handle_dtmf(ast, idx, &f);
07875 }
07876 return &p->subs[idx].f;
07877 }
07878
07879 switch (res) {
07880 case DAHDI_EVENT_EC_DISABLED:
07881 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07882 p->echocanon = 0;
07883 break;
07884 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07885 case DAHDI_EVENT_TX_CED_DETECTED:
07886 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07887 break;
07888 case DAHDI_EVENT_RX_CED_DETECTED:
07889 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07890 break;
07891 case DAHDI_EVENT_EC_NLP_DISABLED:
07892 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07893 break;
07894 case DAHDI_EVENT_EC_NLP_ENABLED:
07895 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07896 break;
07897 #endif
07898 case DAHDI_EVENT_BITSCHANGED:
07899 #ifdef HAVE_OPENR2
07900 if (p->sig != SIG_MFCR2) {
07901 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07902 } else {
07903 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07904 openr2_chan_handle_cas(p->r2chan);
07905 }
07906 #else
07907 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07908 #endif
07909 case DAHDI_EVENT_PULSE_START:
07910
07911 if (!ast->pbx)
07912 tone_zone_play_tone(p->subs[idx].dfd, -1);
07913 break;
07914 case DAHDI_EVENT_DIALCOMPLETE:
07915 #ifdef HAVE_OPENR2
07916 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07917
07918
07919 break;
07920 }
07921 #endif
07922 if (p->inalarm) break;
07923 if ((p->radio || (p->oprmode < 0))) break;
07924 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07925 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07926 return NULL;
07927 }
07928 if (!x) {
07929 dahdi_enable_ec(p);
07930 if (p->echobreak) {
07931 dahdi_train_ec(p);
07932 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07933 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07934 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07935 p->echobreak = 0;
07936 } else {
07937 p->dialing = 0;
07938 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07939
07940 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07941 ast_setstate(ast, AST_STATE_UP);
07942 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07943 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07944 break;
07945 } else {
07946
07947 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07948 }
07949 }
07950 if (ast->_state == AST_STATE_DIALING) {
07951 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07952 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07953 } else if (p->confirmanswer || (!p->dialednone
07954 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07955 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07956 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07957 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07958 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07959 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07960 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07961 || (mysig == SIG_SF_FEATB)))) {
07962 ast_setstate(ast, AST_STATE_RINGING);
07963 } else if (!p->answeronpolarityswitch) {
07964 ast_setstate(ast, AST_STATE_UP);
07965 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07966 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07967
07968 p->polarity = POLARITY_REV;
07969 } else {
07970
07971 p->polarity = POLARITY_IDLE;
07972 }
07973 }
07974 }
07975 }
07976 break;
07977 case DAHDI_EVENT_ALARM:
07978 switch (p->sig) {
07979 #if defined(HAVE_PRI)
07980 case SIG_PRI_LIB_HANDLE_CASES:
07981 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07982 break;
07983 #endif
07984 #if defined(HAVE_SS7)
07985 case SIG_SS7:
07986 sig_ss7_set_alarm(p->sig_pvt, 1);
07987 break;
07988 #endif
07989 default:
07990 p->inalarm = 1;
07991 break;
07992 }
07993 res = get_alarms(p);
07994 handle_alarms(p, res);
07995 #ifdef HAVE_PRI
07996 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07997
07998 } else {
07999 break;
08000 }
08001 #endif
08002 #if defined(HAVE_SS7)
08003 if (p->sig == SIG_SS7)
08004 break;
08005 #endif
08006 #ifdef HAVE_OPENR2
08007 if (p->sig == SIG_MFCR2)
08008 break;
08009 #endif
08010 case DAHDI_EVENT_ONHOOK:
08011 if (p->radio) {
08012 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08013 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08014 break;
08015 }
08016 if (p->oprmode < 0)
08017 {
08018 if (p->oprmode != -1) break;
08019 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08020 {
08021
08022 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08023 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08024 save_conference(p->oprpeer);
08025 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08026 }
08027 break;
08028 }
08029 switch (p->sig) {
08030 case SIG_FXOLS:
08031 case SIG_FXOGS:
08032 case SIG_FXOKS:
08033
08034 if (idx == SUB_REAL) {
08035
08036 if (p->subs[SUB_CALLWAIT].owner) {
08037
08038 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08039 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08040 unalloc_sub(p, SUB_CALLWAIT);
08041 #if 0
08042 p->subs[idx].needanswer = 0;
08043 p->subs[idx].needringing = 0;
08044 #endif
08045 p->callwaitingrepeat = 0;
08046 p->cidcwexpire = 0;
08047 p->cid_suppress_expire = 0;
08048 p->owner = NULL;
08049
08050 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08051 p->dialing = 1;
08052 dahdi_ring_phone(p);
08053 } else if (p->subs[SUB_THREEWAY].owner) {
08054 unsigned int mssinceflash;
08055
08056
08057 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08058
08059 DLA_UNLOCK(&p->lock);
08060 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08061
08062
08063
08064 DLA_LOCK(&p->lock);
08065 if (p->owner != ast) {
08066 ast_log(LOG_WARNING, "This isn't good...\n");
08067 return NULL;
08068 }
08069 }
08070 if (!p->subs[SUB_THREEWAY].owner) {
08071 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08072 return NULL;
08073 }
08074 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08075 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08076 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08077
08078
08079 if (p->subs[SUB_THREEWAY].owner)
08080 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08081 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08082 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08083 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08084 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08085 if (p->transfer) {
08086
08087 p->subs[SUB_REAL].inthreeway = 0;
08088 p->subs[SUB_THREEWAY].inthreeway = 0;
08089
08090 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08091 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08092
08093 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08094 p->owner = NULL;
08095
08096 dahdi_ring_phone(p);
08097 } else {
08098 if ((res = attempt_transfer(p)) < 0) {
08099 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08100 if (p->subs[SUB_THREEWAY].owner)
08101 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08102 } else if (res) {
08103
08104 if (p->subs[SUB_THREEWAY].owner)
08105 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08106 break;
08107 }
08108 }
08109 } else {
08110 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08111 if (p->subs[SUB_THREEWAY].owner)
08112 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08113 }
08114 } else {
08115 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08116
08117 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08118 p->owner = NULL;
08119
08120 dahdi_ring_phone(p);
08121 }
08122 }
08123 } else {
08124 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08125 }
08126
08127 default:
08128 dahdi_disable_ec(p);
08129 return NULL;
08130 }
08131 break;
08132 case DAHDI_EVENT_RINGOFFHOOK:
08133 if (p->inalarm) break;
08134 if (p->oprmode < 0)
08135 {
08136 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08137 {
08138
08139 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08140 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08141 restore_conference(p->oprpeer);
08142 }
08143 break;
08144 }
08145 if (p->radio)
08146 {
08147 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08148 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08149 break;
08150 }
08151
08152
08153 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08154 c = strchr(p->dialdest, '/');
08155 if (c)
08156 c++;
08157 else
08158 c = p->dialdest;
08159 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08160 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08161 if (strlen(p->dop.dialstr) > 4) {
08162 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08163 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08164 p->echorest[sizeof(p->echorest) - 1] = '\0';
08165 p->echobreak = 1;
08166 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08167 } else
08168 p->echobreak = 0;
08169 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08170 int saveerr = errno;
08171
08172 x = DAHDI_ONHOOK;
08173 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08174 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08175 return NULL;
08176 }
08177 p->dialing = 1;
08178 return &p->subs[idx].f;
08179 }
08180 switch (p->sig) {
08181 case SIG_FXOLS:
08182 case SIG_FXOGS:
08183 case SIG_FXOKS:
08184 switch (ast->_state) {
08185 case AST_STATE_RINGING:
08186 dahdi_enable_ec(p);
08187 dahdi_train_ec(p);
08188 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08189 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08190
08191 p->subs[SUB_REAL].needringing = 0;
08192 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08193 ast_debug(1, "channel %d answered\n", p->channel);
08194
08195
08196 ast_free(p->cidspill);
08197 p->cidspill = NULL;
08198 restore_conference(p);
08199
08200 p->dialing = 0;
08201 p->callwaitcas = 0;
08202 if (p->confirmanswer) {
08203
08204 p->subs[idx].f.frametype = AST_FRAME_NULL;
08205 p->subs[idx].f.subclass.integer = 0;
08206 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08207
08208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08209 if (res < 0) {
08210 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08211 p->dop.dialstr[0] = '\0';
08212 return NULL;
08213 } else {
08214 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08215 p->subs[idx].f.frametype = AST_FRAME_NULL;
08216 p->subs[idx].f.subclass.integer = 0;
08217 p->dialing = 1;
08218 }
08219 p->dop.dialstr[0] = '\0';
08220 ast_setstate(ast, AST_STATE_DIALING);
08221 } else
08222 ast_setstate(ast, AST_STATE_UP);
08223 return &p->subs[idx].f;
08224 case AST_STATE_DOWN:
08225 ast_setstate(ast, AST_STATE_RING);
08226 ast->rings = 1;
08227 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08228 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08229 ast_debug(1, "channel %d picked up\n", p->channel);
08230 return &p->subs[idx].f;
08231 case AST_STATE_UP:
08232
08233 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08234
08235 if (ast_bridged_channel(p->owner))
08236 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08237 p->subs[idx].needunhold = 1;
08238 break;
08239 case AST_STATE_RESERVED:
08240
08241 if (has_voicemail(p))
08242 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08243 else
08244 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08245 break;
08246 default:
08247 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08248 }
08249 break;
08250 case SIG_FXSLS:
08251 case SIG_FXSGS:
08252 case SIG_FXSKS:
08253 if (ast->_state == AST_STATE_RING) {
08254 p->ringt = p->ringt_base;
08255 }
08256
08257
08258
08259 ast_debug(1, "Setting IDLE polarity due "
08260 "to ring. Old polarity was %d\n",
08261 p->polarity);
08262 p->polarity = POLARITY_IDLE;
08263
08264
08265 case SIG_EM:
08266 case SIG_EM_E1:
08267 case SIG_EMWINK:
08268 case SIG_FEATD:
08269 case SIG_FEATDMF:
08270 case SIG_FEATDMF_TA:
08271 case SIG_E911:
08272 case SIG_FGC_CAMA:
08273 case SIG_FGC_CAMAMF:
08274 case SIG_FEATB:
08275 case SIG_SF:
08276 case SIG_SFWINK:
08277 case SIG_SF_FEATD:
08278 case SIG_SF_FEATDMF:
08279 case SIG_SF_FEATB:
08280 if (ast->_state == AST_STATE_PRERING)
08281 ast_setstate(ast, AST_STATE_RING);
08282 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08283 ast_debug(1, "Ring detected\n");
08284 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08285 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08286 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08287 ast_debug(1, "Line answered\n");
08288 if (p->confirmanswer) {
08289 p->subs[idx].f.frametype = AST_FRAME_NULL;
08290 p->subs[idx].f.subclass.integer = 0;
08291 } else {
08292 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08293 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08294 ast_setstate(ast, AST_STATE_UP);
08295 }
08296 } else if (ast->_state != AST_STATE_RING)
08297 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08298 break;
08299 default:
08300 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08301 }
08302 break;
08303 case DAHDI_EVENT_RINGBEGIN:
08304 switch (p->sig) {
08305 case SIG_FXSLS:
08306 case SIG_FXSGS:
08307 case SIG_FXSKS:
08308 if (ast->_state == AST_STATE_RING) {
08309 p->ringt = p->ringt_base;
08310 }
08311 break;
08312 }
08313 break;
08314 case DAHDI_EVENT_RINGERON:
08315 break;
08316 case DAHDI_EVENT_NOALARM:
08317 switch (p->sig) {
08318 #if defined(HAVE_PRI)
08319 case SIG_PRI_LIB_HANDLE_CASES:
08320 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08321 break;
08322 #endif
08323 #if defined(HAVE_SS7)
08324 case SIG_SS7:
08325 sig_ss7_set_alarm(p->sig_pvt, 0);
08326 break;
08327 #endif
08328 default:
08329 p->inalarm = 0;
08330 break;
08331 }
08332 handle_clear_alarms(p);
08333 break;
08334 case DAHDI_EVENT_WINKFLASH:
08335 if (p->inalarm) break;
08336 if (p->radio) break;
08337 if (p->oprmode < 0) break;
08338 if (p->oprmode > 1)
08339 {
08340 struct dahdi_params par;
08341
08342 memset(&par, 0, sizeof(par));
08343 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08344 {
08345 if (!par.rxisoffhook)
08346 {
08347
08348 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08349 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08350 save_conference(p);
08351 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08352 }
08353 }
08354 break;
08355 }
08356
08357 p->flashtime = ast_tvnow();
08358 switch (mysig) {
08359 case SIG_FXOLS:
08360 case SIG_FXOGS:
08361 case SIG_FXOKS:
08362 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08363 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08364
08365
08366 ast_free(p->cidspill);
08367 p->cidspill = NULL;
08368 restore_conference(p);
08369 p->callwaitcas = 0;
08370
08371 if (idx != SUB_REAL) {
08372 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08373 goto winkflashdone;
08374 }
08375
08376 if (p->subs[SUB_CALLWAIT].owner) {
08377
08378 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08379 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08380 p->owner = p->subs[SUB_REAL].owner;
08381 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08382 if (p->owner->_state == AST_STATE_RINGING) {
08383 ast_setstate(p->owner, AST_STATE_UP);
08384 p->subs[SUB_REAL].needanswer = 1;
08385 }
08386 p->callwaitingrepeat = 0;
08387 p->cidcwexpire = 0;
08388 p->cid_suppress_expire = 0;
08389
08390 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08391 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08392 S_OR(p->mohsuggest, NULL),
08393 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08394 }
08395 p->subs[SUB_CALLWAIT].needhold = 1;
08396 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08397 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08398 S_OR(p->mohsuggest, NULL),
08399 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08400 }
08401 p->subs[SUB_REAL].needunhold = 1;
08402 } else if (!p->subs[SUB_THREEWAY].owner) {
08403 if (!p->threewaycalling) {
08404
08405 p->subs[SUB_REAL].needflash = 1;
08406 goto winkflashdone;
08407 } else if (!check_for_conference(p)) {
08408 char cid_num[256];
08409 char cid_name[256];
08410
08411 cid_num[0] = 0;
08412 cid_name[0] = 0;
08413 if (p->dahditrcallerid && p->owner) {
08414 if (p->owner->caller.id.number.valid
08415 && p->owner->caller.id.number.str) {
08416 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08417 sizeof(cid_num));
08418 }
08419 if (p->owner->caller.id.name.valid
08420 && p->owner->caller.id.name.str) {
08421 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08422 sizeof(cid_name));
08423 }
08424 }
08425
08426
08427 if (!((ast->pbx) ||
08428 (ast->_state == AST_STATE_UP) ||
08429 (ast->_state == AST_STATE_RING))) {
08430 ast_debug(1, "Flash when call not up or ringing\n");
08431 goto winkflashdone;
08432 }
08433 if (alloc_sub(p, SUB_THREEWAY)) {
08434 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08435 goto winkflashdone;
08436 }
08437
08438 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08439 if (p->dahditrcallerid) {
08440 if (!p->origcid_num)
08441 p->origcid_num = ast_strdup(p->cid_num);
08442 if (!p->origcid_name)
08443 p->origcid_name = ast_strdup(p->cid_name);
08444 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08445 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08446 }
08447
08448 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08449
08450 dahdi_disable_ec(p);
08451 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08452 if (res)
08453 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08454 p->owner = chan;
08455 if (!chan) {
08456 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08457 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08458 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08459 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08460 dahdi_enable_ec(p);
08461 ast_hangup(chan);
08462 } else {
08463 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08464
08465
08466 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08467 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08468 S_OR(p->mohsuggest, NULL),
08469 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08470 }
08471 p->subs[SUB_THREEWAY].needhold = 1;
08472 }
08473 }
08474 } else {
08475
08476 if (p->subs[SUB_THREEWAY].inthreeway) {
08477
08478 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08479
08480 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08481
08482 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08483 p->owner = p->subs[SUB_REAL].owner;
08484 }
08485
08486 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08487 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08488 p->subs[SUB_REAL].inthreeway = 0;
08489 p->subs[SUB_THREEWAY].inthreeway = 0;
08490 } else {
08491
08492 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08493 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08494 int otherindex = SUB_THREEWAY;
08495
08496 ast_verb(3, "Building conference call with %s and %s\n",
08497 p->subs[SUB_THREEWAY].owner->name,
08498 p->subs[SUB_REAL].owner->name);
08499
08500 p->subs[SUB_THREEWAY].inthreeway = 1;
08501 p->subs[SUB_REAL].inthreeway = 1;
08502 if (ast->_state == AST_STATE_UP) {
08503 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08504 otherindex = SUB_REAL;
08505 }
08506 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08507 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08508 p->subs[otherindex].needunhold = 1;
08509 p->owner = p->subs[SUB_REAL].owner;
08510 } else {
08511 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08512 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08513 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08514 p->owner = p->subs[SUB_REAL].owner;
08515 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08516 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08517 p->subs[SUB_REAL].needunhold = 1;
08518 dahdi_enable_ec(p);
08519 }
08520 }
08521 }
08522 winkflashdone:
08523 update_conf(p);
08524 break;
08525 case SIG_EM:
08526 case SIG_EM_E1:
08527 case SIG_FEATD:
08528 case SIG_SF:
08529 case SIG_SFWINK:
08530 case SIG_SF_FEATD:
08531 case SIG_FXSLS:
08532 case SIG_FXSGS:
08533 if (p->dialing)
08534 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08535 else
08536 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08537 break;
08538 case SIG_FEATDMF_TA:
08539 switch (p->whichwink) {
08540 case 0:
08541 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08542 S_COR(p->owner->caller.ani.number.valid,
08543 p->owner->caller.ani.number.str, ""));
08544 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08545 p->owner->caller.ani2,
08546 S_COR(p->owner->caller.ani.number.valid,
08547 p->owner->caller.ani.number.str, ""));
08548 break;
08549 case 1:
08550 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08551 break;
08552 case 2:
08553 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08554 return NULL;
08555 }
08556 p->whichwink++;
08557
08558 case SIG_FEATDMF:
08559 case SIG_E911:
08560 case SIG_FGC_CAMAMF:
08561 case SIG_FGC_CAMA:
08562 case SIG_FEATB:
08563 case SIG_SF_FEATDMF:
08564 case SIG_SF_FEATB:
08565 case SIG_EMWINK:
08566
08567 if (!ast_strlen_zero(p->dop.dialstr)) {
08568 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08569 if (res < 0) {
08570 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08571 p->dop.dialstr[0] = '\0';
08572 return NULL;
08573 } else
08574 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08575 }
08576 p->dop.dialstr[0] = '\0';
08577 break;
08578 default:
08579 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08580 }
08581 break;
08582 case DAHDI_EVENT_HOOKCOMPLETE:
08583 if (p->inalarm) break;
08584 if ((p->radio || (p->oprmode < 0))) break;
08585 if (p->waitingfordt.tv_sec) break;
08586 switch (mysig) {
08587 case SIG_FXSLS:
08588 case SIG_FXSGS:
08589 case SIG_FXSKS:
08590 case SIG_EM:
08591 case SIG_EM_E1:
08592 case SIG_EMWINK:
08593 case SIG_FEATD:
08594 case SIG_SF:
08595 case SIG_SFWINK:
08596 case SIG_SF_FEATD:
08597 if (!ast_strlen_zero(p->dop.dialstr)) {
08598 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08599 if (res < 0) {
08600 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08601 p->dop.dialstr[0] = '\0';
08602 return NULL;
08603 } else
08604 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08605 }
08606 p->dop.dialstr[0] = '\0';
08607 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08608 break;
08609 case SIG_FEATDMF:
08610 case SIG_FEATDMF_TA:
08611 case SIG_E911:
08612 case SIG_FGC_CAMA:
08613 case SIG_FGC_CAMAMF:
08614 case SIG_FEATB:
08615 case SIG_SF_FEATDMF:
08616 case SIG_SF_FEATB:
08617 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08618 break;
08619 default:
08620 break;
08621 }
08622 break;
08623 case DAHDI_EVENT_POLARITY:
08624
08625
08626
08627
08628
08629
08630 if (p->polarity == POLARITY_IDLE) {
08631 p->polarity = POLARITY_REV;
08632 if (p->answeronpolarityswitch &&
08633 ((ast->_state == AST_STATE_DIALING) ||
08634 (ast->_state == AST_STATE_RINGING))) {
08635 ast_debug(1, "Answering on polarity switch!\n");
08636 ast_setstate(p->owner, AST_STATE_UP);
08637 if (p->hanguponpolarityswitch) {
08638 p->polaritydelaytv = ast_tvnow();
08639 }
08640 } else
08641 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08642 }
08643
08644
08645 if (p->hanguponpolarityswitch &&
08646 (p->polarityonanswerdelay > 0) &&
08647 (p->polarity == POLARITY_REV) &&
08648 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08649
08650 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) );
08651
08652 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08653 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08654 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08655 p->polarity = POLARITY_IDLE;
08656 } else
08657 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);
08658
08659 } else {
08660 p->polarity = POLARITY_IDLE;
08661 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08662 }
08663
08664 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) );
08665 break;
08666 default:
08667 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08668 }
08669 return &p->subs[idx].f;
08670 }
08671
08672 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08673 {
08674 int res;
08675 int idx;
08676 struct ast_frame *f;
08677 int usedindex = -1;
08678 struct dahdi_pvt *p = ast->tech_pvt;
08679
08680 idx = dahdi_get_index(ast, p, 1);
08681
08682 p->subs[idx].f.frametype = AST_FRAME_NULL;
08683 p->subs[idx].f.datalen = 0;
08684 p->subs[idx].f.samples = 0;
08685 p->subs[idx].f.mallocd = 0;
08686 p->subs[idx].f.offset = 0;
08687 p->subs[idx].f.subclass.integer = 0;
08688 p->subs[idx].f.delivery = ast_tv(0,0);
08689 p->subs[idx].f.src = "dahdi_exception";
08690 p->subs[idx].f.data.ptr = NULL;
08691
08692
08693 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08694
08695
08696
08697
08698
08699 if (p->fake_event) {
08700 res = p->fake_event;
08701 p->fake_event = 0;
08702 } else
08703 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08704
08705 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08706 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08707 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08708 p->owner = p->subs[SUB_REAL].owner;
08709 if (p->owner && ast_bridged_channel(p->owner))
08710 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08711 p->subs[SUB_REAL].needunhold = 1;
08712 }
08713 switch (res) {
08714 case DAHDI_EVENT_ONHOOK:
08715 dahdi_disable_ec(p);
08716 if (p->owner) {
08717 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08718 dahdi_ring_phone(p);
08719 p->callwaitingrepeat = 0;
08720 p->cidcwexpire = 0;
08721 p->cid_suppress_expire = 0;
08722 } else
08723 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08724 update_conf(p);
08725 break;
08726 case DAHDI_EVENT_RINGOFFHOOK:
08727 dahdi_enable_ec(p);
08728 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08729 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08730 p->subs[SUB_REAL].needanswer = 1;
08731 p->dialing = 0;
08732 }
08733 break;
08734 case DAHDI_EVENT_HOOKCOMPLETE:
08735 case DAHDI_EVENT_RINGERON:
08736 case DAHDI_EVENT_RINGEROFF:
08737
08738 break;
08739 case DAHDI_EVENT_WINKFLASH:
08740 p->flashtime = ast_tvnow();
08741 if (p->owner) {
08742 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08743 if (p->owner->_state != AST_STATE_UP) {
08744
08745 usedindex = dahdi_get_index(p->owner, p, 0);
08746 if (usedindex > -1) {
08747 p->subs[usedindex].needanswer = 1;
08748 }
08749 ast_setstate(p->owner, AST_STATE_UP);
08750 }
08751 p->callwaitingrepeat = 0;
08752 p->cidcwexpire = 0;
08753 p->cid_suppress_expire = 0;
08754 if (ast_bridged_channel(p->owner))
08755 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08756 p->subs[SUB_REAL].needunhold = 1;
08757 } else
08758 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08759 update_conf(p);
08760 break;
08761 default:
08762 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08763 }
08764 f = &p->subs[idx].f;
08765 return f;
08766 }
08767 if (!(p->radio || (p->oprmode < 0)))
08768 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08769
08770 if (ast != p->owner) {
08771 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08772 f = &p->subs[idx].f;
08773 return f;
08774 }
08775 f = dahdi_handle_event(ast);
08776
08777
08778 if (f == NULL) {
08779 ast_set_hangupsource(ast, ast->name, 0);
08780 }
08781
08782 return f;
08783 }
08784
08785 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08786 {
08787 struct dahdi_pvt *p = ast->tech_pvt;
08788 struct ast_frame *f;
08789 ast_mutex_lock(&p->lock);
08790 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08791 struct analog_pvt *analog_p = p->sig_pvt;
08792 f = analog_exception(analog_p, ast);
08793 } else {
08794 f = __dahdi_exception(ast);
08795 }
08796 ast_mutex_unlock(&p->lock);
08797 return f;
08798 }
08799
08800 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08801 {
08802 struct dahdi_pvt *p;
08803 int res;
08804 int idx;
08805 void *readbuf;
08806 struct ast_frame *f;
08807
08808
08809
08810
08811
08812
08813 p = ast->tech_pvt;
08814 while (ast_mutex_trylock(&p->lock)) {
08815 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08816
08817
08818
08819
08820
08821
08822 p = ast->tech_pvt;
08823 }
08824
08825 idx = dahdi_get_index(ast, p, 0);
08826
08827
08828 if (idx < 0) {
08829 ast_log(LOG_WARNING, "We don't exist?\n");
08830 ast_mutex_unlock(&p->lock);
08831 return NULL;
08832 }
08833
08834 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08835 ast_mutex_unlock(&p->lock);
08836 return NULL;
08837 }
08838
08839 p->subs[idx].f.frametype = AST_FRAME_NULL;
08840 p->subs[idx].f.datalen = 0;
08841 p->subs[idx].f.samples = 0;
08842 p->subs[idx].f.mallocd = 0;
08843 p->subs[idx].f.offset = 0;
08844 p->subs[idx].f.subclass.integer = 0;
08845 p->subs[idx].f.delivery = ast_tv(0,0);
08846 p->subs[idx].f.src = "dahdi_read";
08847 p->subs[idx].f.data.ptr = NULL;
08848
08849
08850 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08851 {
08852 struct dahdi_params ps;
08853
08854 memset(&ps, 0, sizeof(ps));
08855 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08856 ast_mutex_unlock(&p->lock);
08857 return NULL;
08858 }
08859 p->firstradio = 1;
08860 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08861 if (ps.rxisoffhook)
08862 {
08863 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08864 }
08865 else
08866 {
08867 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08868 }
08869 ast_mutex_unlock(&p->lock);
08870 return &p->subs[idx].f;
08871 }
08872 if (p->ringt > 0) {
08873 if (!(--p->ringt)) {
08874 ast_mutex_unlock(&p->lock);
08875 return NULL;
08876 }
08877 }
08878
08879 #ifdef HAVE_OPENR2
08880 if (p->mfcr2) {
08881 openr2_chan_process_event(p->r2chan);
08882 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08883 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08884
08885
08886 if (p->mfcr2_call_accepted &&
08887 !p->mfcr2_progress &&
08888 ast->_state == AST_STATE_RINGING) {
08889 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08890 ast_queue_frame(p->owner, &f);
08891 p->mfcr2_progress = 1;
08892 }
08893 }
08894 }
08895 #endif
08896
08897 if (p->subs[idx].needringing) {
08898
08899 p->subs[idx].needringing = 0;
08900 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08901 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08902 ast_setstate(ast, AST_STATE_RINGING);
08903 ast_mutex_unlock(&p->lock);
08904 return &p->subs[idx].f;
08905 }
08906
08907 if (p->subs[idx].needbusy) {
08908
08909 p->subs[idx].needbusy = 0;
08910 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08911 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08912 ast_mutex_unlock(&p->lock);
08913 return &p->subs[idx].f;
08914 }
08915
08916 if (p->subs[idx].needcongestion) {
08917
08918 p->subs[idx].needcongestion = 0;
08919 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08920 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08921 ast_mutex_unlock(&p->lock);
08922 return &p->subs[idx].f;
08923 }
08924
08925 if (p->subs[idx].needanswer) {
08926
08927 p->subs[idx].needanswer = 0;
08928 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08929 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08930 ast_mutex_unlock(&p->lock);
08931 return &p->subs[idx].f;
08932 }
08933 #ifdef HAVE_OPENR2
08934 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08935
08936
08937
08938
08939 ast_mutex_unlock(&p->lock);
08940 return &ast_null_frame;
08941 }
08942 #endif
08943
08944 if (p->subs[idx].needflash) {
08945
08946 p->subs[idx].needflash = 0;
08947 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08948 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08949 ast_mutex_unlock(&p->lock);
08950 return &p->subs[idx].f;
08951 }
08952
08953 if (p->subs[idx].needhold) {
08954
08955 p->subs[idx].needhold = 0;
08956 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08957 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08958 ast_mutex_unlock(&p->lock);
08959 ast_debug(1, "Sending hold on '%s'\n", ast->name);
08960 return &p->subs[idx].f;
08961 }
08962
08963 if (p->subs[idx].needunhold) {
08964
08965 p->subs[idx].needunhold = 0;
08966 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08967 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08968 ast_mutex_unlock(&p->lock);
08969 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08970 return &p->subs[idx].f;
08971 }
08972
08973
08974
08975
08976
08977 if (p->fake_event && p->owner == ast) {
08978 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08979 struct analog_pvt *analog_p = p->sig_pvt;
08980
08981 f = analog_exception(analog_p, ast);
08982 } else {
08983 f = __dahdi_exception(ast);
08984 }
08985 ast_mutex_unlock(&p->lock);
08986 return f;
08987 }
08988
08989 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08990 if (!p->subs[idx].linear) {
08991 p->subs[idx].linear = 1;
08992 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08993 if (res)
08994 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08995 }
08996 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08997 (ast->rawreadformat == AST_FORMAT_ALAW)) {
08998 if (p->subs[idx].linear) {
08999 p->subs[idx].linear = 0;
09000 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09001 if (res)
09002 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09003 }
09004 } else {
09005 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09006 ast_mutex_unlock(&p->lock);
09007 return NULL;
09008 }
09009 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09010 CHECK_BLOCKING(ast);
09011 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09012 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09013
09014 if (res < 0) {
09015 f = NULL;
09016 if (res == -1) {
09017 if (errno == EAGAIN) {
09018
09019 ast_mutex_unlock(&p->lock);
09020 return &p->subs[idx].f;
09021 } else if (errno == ELAST) {
09022 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09023 struct analog_pvt *analog_p = p->sig_pvt;
09024 f = analog_exception(analog_p, ast);
09025 } else {
09026 f = __dahdi_exception(ast);
09027 }
09028 } else
09029 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09030 }
09031 ast_mutex_unlock(&p->lock);
09032 return f;
09033 }
09034 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09035 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09036 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09037 struct analog_pvt *analog_p = p->sig_pvt;
09038 f = analog_exception(analog_p, ast);
09039 } else {
09040 f = __dahdi_exception(ast);
09041 }
09042 ast_mutex_unlock(&p->lock);
09043 return f;
09044 }
09045 if (p->tdd) {
09046 int c;
09047
09048 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09049 if (c < 0) {
09050 ast_debug(1,"tdd_feed failed\n");
09051 ast_mutex_unlock(&p->lock);
09052 return NULL;
09053 }
09054 if (c) {
09055 p->subs[idx].f.subclass.integer = 0;
09056 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09057 p->subs[idx].f.mallocd = 0;
09058 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09059 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09060 p->subs[idx].f.datalen = 1;
09061 *((char *) p->subs[idx].f.data.ptr) = c;
09062 ast_mutex_unlock(&p->lock);
09063 return &p->subs[idx].f;
09064 }
09065 }
09066 if (idx == SUB_REAL) {
09067
09068 if (p->cidcwexpire) {
09069 if (!--p->cidcwexpire) {
09070
09071 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09072 restore_conference(p);
09073 }
09074 }
09075 if (p->cid_suppress_expire) {
09076 --p->cid_suppress_expire;
09077 }
09078 if (p->callwaitingrepeat) {
09079 if (!--p->callwaitingrepeat) {
09080
09081 ++p->callwaitrings;
09082 dahdi_callwait(ast);
09083 }
09084 }
09085 }
09086 if (p->subs[idx].linear) {
09087 p->subs[idx].f.datalen = READ_SIZE * 2;
09088 } else
09089 p->subs[idx].f.datalen = READ_SIZE;
09090
09091
09092 if ((p->owner == ast) && p->cidspill) {
09093 send_callerid(p);
09094 }
09095
09096 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09097 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09098 p->subs[idx].f.samples = READ_SIZE;
09099 p->subs[idx].f.mallocd = 0;
09100 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09101 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09102 #if 0
09103 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09104 #endif
09105 if (p->dialing || p->radio ||
09106 (idx && (ast->_state != AST_STATE_UP)) ||
09107 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09108 ) {
09109
09110
09111 p->subs[idx].f.frametype = AST_FRAME_NULL;
09112 p->subs[idx].f.subclass.integer = 0;
09113 p->subs[idx].f.samples = 0;
09114 p->subs[idx].f.mallocd = 0;
09115 p->subs[idx].f.offset = 0;
09116 p->subs[idx].f.data.ptr = NULL;
09117 p->subs[idx].f.datalen= 0;
09118 }
09119 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09120
09121 int mute;
09122
09123 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09124
09125
09126 mute = ast_dsp_was_muted(p->dsp);
09127 if (p->muting != mute) {
09128 p->muting = mute;
09129 dahdi_confmute(p, mute);
09130 }
09131
09132 if (f) {
09133 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09134 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09135
09136
09137 f = NULL;
09138 }
09139 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09140 || f->frametype == AST_FRAME_DTMF_END) {
09141 #ifdef HAVE_PRI
09142 if (dahdi_sig_pri_lib_handles(p->sig)
09143 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09144 && p->pri
09145 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09146 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09147
09148 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09149 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09150 f->subclass.integer, f->subclass.integer, ast->name);
09151
09152 f->frametype = AST_FRAME_NULL;
09153 f->subclass.integer = 0;
09154 }
09155 #endif
09156
09157 p->pulsedial = 0;
09158 } else if (p->waitingfordt.tv_sec) {
09159 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09160 p->waitingfordt.tv_sec = 0;
09161 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09162 f=NULL;
09163 } else if (f->frametype == AST_FRAME_VOICE) {
09164 f->frametype = AST_FRAME_NULL;
09165 f->subclass.integer = 0;
09166 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) {
09167 p->waitingfordt.tv_sec = 0;
09168 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09169 ast_dsp_set_features(p->dsp, p->dsp_features);
09170 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09171 if (!ast_strlen_zero(p->dop.dialstr)) {
09172 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09173 if (res < 0) {
09174 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09175 p->dop.dialstr[0] = '\0';
09176 ast_mutex_unlock(&p->lock);
09177 return NULL;
09178 } else {
09179 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09180 p->dialing = 1;
09181 p->dop.dialstr[0] = '\0';
09182 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09183 ast_setstate(ast, AST_STATE_DIALING);
09184 }
09185 }
09186 }
09187 }
09188 }
09189 }
09190 } else
09191 f = &p->subs[idx].f;
09192
09193 if (f) {
09194 switch (f->frametype) {
09195 case AST_FRAME_DTMF_BEGIN:
09196 case AST_FRAME_DTMF_END:
09197 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09198 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09199 } else {
09200 dahdi_handle_dtmf(ast, idx, &f);
09201 }
09202 break;
09203 case AST_FRAME_VOICE:
09204 if (p->cidspill || p->cid_suppress_expire) {
09205
09206 p->subs[idx].f.frametype = AST_FRAME_NULL;
09207 p->subs[idx].f.subclass.integer = 0;
09208 p->subs[idx].f.samples = 0;
09209 p->subs[idx].f.mallocd = 0;
09210 p->subs[idx].f.offset = 0;
09211 p->subs[idx].f.data.ptr = NULL;
09212 p->subs[idx].f.datalen= 0;
09213 }
09214 break;
09215 default:
09216 break;
09217 }
09218 }
09219
09220 ast_mutex_unlock(&p->lock);
09221 return f;
09222 }
09223
09224 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09225 {
09226 int sent=0;
09227 int size;
09228 int res;
09229 int fd;
09230 fd = p->subs[idx].dfd;
09231 while (len) {
09232 size = len;
09233 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09234 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09235 res = write(fd, buf, size);
09236 if (res != size) {
09237 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09238 return sent;
09239 }
09240 len -= size;
09241 buf += size;
09242 }
09243 return sent;
09244 }
09245
09246 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09247 {
09248 struct dahdi_pvt *p = ast->tech_pvt;
09249 int res;
09250 int idx;
09251 idx = dahdi_get_index(ast, p, 0);
09252 if (idx < 0) {
09253 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09254 return -1;
09255 }
09256
09257
09258 if (frame->frametype != AST_FRAME_VOICE) {
09259 if (frame->frametype != AST_FRAME_IMAGE)
09260 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09261 return 0;
09262 }
09263 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09264 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09265 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09266 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09267 return -1;
09268 }
09269 if (p->dialing) {
09270 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09271 return 0;
09272 }
09273 if (!p->owner) {
09274 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09275 return 0;
09276 }
09277 if (p->cidspill) {
09278 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09279 ast->name);
09280 return 0;
09281 }
09282
09283 if (!frame->data.ptr || !frame->datalen)
09284 return 0;
09285
09286 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09287 if (!p->subs[idx].linear) {
09288 p->subs[idx].linear = 1;
09289 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09290 if (res)
09291 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09292 }
09293 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09294 } else {
09295
09296 if (p->subs[idx].linear) {
09297 p->subs[idx].linear = 0;
09298 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09299 if (res)
09300 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09301 }
09302 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09303 }
09304 if (res < 0) {
09305 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09306 return -1;
09307 }
09308 return 0;
09309 }
09310
09311 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09312 {
09313 struct dahdi_pvt *p = chan->tech_pvt;
09314 int res=-1;
09315 int idx;
09316 int func = DAHDI_FLASH;
09317
09318 ast_mutex_lock(&p->lock);
09319 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09320 switch (p->sig) {
09321 #if defined(HAVE_PRI)
09322 case SIG_PRI_LIB_HANDLE_CASES:
09323 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09324 ast_mutex_unlock(&p->lock);
09325 return res;
09326 #endif
09327 #if defined(HAVE_SS7)
09328 case SIG_SS7:
09329 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09330 ast_mutex_unlock(&p->lock);
09331 return res;
09332 #endif
09333 default:
09334 break;
09335 }
09336 #ifdef HAVE_OPENR2
09337 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09338 ast_mutex_unlock(&p->lock);
09339
09340
09341 return 0;
09342 }
09343 #endif
09344 idx = dahdi_get_index(chan, p, 0);
09345 if (idx == SUB_REAL) {
09346 switch (condition) {
09347 case AST_CONTROL_BUSY:
09348 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09349 break;
09350 case AST_CONTROL_RINGING:
09351 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09352
09353 if (chan->_state != AST_STATE_UP) {
09354 if ((chan->_state != AST_STATE_RING) ||
09355 ((p->sig != SIG_FXSKS) &&
09356 (p->sig != SIG_FXSLS) &&
09357 (p->sig != SIG_FXSGS)))
09358 ast_setstate(chan, AST_STATE_RINGING);
09359 }
09360 break;
09361 case AST_CONTROL_INCOMPLETE:
09362 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09363
09364 res = 0;
09365 break;
09366 case AST_CONTROL_PROCEEDING:
09367 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09368
09369 res = 0;
09370 break;
09371 case AST_CONTROL_PROGRESS:
09372 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09373
09374 res = 0;
09375 break;
09376 case AST_CONTROL_CONGESTION:
09377
09378 switch (chan->hangupcause) {
09379 case AST_CAUSE_USER_BUSY:
09380 case AST_CAUSE_NORMAL_CLEARING:
09381 case 0:
09382
09383 chan->hangupcause = AST_CAUSE_CONGESTION;
09384 break;
09385 default:
09386 break;
09387 }
09388 break;
09389 case AST_CONTROL_HOLD:
09390 ast_moh_start(chan, data, p->mohinterpret);
09391 break;
09392 case AST_CONTROL_UNHOLD:
09393 ast_moh_stop(chan);
09394 break;
09395 case AST_CONTROL_RADIO_KEY:
09396 if (p->radio)
09397 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09398 res = 0;
09399 break;
09400 case AST_CONTROL_RADIO_UNKEY:
09401 if (p->radio)
09402 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09403 res = 0;
09404 break;
09405 case AST_CONTROL_FLASH:
09406
09407 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09408
09409 p->dop.dialstr[0] = '\0';
09410 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09411 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09412 chan->name, strerror(errno));
09413 } else
09414 res = 0;
09415 } else
09416 res = 0;
09417 break;
09418 case AST_CONTROL_SRCUPDATE:
09419 res = 0;
09420 break;
09421 case -1:
09422 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09423 break;
09424 }
09425 } else {
09426 res = 0;
09427 }
09428 ast_mutex_unlock(&p->lock);
09429 return res;
09430 }
09431
09432 #if defined(HAVE_PRI)
09433 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09434 #else
09435 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09436 #endif
09437 {
09438 struct ast_str *chan_name;
09439 int x, y;
09440
09441
09442 if (!(chan_name = ast_str_create(32))) {
09443 return NULL;
09444 }
09445 if (i->channel == CHAN_PSEUDO) {
09446 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09447 #if defined(HAVE_PRI)
09448 } else if (i->pri) {
09449 ast_mutex_lock(&i->pri->lock);
09450 y = ++i->pri->new_chan_seq;
09451 if (is_outgoing) {
09452 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09453 address[0] = '\0';
09454 } else if (ast_strlen_zero(i->cid_subaddr)) {
09455
09456 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09457 } else {
09458
09459 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09460 i->cid_subaddr, y);
09461 }
09462 ast_mutex_unlock(&i->pri->lock);
09463 #endif
09464 } else {
09465 y = 1;
09466 do {
09467 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09468 for (x = 0; x < 3; ++x) {
09469 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09470 i->subs[x].owner->name + 6)) {
09471 break;
09472 }
09473 }
09474 ++y;
09475 } while (x < 3);
09476 }
09477 return chan_name;
09478 }
09479
09480 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09481 {
09482 struct ast_channel *tmp;
09483 format_t deflaw;
09484 int x;
09485 int features;
09486 struct ast_str *chan_name;
09487 struct ast_variable *v;
09488 char *dashptr;
09489 char device_name[AST_CHANNEL_NAME];
09490
09491 if (i->subs[idx].owner) {
09492 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09493 return NULL;
09494 }
09495
09496 #if defined(HAVE_PRI)
09497
09498
09499
09500
09501 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09502 #else
09503 chan_name = create_channel_name(i);
09504 #endif
09505 if (!chan_name) {
09506 return NULL;
09507 }
09508
09509 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));
09510 ast_free(chan_name);
09511 if (!tmp)
09512 return NULL;
09513 tmp->tech = &dahdi_tech;
09514 #if defined(HAVE_PRI)
09515 if (i->pri) {
09516 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09517 }
09518 #endif
09519 ast_channel_cc_params_init(tmp, i->cc_params);
09520 if (law) {
09521 i->law = law;
09522 if (law == DAHDI_LAW_ALAW) {
09523 deflaw = AST_FORMAT_ALAW;
09524 } else {
09525 deflaw = AST_FORMAT_ULAW;
09526 }
09527 } else {
09528 switch (i->sig) {
09529 case SIG_PRI_LIB_HANDLE_CASES:
09530
09531 i->law = (i->law_default == DAHDI_LAW_ALAW)
09532 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09533 break;
09534 default:
09535 i->law = i->law_default;
09536 break;
09537 }
09538 if (i->law_default == DAHDI_LAW_ALAW) {
09539 deflaw = AST_FORMAT_ALAW;
09540 } else {
09541 deflaw = AST_FORMAT_ULAW;
09542 }
09543 }
09544 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09545 tmp->nativeformats = deflaw;
09546
09547 tmp->rawreadformat = deflaw;
09548 tmp->readformat = deflaw;
09549 tmp->rawwriteformat = deflaw;
09550 tmp->writeformat = deflaw;
09551 i->subs[idx].linear = 0;
09552 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09553 features = 0;
09554 if (idx == SUB_REAL) {
09555 if (i->busydetect && CANBUSYDETECT(i))
09556 features |= DSP_FEATURE_BUSY_DETECT;
09557 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09558 features |= DSP_FEATURE_CALL_PROGRESS;
09559 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09560 features |= DSP_FEATURE_WAITDIALTONE;
09561 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09562 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09563 features |= DSP_FEATURE_FAX_DETECT;
09564 }
09565 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09566 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09567 i->hardwaredtmf = 0;
09568 features |= DSP_FEATURE_DIGIT_DETECT;
09569 } else if (NEED_MFDETECT(i)) {
09570 i->hardwaredtmf = 1;
09571 features |= DSP_FEATURE_DIGIT_DETECT;
09572 }
09573 }
09574 if (features) {
09575 if (i->dsp) {
09576 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09577 } else {
09578 if (i->channel != CHAN_PSEUDO)
09579 i->dsp = ast_dsp_new();
09580 else
09581 i->dsp = NULL;
09582 if (i->dsp) {
09583 i->dsp_features = features;
09584 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09585
09586 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09587
09588
09589 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09590 features = 0;
09591 }
09592 #endif
09593 ast_dsp_set_features(i->dsp, features);
09594 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09595 if (!ast_strlen_zero(progzone))
09596 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09597 if (i->busydetect && CANBUSYDETECT(i)) {
09598 if(i->silencethreshold > 0)
09599 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09600 ast_dsp_set_busy_count(i->dsp, i->busycount);
09601 if(i->busytonelength > 0)
09602 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09603 if((i->busytonelength == i->busyquietlength) && i->busycompare)
09604 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09605 }
09606 }
09607 }
09608 }
09609
09610 if (state == AST_STATE_RING)
09611 tmp->rings = 1;
09612 tmp->tech_pvt = i;
09613 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09614
09615 tmp->callgroup = i->callgroup;
09616 tmp->pickupgroup = i->pickupgroup;
09617 }
09618 if (!ast_strlen_zero(i->parkinglot))
09619 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09620 if (!ast_strlen_zero(i->language))
09621 ast_string_field_set(tmp, language, i->language);
09622 if (!i->owner)
09623 i->owner = tmp;
09624 if (!ast_strlen_zero(i->accountcode))
09625 ast_string_field_set(tmp, accountcode, i->accountcode);
09626 if (i->amaflags)
09627 tmp->amaflags = i->amaflags;
09628 i->subs[idx].owner = tmp;
09629 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09630 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09631 ast_string_field_set(tmp, call_forward, i->call_forward);
09632 }
09633
09634 if (!i->adsi)
09635 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09636 if (!ast_strlen_zero(i->exten))
09637 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09638 if (!ast_strlen_zero(i->rdnis)) {
09639 tmp->redirecting.from.number.valid = 1;
09640 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09641 }
09642 if (!ast_strlen_zero(i->dnid)) {
09643 tmp->dialed.number.str = ast_strdup(i->dnid);
09644 }
09645
09646
09647
09648 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09649 if (!ast_strlen_zero(i->cid_ani)) {
09650 tmp->caller.ani.number.valid = 1;
09651 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09652 } else if (!ast_strlen_zero(i->cid_num)) {
09653 tmp->caller.ani.number.valid = 1;
09654 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09655 }
09656 #else
09657 if (!ast_strlen_zero(i->cid_num)) {
09658 tmp->caller.ani.number.valid = 1;
09659 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09660 }
09661 #endif
09662 tmp->caller.id.name.presentation = i->callingpres;
09663 tmp->caller.id.number.presentation = i->callingpres;
09664 tmp->caller.id.number.plan = i->cid_ton;
09665 tmp->caller.ani2 = i->cid_ani2;
09666 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09667
09668 i->fake_event = 0;
09669
09670 dahdi_confmute(i, 0);
09671 i->muting = 0;
09672
09673 ast_jb_configure(tmp, &global_jbconf);
09674
09675
09676 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09677 dashptr = strrchr(device_name, '-');
09678 if (dashptr) {
09679 *dashptr = '\0';
09680 }
09681 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09682
09683 for (v = i->vars ; v ; v = v->next)
09684 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09685
09686 ast_module_ref(ast_module_info->self);
09687
09688 dahdi_ami_channel_event(i, tmp);
09689 if (startpbx) {
09690 #ifdef HAVE_OPENR2
09691 if (i->mfcr2call) {
09692 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09693 }
09694 #endif
09695 if (ast_pbx_start(tmp)) {
09696 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09697 ast_hangup(tmp);
09698 return NULL;
09699 }
09700 }
09701 return tmp;
09702 }
09703
09704
09705 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09706 {
09707 char c;
09708
09709 *str = 0;
09710 for (;;)
09711 {
09712
09713 c = ast_waitfordigit(chan, ms);
09714
09715 if (c < 1)
09716 return c;
09717 *str++ = c;
09718 *str = 0;
09719 if (strchr(term, c))
09720 return 1;
09721 }
09722 }
09723
09724 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09725 {
09726 int j;
09727 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09728 for (;;)
09729 {
09730
09731 j = DAHDI_IOMUX_SIGEVENT;
09732
09733 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09734
09735 if (j & DAHDI_IOMUX_SIGEVENT) break;
09736 }
09737
09738 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09739 return 0;
09740 }
09741
09742
09743
09744
09745
09746
09747
09748
09749
09750
09751 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09752 {
09753 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09754 return analog_dnd(dahdichan->sig_pvt, flag);
09755 }
09756
09757 if (flag == -1) {
09758 return dahdichan->dnd;
09759 }
09760
09761
09762 dahdichan->dnd = flag;
09763 ast_verb(3, "%s DND on channel %d\n",
09764 flag? "Enabled" : "Disabled",
09765 dahdichan->channel);
09766 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09767 "Channel: DAHDI/%d\r\n"
09768 "Status: %s\r\n", dahdichan->channel,
09769 flag? "enabled" : "disabled");
09770
09771 return 0;
09772 }
09773
09774 static int canmatch_featurecode(const char *exten)
09775 {
09776 int extlen = strlen(exten);
09777 const char *pickup_ext;
09778 if (!extlen) {
09779 return 1;
09780 }
09781 pickup_ext = ast_pickup_ext();
09782 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09783 return 1;
09784 }
09785
09786 if (exten[0] == '*' && extlen < 3) {
09787 if (extlen == 1) {
09788 return 1;
09789 }
09790
09791 switch (exten[1]) {
09792 case '6':
09793 case '7':
09794 case '8':
09795 return 1;
09796 }
09797 }
09798 return 0;
09799 }
09800
09801 static void *analog_ss_thread(void *data)
09802 {
09803 struct ast_channel *chan = data;
09804 struct dahdi_pvt *p = chan->tech_pvt;
09805 char exten[AST_MAX_EXTENSION] = "";
09806 char exten2[AST_MAX_EXTENSION] = "";
09807 unsigned char buf[256];
09808 char dtmfcid[300];
09809 char dtmfbuf[300];
09810 struct callerid_state *cs = NULL;
09811 char *name = NULL, *number = NULL;
09812 int distMatches;
09813 int curRingData[3];
09814 int receivedRingT;
09815 int counter1;
09816 int counter;
09817 int samples = 0;
09818 struct ast_smdi_md_message *smdi_msg = NULL;
09819 int flags = 0;
09820 int i;
09821 int timeout;
09822 int getforward = 0;
09823 char *s1, *s2;
09824 int len = 0;
09825 int res;
09826 int idx;
09827
09828 ast_mutex_lock(&ss_thread_lock);
09829 ss_thread_count++;
09830 ast_mutex_unlock(&ss_thread_lock);
09831
09832
09833
09834 if (!p) {
09835 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09836 ast_hangup(chan);
09837 goto quit;
09838 }
09839 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09840 idx = dahdi_get_index(chan, p, 1);
09841 if (idx < 0) {
09842 ast_log(LOG_WARNING, "Huh?\n");
09843 ast_hangup(chan);
09844 goto quit;
09845 }
09846 if (p->dsp)
09847 ast_dsp_digitreset(p->dsp);
09848 switch (p->sig) {
09849 case SIG_FEATD:
09850 case SIG_FEATDMF:
09851 case SIG_FEATDMF_TA:
09852 case SIG_E911:
09853 case SIG_FGC_CAMAMF:
09854 case SIG_FEATB:
09855 case SIG_EMWINK:
09856 case SIG_SF_FEATD:
09857 case SIG_SF_FEATDMF:
09858 case SIG_SF_FEATB:
09859 case SIG_SFWINK:
09860 if (dahdi_wink(p, idx))
09861 goto quit;
09862
09863 case SIG_EM:
09864 case SIG_EM_E1:
09865 case SIG_SF:
09866 case SIG_FGC_CAMA:
09867 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09868 if (p->dsp)
09869 ast_dsp_digitreset(p->dsp);
09870
09871 if (p->dsp) {
09872 if (NEED_MFDETECT(p))
09873 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09874 else
09875 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09876 }
09877 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09878
09879 if (!p->immediate)
09880
09881 res = ast_waitfordigit(chan, 5000);
09882 else
09883 res = 0;
09884 if (res > 0) {
09885
09886 dtmfbuf[0] = res;
09887 switch (p->sig) {
09888 case SIG_FEATD:
09889 case SIG_SF_FEATD:
09890 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09891 if (res > 0)
09892 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09893 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09894 break;
09895 case SIG_FEATDMF_TA:
09896 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09897 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09898 if (dahdi_wink(p, idx)) goto quit;
09899 dtmfbuf[0] = 0;
09900
09901 res = ast_waitfordigit(chan, 5000);
09902 if (res <= 0) break;
09903 dtmfbuf[0] = res;
09904
09905 case SIG_FEATDMF:
09906 case SIG_E911:
09907 case SIG_FGC_CAMAMF:
09908 case SIG_SF_FEATDMF:
09909 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09910
09911 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09912 {
09913 if (dahdi_wink(p, idx)) goto quit;
09914 dtmfbuf[0] = 0;
09915
09916 res = ast_waitfordigit(chan, 5000);
09917 if (res <= 0) break;
09918 dtmfbuf[0] = res;
09919 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09920 }
09921 if (res > 0) {
09922
09923 if (p->sig == SIG_E911)
09924 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09925 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09926 }
09927 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09928 break;
09929 case SIG_FEATB:
09930 case SIG_SF_FEATB:
09931 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09932 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09933 break;
09934 case SIG_EMWINK:
09935
09936
09937
09938
09939 if (res == '*') {
09940 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09941 if (res > 0)
09942 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09943 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09944 break;
09945 }
09946 default:
09947
09948 len = 1;
09949 dtmfbuf[len] = '\0';
09950 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09951 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09952 timeout = matchdigittimeout;
09953 } else {
09954 timeout = gendigittimeout;
09955 }
09956 res = ast_waitfordigit(chan, timeout);
09957 if (res < 0) {
09958 ast_debug(1, "waitfordigit returned < 0...\n");
09959 ast_hangup(chan);
09960 goto quit;
09961 } else if (res) {
09962 dtmfbuf[len++] = res;
09963 dtmfbuf[len] = '\0';
09964 } else {
09965 break;
09966 }
09967 }
09968 break;
09969 }
09970 }
09971 if (res == -1) {
09972 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09973 ast_hangup(chan);
09974 goto quit;
09975 } else if (res < 0) {
09976 ast_debug(1, "Got hung up before digits finished\n");
09977 ast_hangup(chan);
09978 goto quit;
09979 }
09980
09981 if (p->sig == SIG_FGC_CAMA) {
09982 char anibuf[100];
09983
09984 if (ast_safe_sleep(chan,1000) == -1) {
09985 ast_hangup(chan);
09986 goto quit;
09987 }
09988 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09989 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09990 res = my_getsigstr(chan, anibuf, "#", 10000);
09991 if ((res > 0) && (strlen(anibuf) > 2)) {
09992 if (anibuf[strlen(anibuf) - 1] == '#')
09993 anibuf[strlen(anibuf) - 1] = 0;
09994 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09995 }
09996 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09997 }
09998
09999 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10000 if (ast_strlen_zero(exten))
10001 ast_copy_string(exten, "s", sizeof(exten));
10002 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10003
10004 if (exten[0] == '*') {
10005 char *stringp=NULL;
10006 ast_copy_string(exten2, exten, sizeof(exten2));
10007
10008 stringp=exten2 +1;
10009 s1 = strsep(&stringp, "*");
10010 s2 = strsep(&stringp, "*");
10011 if (s2) {
10012 if (!ast_strlen_zero(p->cid_num))
10013 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10014 else
10015 ast_set_callerid(chan, s1, NULL, s1);
10016 ast_copy_string(exten, s2, sizeof(exten));
10017 } else
10018 ast_copy_string(exten, s1, sizeof(exten));
10019 } else if (p->sig == SIG_FEATD)
10020 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10021 }
10022 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10023 if (exten[0] == '*') {
10024 char *stringp=NULL;
10025 ast_copy_string(exten2, exten, sizeof(exten2));
10026
10027 stringp=exten2 +1;
10028 s1 = strsep(&stringp, "#");
10029 s2 = strsep(&stringp, "#");
10030 if (s2) {
10031 if (!ast_strlen_zero(p->cid_num))
10032 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10033 else
10034 if (*(s1 + 2))
10035 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10036 ast_copy_string(exten, s2 + 1, sizeof(exten));
10037 } else
10038 ast_copy_string(exten, s1 + 2, sizeof(exten));
10039 } else
10040 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10041 }
10042 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10043 if (exten[0] == '*') {
10044 char *stringp=NULL;
10045 ast_copy_string(exten2, exten, sizeof(exten2));
10046
10047 stringp=exten2 +1;
10048 s1 = strsep(&stringp, "#");
10049 s2 = strsep(&stringp, "#");
10050 if (s2 && (*(s2 + 1) == '0')) {
10051 if (*(s2 + 2))
10052 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10053 }
10054 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10055 else ast_copy_string(exten, "911", sizeof(exten));
10056 } else
10057 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10058 }
10059 if (p->sig == SIG_FEATB) {
10060 if (exten[0] == '*') {
10061 char *stringp=NULL;
10062 ast_copy_string(exten2, exten, sizeof(exten2));
10063
10064 stringp=exten2 +1;
10065 s1 = strsep(&stringp, "#");
10066 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10067 } else
10068 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10069 }
10070 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10071 dahdi_wink(p, idx);
10072
10073
10074
10075 if (ast_safe_sleep(chan, 100)) {
10076 ast_hangup(chan);
10077 goto quit;
10078 }
10079 }
10080 dahdi_enable_ec(p);
10081 if (NEED_MFDETECT(p)) {
10082 if (p->dsp) {
10083 if (!p->hardwaredtmf)
10084 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10085 else {
10086 ast_dsp_free(p->dsp);
10087 p->dsp = NULL;
10088 }
10089 }
10090 }
10091
10092 if (ast_exists_extension(chan, chan->context, exten, 1,
10093 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10094 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10095 if (p->dsp) ast_dsp_digitreset(p->dsp);
10096 res = ast_pbx_run(chan);
10097 if (res) {
10098 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10099 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10100 }
10101 goto quit;
10102 } else {
10103 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10104 sleep(2);
10105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10106 if (res < 0)
10107 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10108 else
10109 sleep(1);
10110 res = ast_streamfile(chan, "ss-noservice", chan->language);
10111 if (res >= 0)
10112 ast_waitstream(chan, "");
10113 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10114 ast_hangup(chan);
10115 goto quit;
10116 }
10117 break;
10118 case SIG_FXOLS:
10119 case SIG_FXOGS:
10120 case SIG_FXOKS:
10121
10122 timeout = firstdigittimeout;
10123
10124
10125 if (p->subs[SUB_THREEWAY].owner)
10126 timeout = 999999;
10127 while (len < AST_MAX_EXTENSION-1) {
10128
10129
10130 if (p->immediate)
10131 res = 's';
10132 else
10133 res = ast_waitfordigit(chan, timeout);
10134 timeout = 0;
10135 if (res < 0) {
10136 ast_debug(1, "waitfordigit returned < 0...\n");
10137 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10138 ast_hangup(chan);
10139 goto quit;
10140 } else if (res) {
10141 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10142 exten[len++]=res;
10143 exten[len] = '\0';
10144 }
10145 if (!ast_ignore_pattern(chan->context, exten))
10146 tone_zone_play_tone(p->subs[idx].dfd, -1);
10147 else
10148 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10149 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10150 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10151 if (getforward) {
10152
10153 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10154 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10155 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10156 if (res)
10157 break;
10158 usleep(500000);
10159 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10160 sleep(1);
10161 memset(exten, 0, sizeof(exten));
10162 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10163 len = 0;
10164 getforward = 0;
10165 } else {
10166 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10167 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10168 if (!ast_strlen_zero(p->cid_num)) {
10169 if (!p->hidecallerid)
10170 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10171 else
10172 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10173 }
10174 if (!ast_strlen_zero(p->cid_name)) {
10175 if (!p->hidecallerid)
10176 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10177 }
10178 ast_setstate(chan, AST_STATE_RING);
10179 dahdi_enable_ec(p);
10180 res = ast_pbx_run(chan);
10181 if (res) {
10182 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10183 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10184 }
10185 goto quit;
10186 }
10187 } else {
10188
10189
10190 timeout = matchdigittimeout;
10191 }
10192 } else if (res == 0) {
10193 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10194 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10195 dahdi_wait_event(p->subs[idx].dfd);
10196 ast_hangup(chan);
10197 goto quit;
10198 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10199 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10200
10201 p->callwaiting = 0;
10202 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10203 if (res) {
10204 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10205 chan->name, strerror(errno));
10206 }
10207 len = 0;
10208 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10209 memset(exten, 0, sizeof(exten));
10210 timeout = firstdigittimeout;
10211
10212 } else if (!strcmp(exten,ast_pickup_ext())) {
10213
10214
10215
10216
10217 if (idx == SUB_REAL) {
10218
10219 if (p->subs[SUB_THREEWAY].owner) {
10220
10221
10222 alloc_sub(p, SUB_CALLWAIT);
10223 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10224 unalloc_sub(p, SUB_THREEWAY);
10225 }
10226 dahdi_enable_ec(p);
10227 if (ast_pickup_call(chan)) {
10228 ast_debug(1, "No call pickup possible...\n");
10229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10230 dahdi_wait_event(p->subs[idx].dfd);
10231 }
10232 ast_hangup(chan);
10233 goto quit;
10234 } else {
10235 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10236 ast_hangup(chan);
10237 goto quit;
10238 }
10239
10240 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10241 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10242
10243 p->hidecallerid = 1;
10244 ast_party_number_free(&chan->caller.id.number);
10245 ast_party_number_init(&chan->caller.id.number);
10246 ast_party_name_free(&chan->caller.id.name);
10247 ast_party_name_init(&chan->caller.id.name);
10248 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10249 if (res) {
10250 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10251 chan->name, strerror(errno));
10252 }
10253 len = 0;
10254 memset(exten, 0, sizeof(exten));
10255 timeout = firstdigittimeout;
10256 } else if (p->callreturn && !strcmp(exten, "*69")) {
10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10258 break;
10259 } else if (!strcmp(exten, "*78")) {
10260 dahdi_dnd(p, 1);
10261
10262 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10263 getforward = 0;
10264 memset(exten, 0, sizeof(exten));
10265 len = 0;
10266 } else if (!strcmp(exten, "*79")) {
10267 dahdi_dnd(p, 0);
10268
10269 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10270 getforward = 0;
10271 memset(exten, 0, sizeof(exten));
10272 len = 0;
10273 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10274 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10275 getforward = 1;
10276 memset(exten, 0, sizeof(exten));
10277 len = 0;
10278 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10279 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10280 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10281 memset(p->call_forward, 0, sizeof(p->call_forward));
10282 getforward = 0;
10283 memset(exten, 0, sizeof(exten));
10284 len = 0;
10285 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10286 p->subs[SUB_THREEWAY].owner &&
10287 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10288
10289
10290 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10291 chan, exten, chan->context, 0, NULL);
10292 ast_verb(3, "Parking call to '%s'\n", chan->name);
10293 break;
10294 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10295 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10296
10297 p->hidecallerid = 0;
10298 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10300 if (res) {
10301 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10302 chan->name, strerror(errno));
10303 }
10304 len = 0;
10305 memset(exten, 0, sizeof(exten));
10306 timeout = firstdigittimeout;
10307 } else if (!strcmp(exten, "*0")) {
10308 struct ast_channel *nbridge =
10309 p->subs[SUB_THREEWAY].owner;
10310 struct dahdi_pvt *pbridge = NULL;
10311
10312 if (nbridge && ast_bridged_channel(nbridge))
10313 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10314 if (nbridge && pbridge &&
10315 (nbridge->tech == &dahdi_tech) &&
10316 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10317 ISTRUNK(pbridge)) {
10318 int func = DAHDI_FLASH;
10319
10320 p->dop.dialstr[0] = '\0';
10321
10322 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10323 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10324 nbridge->name, strerror(errno));
10325 }
10326 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10327 unalloc_sub(p, SUB_THREEWAY);
10328 p->owner = p->subs[SUB_REAL].owner;
10329 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10330 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10331 ast_hangup(chan);
10332 goto quit;
10333 } else {
10334 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10335 dahdi_wait_event(p->subs[idx].dfd);
10336 tone_zone_play_tone(p->subs[idx].dfd, -1);
10337 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10338 unalloc_sub(p, SUB_THREEWAY);
10339 p->owner = p->subs[SUB_REAL].owner;
10340 ast_hangup(chan);
10341 goto quit;
10342 }
10343 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10344 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10345 && !canmatch_featurecode(exten)) {
10346 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10347 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10348 chan->context);
10349 break;
10350 }
10351 if (!timeout)
10352 timeout = gendigittimeout;
10353 if (len && !ast_ignore_pattern(chan->context, exten))
10354 tone_zone_play_tone(p->subs[idx].dfd, -1);
10355 }
10356 break;
10357 case SIG_FXSLS:
10358 case SIG_FXSGS:
10359 case SIG_FXSKS:
10360
10361 if (p->use_smdi && p->smdi_iface) {
10362 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10363
10364 if (smdi_msg != NULL) {
10365 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10366
10367 if (smdi_msg->type == 'B')
10368 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10369 else if (smdi_msg->type == 'N')
10370 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10371
10372 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10373 } else {
10374 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10375 }
10376 }
10377
10378 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10379 number = smdi_msg->calling_st;
10380
10381
10382
10383
10384 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10385 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10386
10387 if (p->cid_signalling == CID_SIG_DTMF) {
10388 int k = 0;
10389 cs = NULL;
10390 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10391 dahdi_setlinear(p->subs[idx].dfd, 0);
10392
10393
10394
10395
10396
10397
10398 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10399 res = 4000;
10400 for (;;) {
10401 struct ast_frame *f;
10402 res = ast_waitfor(chan, res);
10403 if (res <= 0) {
10404
10405
10406
10407
10408
10409 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10410 "Exiting simple switch\n");
10411 ast_hangup(chan);
10412 goto quit;
10413 }
10414 f = ast_read(chan);
10415 if (!f)
10416 break;
10417 if (f->frametype == AST_FRAME_DTMF) {
10418 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10419 dtmfbuf[k++] = f->subclass.integer;
10420 }
10421 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10422 res = 4000;
10423 }
10424 ast_frfree(f);
10425 if (chan->_state == AST_STATE_RING ||
10426 chan->_state == AST_STATE_RINGING)
10427 break;
10428 }
10429 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10430 dtmfbuf[k] = '\0';
10431 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10432
10433 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10434 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10435 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10436
10437 if (!ast_strlen_zero(dtmfcid))
10438 number = dtmfcid;
10439 else
10440 number = NULL;
10441
10442 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10443 cs = callerid_new(p->cid_signalling);
10444 if (cs) {
10445 samples = 0;
10446 #if 1
10447 bump_gains(p);
10448 #endif
10449
10450 dahdi_setlinear(p->subs[idx].dfd, 0);
10451
10452
10453 for (;;) {
10454 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10455 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10456 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10457 callerid_free(cs);
10458 ast_hangup(chan);
10459 goto quit;
10460 }
10461 if (i & DAHDI_IOMUX_SIGEVENT) {
10462 res = dahdi_get_event(p->subs[idx].dfd);
10463 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10464 if (res == DAHDI_EVENT_NOALARM) {
10465 p->inalarm = 0;
10466 }
10467
10468 if (p->cid_signalling == CID_SIG_V23_JP) {
10469 if (res == DAHDI_EVENT_RINGBEGIN) {
10470 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10471 usleep(1);
10472 }
10473 } else {
10474 res = 0;
10475 break;
10476 }
10477 } else if (i & DAHDI_IOMUX_READ) {
10478 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10479 if (res < 0) {
10480 if (errno != ELAST) {
10481 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10482 callerid_free(cs);
10483 ast_hangup(chan);
10484 goto quit;
10485 }
10486 break;
10487 }
10488 samples += res;
10489
10490 if (p->cid_signalling == CID_SIG_V23_JP) {
10491 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10492 } else {
10493 res = callerid_feed(cs, buf, res, AST_LAW(p));
10494 }
10495 if (res < 0) {
10496
10497
10498
10499
10500 ast_log(LOG_WARNING,
10501 "Failed to decode CallerID on channel '%s'\n",
10502 chan->name);
10503 break;
10504 } else if (res)
10505 break;
10506 else if (samples > (8000 * 10))
10507 break;
10508 }
10509 }
10510 if (res == 1) {
10511 callerid_get(cs, &name, &number, &flags);
10512 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10513 }
10514
10515 if (p->cid_signalling == CID_SIG_V23_JP) {
10516 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10517 usleep(1);
10518 }
10519
10520
10521 res = 4000;
10522 for (;;) {
10523 struct ast_frame *f;
10524 res = ast_waitfor(chan, res);
10525 if (res <= 0) {
10526 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10527 "Exiting simple switch\n");
10528 ast_hangup(chan);
10529 goto quit;
10530 }
10531 if (!(f = ast_read(chan))) {
10532 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10533 ast_hangup(chan);
10534 goto quit;
10535 }
10536 ast_frfree(f);
10537 if (chan->_state == AST_STATE_RING ||
10538 chan->_state == AST_STATE_RINGING)
10539 break;
10540 }
10541
10542
10543
10544 if (p->usedistinctiveringdetection) {
10545 len = 0;
10546 distMatches = 0;
10547
10548 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10549 curRingData[receivedRingT] = 0;
10550 receivedRingT = 0;
10551 counter = 0;
10552 counter1 = 0;
10553
10554 if (strcmp(p->context,p->defcontext) != 0) {
10555 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10556 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10557 }
10558
10559 for (;;) {
10560 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10561 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10562 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10563 callerid_free(cs);
10564 ast_hangup(chan);
10565 goto quit;
10566 }
10567 if (i & DAHDI_IOMUX_SIGEVENT) {
10568 res = dahdi_get_event(p->subs[idx].dfd);
10569 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10570 if (res == DAHDI_EVENT_NOALARM) {
10571 p->inalarm = 0;
10572 }
10573 res = 0;
10574
10575
10576 curRingData[receivedRingT] = p->ringt;
10577
10578 if (p->ringt < p->ringt_base/2)
10579 break;
10580
10581
10582 if (++receivedRingT == ARRAY_LEN(curRingData))
10583 break;
10584 } else if (i & DAHDI_IOMUX_READ) {
10585 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10586 if (res < 0) {
10587 if (errno != ELAST) {
10588 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10589 callerid_free(cs);
10590 ast_hangup(chan);
10591 goto quit;
10592 }
10593 break;
10594 }
10595 if (p->ringt > 0) {
10596 if (!(--p->ringt)) {
10597 res = -1;
10598 break;
10599 }
10600 }
10601 }
10602 }
10603
10604 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10605 for (counter = 0; counter < 3; counter++) {
10606
10607
10608 distMatches = 0;
10609 for (counter1 = 0; counter1 < 3; counter1++) {
10610 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10611 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10612 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10613 curRingData[counter1]);
10614 distMatches++;
10615 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10616 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10617 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10618 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10619 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10620 distMatches++;
10621 }
10622 }
10623
10624 if (distMatches == 3) {
10625
10626 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10627 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10628 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10629 break;
10630 }
10631 }
10632 }
10633
10634 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10635 #if 1
10636 restore_gains(p);
10637 #endif
10638 } else
10639 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10640 } else {
10641 ast_log(LOG_WARNING, "Channel %s in prering "
10642 "state, but I have nothing to do. "
10643 "Terminating simple switch, should be "
10644 "restarted by the actual ring.\n",
10645 chan->name);
10646 ast_hangup(chan);
10647 goto quit;
10648 }
10649 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10650 if (p->cid_signalling == CID_SIG_DTMF) {
10651 int k = 0;
10652 cs = NULL;
10653 dahdi_setlinear(p->subs[idx].dfd, 0);
10654 res = 2000;
10655 for (;;) {
10656 struct ast_frame *f;
10657 res = ast_waitfor(chan, res);
10658 if (res <= 0) {
10659 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10660 "Exiting simple switch\n");
10661 ast_hangup(chan);
10662 goto quit;
10663 }
10664 f = ast_read(chan);
10665 if (!f) {
10666
10667 ast_hangup(chan);
10668 goto quit;
10669 }
10670 if (f->frametype == AST_FRAME_DTMF) {
10671 dtmfbuf[k++] = f->subclass.integer;
10672 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10673 res = 2000;
10674 }
10675 ast_frfree(f);
10676
10677 if (p->ringt_base == p->ringt)
10678 break;
10679 }
10680 dtmfbuf[k] = '\0';
10681 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10682
10683 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10684 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10685 dtmfcid, flags);
10686
10687 if (!ast_strlen_zero(dtmfcid))
10688 number = dtmfcid;
10689 else
10690 number = NULL;
10691
10692 } else {
10693
10694 cs = callerid_new(p->cid_signalling);
10695 if (cs) {
10696 #if 1
10697 bump_gains(p);
10698 #endif
10699 samples = 0;
10700 len = 0;
10701 distMatches = 0;
10702
10703 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10704 curRingData[receivedRingT] = 0;
10705 receivedRingT = 0;
10706 counter = 0;
10707 counter1 = 0;
10708
10709 if (strcmp(p->context,p->defcontext) != 0) {
10710 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10711 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10712 }
10713
10714
10715 dahdi_setlinear(p->subs[idx].dfd, 0);
10716 for (;;) {
10717 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10718 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10719 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10720 callerid_free(cs);
10721 ast_hangup(chan);
10722 goto quit;
10723 }
10724 if (i & DAHDI_IOMUX_SIGEVENT) {
10725 res = dahdi_get_event(p->subs[idx].dfd);
10726 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10727 if (res == DAHDI_EVENT_NOALARM) {
10728 p->inalarm = 0;
10729 }
10730
10731 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10732 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10733 p->polarity = POLARITY_IDLE;
10734 callerid_free(cs);
10735 ast_hangup(chan);
10736 goto quit;
10737 }
10738 res = 0;
10739
10740
10741 curRingData[receivedRingT] = p->ringt;
10742
10743 if (p->ringt < p->ringt_base/2)
10744 break;
10745
10746
10747 if (++receivedRingT == ARRAY_LEN(curRingData))
10748 break;
10749 } else if (i & DAHDI_IOMUX_READ) {
10750 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10751 if (res < 0) {
10752 if (errno != ELAST) {
10753 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10754 callerid_free(cs);
10755 ast_hangup(chan);
10756 goto quit;
10757 }
10758 break;
10759 }
10760 if (p->ringt > 0) {
10761 if (!(--p->ringt)) {
10762 res = -1;
10763 break;
10764 }
10765 }
10766 samples += res;
10767 res = callerid_feed(cs, buf, res, AST_LAW(p));
10768 if (res < 0) {
10769
10770
10771
10772
10773 ast_log(LOG_WARNING,
10774 "Failed to decode CallerID on channel '%s'\n",
10775 chan->name);
10776 break;
10777 } else if (res)
10778 break;
10779 else if (samples > (8000 * 10))
10780 break;
10781 }
10782 }
10783 if (res == 1) {
10784 callerid_get(cs, &name, &number, &flags);
10785 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10786 }
10787 if (distinctiveringaftercid == 1) {
10788
10789 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10790 curRingData[receivedRingT] = 0;
10791 }
10792 receivedRingT = 0;
10793 ast_verb(3, "Detecting post-CID distinctive ring\n");
10794 for (;;) {
10795 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10796 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10797 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10798 callerid_free(cs);
10799 ast_hangup(chan);
10800 goto quit;
10801 }
10802 if (i & DAHDI_IOMUX_SIGEVENT) {
10803 res = dahdi_get_event(p->subs[idx].dfd);
10804 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10805 if (res == DAHDI_EVENT_NOALARM) {
10806 p->inalarm = 0;
10807 }
10808 res = 0;
10809
10810
10811 curRingData[receivedRingT] = p->ringt;
10812
10813 if (p->ringt < p->ringt_base/2)
10814 break;
10815
10816
10817 if (++receivedRingT == ARRAY_LEN(curRingData))
10818 break;
10819 } else if (i & DAHDI_IOMUX_READ) {
10820 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10821 if (res < 0) {
10822 if (errno != ELAST) {
10823 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10824 callerid_free(cs);
10825 ast_hangup(chan);
10826 goto quit;
10827 }
10828 break;
10829 }
10830 if (p->ringt > 0) {
10831 if (!(--p->ringt)) {
10832 res = -1;
10833 break;
10834 }
10835 }
10836 }
10837 }
10838 }
10839 if (p->usedistinctiveringdetection) {
10840
10841 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10842
10843 for (counter = 0; counter < 3; counter++) {
10844
10845
10846
10847 ast_verb(3, "Checking %d,%d,%d\n",
10848 p->drings.ringnum[counter].ring[0],
10849 p->drings.ringnum[counter].ring[1],
10850 p->drings.ringnum[counter].ring[2]);
10851 distMatches = 0;
10852 for (counter1 = 0; counter1 < 3; counter1++) {
10853 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10854 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10855 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10856 curRingData[counter1]);
10857 distMatches++;
10858 }
10859 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10860 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10861 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10862 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10863 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10864 distMatches++;
10865 }
10866 }
10867 if (distMatches == 3) {
10868
10869 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10870 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10871 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10872 break;
10873 }
10874 }
10875 }
10876
10877 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10878 #if 1
10879 restore_gains(p);
10880 #endif
10881 if (res < 0) {
10882 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10883 }
10884 } else
10885 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10886 }
10887 } else
10888 cs = NULL;
10889
10890 if (number)
10891 ast_shrink_phone_number(number);
10892 ast_set_callerid(chan, number, name, number);
10893
10894 if (smdi_msg)
10895 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10896
10897 if (cs)
10898 callerid_free(cs);
10899
10900 my_handle_notify_message(chan, p, flags, -1);
10901
10902 ast_setstate(chan, AST_STATE_RING);
10903 chan->rings = 1;
10904 p->ringt = p->ringt_base;
10905 res = ast_pbx_run(chan);
10906 if (res) {
10907 ast_hangup(chan);
10908 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10909 }
10910 goto quit;
10911 default:
10912 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10913 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10914 if (res < 0)
10915 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10916 }
10917 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10918 if (res < 0)
10919 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10920 ast_hangup(chan);
10921 quit:
10922 ast_mutex_lock(&ss_thread_lock);
10923 ss_thread_count--;
10924 ast_cond_signal(&ss_thread_complete);
10925 ast_mutex_unlock(&ss_thread_lock);
10926 return NULL;
10927 }
10928
10929 struct mwi_thread_data {
10930 struct dahdi_pvt *pvt;
10931 unsigned char buf[READ_SIZE];
10932 size_t len;
10933 };
10934
10935 static int calc_energy(const unsigned char *buf, int len, format_t law)
10936 {
10937 int x;
10938 int sum = 0;
10939
10940 if (!len)
10941 return 0;
10942
10943 for (x = 0; x < len; x++)
10944 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10945
10946 return sum / len;
10947 }
10948
10949 static void *mwi_thread(void *data)
10950 {
10951 struct mwi_thread_data *mtd = data;
10952 struct callerid_state *cs;
10953 pthread_t threadid;
10954 int samples = 0;
10955 char *name, *number;
10956 int flags;
10957 int i, res;
10958 unsigned int spill_done = 0;
10959 int spill_result = -1;
10960
10961 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10962 mtd->pvt->mwimonitoractive = 0;
10963
10964 return NULL;
10965 }
10966
10967 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10968
10969 bump_gains(mtd->pvt);
10970
10971 for (;;) {
10972 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10973 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10974 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10975 goto quit;
10976 }
10977
10978 if (i & DAHDI_IOMUX_SIGEVENT) {
10979 struct ast_channel *chan;
10980
10981
10982
10983
10984 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10985
10986 switch (res) {
10987 case DAHDI_EVENT_NEONMWI_ACTIVE:
10988 case DAHDI_EVENT_NEONMWI_INACTIVE:
10989 case DAHDI_EVENT_NONE:
10990 case DAHDI_EVENT_BITSCHANGED:
10991 break;
10992 case DAHDI_EVENT_NOALARM:
10993 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10994 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10995
10996 analog_p->inalarm = 0;
10997 }
10998 mtd->pvt->inalarm = 0;
10999 handle_clear_alarms(mtd->pvt);
11000 break;
11001 case DAHDI_EVENT_ALARM:
11002 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11003 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11004
11005 analog_p->inalarm = 1;
11006 }
11007 mtd->pvt->inalarm = 1;
11008 res = get_alarms(mtd->pvt);
11009 handle_alarms(mtd->pvt, res);
11010 break;
11011 default:
11012 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11013 callerid_free(cs);
11014
11015 restore_gains(mtd->pvt);
11016 mtd->pvt->ringt = mtd->pvt->ringt_base;
11017
11018 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11019 int result;
11020 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11021 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11022 } else {
11023 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11024 }
11025 if (result) {
11026 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11027 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11028 if (res < 0)
11029 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11030 ast_hangup(chan);
11031 goto quit;
11032 }
11033 goto quit_no_clean;
11034
11035 } else {
11036 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11037 }
11038 }
11039 } else if (i & DAHDI_IOMUX_READ) {
11040 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11041 if (errno != ELAST) {
11042 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11043 goto quit;
11044 }
11045 break;
11046 }
11047 samples += res;
11048 if (!spill_done) {
11049 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11050
11051
11052
11053
11054 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11055 break;
11056 } else if (spill_result) {
11057 spill_done = 1;
11058 }
11059 } else {
11060
11061
11062
11063 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11064 break;
11065 }
11066 if (samples > (8000 * 4))
11067 break;
11068 }
11069 }
11070
11071 if (spill_result == 1) {
11072 callerid_get(cs, &name, &number, &flags);
11073 if (flags & CID_MSGWAITING) {
11074 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11075 notify_message(mtd->pvt->mailbox, 1);
11076 } else if (flags & CID_NOMSGWAITING) {
11077 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11078 notify_message(mtd->pvt->mailbox, 0);
11079 } else {
11080 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11081 }
11082 }
11083
11084
11085 quit:
11086 callerid_free(cs);
11087
11088 restore_gains(mtd->pvt);
11089
11090 quit_no_clean:
11091 mtd->pvt->mwimonitoractive = 0;
11092
11093 ast_free(mtd);
11094
11095 return NULL;
11096 }
11097
11098
11099
11100
11101
11102
11103
11104
11105 static int mwi_send_init(struct dahdi_pvt * pvt)
11106 {
11107 int x;
11108
11109 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11110
11111 if (pvt->mwisend_rpas) {
11112 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11113 pvt->mwisendactive = 1;
11114 } else if (pvt->mwisend_fsk) {
11115 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11116 pvt->mwisendactive = 1;
11117 } else {
11118 pvt->mwisendactive = 0;
11119 return 0;
11120 }
11121 #else
11122 if (mwisend_rpas) {
11123 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11124 } else {
11125 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11126 }
11127 pvt->mwisendactive = 1;
11128 #endif
11129
11130 if (pvt->cidspill) {
11131 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11132 ast_free(pvt->cidspill);
11133 pvt->cidspill = NULL;
11134 pvt->cidpos = 0;
11135 pvt->cidlen = 0;
11136 }
11137 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11138 if (!pvt->cidspill) {
11139 pvt->mwisendactive = 0;
11140 return -1;
11141 }
11142 x = DAHDI_FLUSH_BOTH;
11143 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11144 x = 3000;
11145 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11146 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11147 if (pvt->mwisend_fsk) {
11148 #endif
11149 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11150 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11151 pvt->cidpos = 0;
11152 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11153 }
11154 #endif
11155 return 0;
11156 }
11157
11158 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11159 {
11160 struct timeval now;
11161 int res;
11162
11163
11164
11165
11166 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11167 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11168 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11169
11170 switch ( pvt->mwisend_data.mwisend_current) {
11171 case MWI_SEND_SA:
11172
11173 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11174 if (res) {
11175 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11176 goto quit;
11177 }
11178 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11179 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11180 break;
11181 case MWI_SEND_SA_WAIT:
11182 break;
11183 case MWI_SEND_PAUSE:
11184 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11185 if (pvt->mwisend_fsk) {
11186 #endif
11187 gettimeofday(&now, NULL);
11188 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11189 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11190 }
11191 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11192 } else {
11193 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11194 }
11195 #endif
11196 break;
11197 case MWI_SEND_SPILL:
11198
11199 if(0 < num_read) {
11200 if (num_read > pvt->cidlen - pvt->cidpos)
11201 num_read = pvt->cidlen - pvt->cidpos;
11202 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11203 if (res > 0) {
11204 pvt->cidpos += res;
11205 if (pvt->cidpos >= pvt->cidlen) {
11206 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11207 }
11208 } else {
11209 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11210 goto quit;
11211 }
11212 }
11213 break;
11214 case MWI_SEND_CLEANUP:
11215
11216 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11217 break;
11218 default:
11219
11220 goto quit;
11221 }
11222 }
11223
11224 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11225 if (pvt->cidspill) {
11226 ast_free(pvt->cidspill);
11227 pvt->cidspill = NULL;
11228 pvt->cidpos = 0;
11229 pvt->cidlen = 0;
11230 }
11231 pvt->mwisendactive = 0;
11232 }
11233 return 0;
11234 quit:
11235 if (pvt->cidspill) {
11236 ast_free(pvt->cidspill);
11237 pvt->cidspill = NULL;
11238 pvt->cidpos = 0;
11239 pvt->cidlen = 0;
11240 }
11241 pvt->mwisendactive = 0;
11242 return -1;
11243 }
11244
11245 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11246 {
11247 int handled = 0;
11248
11249 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11250 switch (event) {
11251 case DAHDI_EVENT_RINGEROFF:
11252 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11253 handled = 1;
11254
11255 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11256 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11257 ast_free(pvt->cidspill);
11258 pvt->cidspill = NULL;
11259 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11260 pvt->mwisendactive = 0;
11261 } else {
11262 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11263 gettimeofday(&pvt->mwisend_data.pause, NULL);
11264 }
11265 }
11266 break;
11267
11268 case DAHDI_EVENT_RINGOFFHOOK:
11269 if (pvt->cidspill) {
11270 ast_free(pvt->cidspill);
11271 pvt->cidspill = NULL;
11272 pvt->cidpos = 0;
11273 pvt->cidlen = 0;
11274 }
11275 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11276 pvt->mwisendactive = 0;
11277 break;
11278 case DAHDI_EVENT_RINGERON:
11279 case DAHDI_EVENT_HOOKCOMPLETE:
11280 break;
11281 default:
11282 break;
11283 }
11284 }
11285 return handled;
11286 }
11287
11288
11289 static int dahdi_destroy_channel_bynum(int channel)
11290 {
11291 struct dahdi_pvt *cur;
11292
11293 ast_mutex_lock(&iflock);
11294 for (cur = iflist; cur; cur = cur->next) {
11295 if (cur->channel == channel) {
11296 int x = DAHDI_FLASH;
11297
11298
11299 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11300
11301 destroy_channel(cur, 1);
11302 ast_mutex_unlock(&iflock);
11303 ast_module_unref(ast_module_info->self);
11304 return RESULT_SUCCESS;
11305 }
11306 }
11307 ast_mutex_unlock(&iflock);
11308 return RESULT_FAILURE;
11309 }
11310
11311 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11312 {
11313 int res;
11314 pthread_t threadid;
11315 struct ast_channel *chan;
11316
11317
11318
11319 switch (event) {
11320 case DAHDI_EVENT_NONE:
11321 case DAHDI_EVENT_BITSCHANGED:
11322 break;
11323 case DAHDI_EVENT_WINKFLASH:
11324 case DAHDI_EVENT_RINGOFFHOOK:
11325 if (i->inalarm) break;
11326 if (i->radio) break;
11327
11328 switch (i->sig) {
11329 case SIG_FXOLS:
11330 case SIG_FXOGS:
11331 case SIG_FXOKS:
11332 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11333 if (res && (errno == EBUSY))
11334 break;
11335
11336
11337 ast_free(i->cidspill);
11338 i->cidspill = NULL;
11339 restore_conference(i);
11340
11341 if (i->immediate) {
11342 dahdi_enable_ec(i);
11343
11344 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11345 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11346 if (!chan) {
11347 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11348 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11349 if (res < 0)
11350 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11351 }
11352 } else {
11353
11354 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11355 if (chan) {
11356 if (has_voicemail(i))
11357 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11358 else
11359 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11360 if (res < 0)
11361 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11362 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11363 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11364 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11365 if (res < 0)
11366 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11367 ast_hangup(chan);
11368 }
11369 } else
11370 ast_log(LOG_WARNING, "Unable to create channel\n");
11371 }
11372 break;
11373 case SIG_FXSLS:
11374 case SIG_FXSGS:
11375 case SIG_FXSKS:
11376 i->ringt = i->ringt_base;
11377
11378 case SIG_EMWINK:
11379 case SIG_FEATD:
11380 case SIG_FEATDMF:
11381 case SIG_FEATDMF_TA:
11382 case SIG_E911:
11383 case SIG_FGC_CAMA:
11384 case SIG_FGC_CAMAMF:
11385 case SIG_FEATB:
11386 case SIG_EM:
11387 case SIG_EM_E1:
11388 case SIG_SFWINK:
11389 case SIG_SF_FEATD:
11390 case SIG_SF_FEATDMF:
11391 case SIG_SF_FEATB:
11392 case SIG_SF:
11393
11394 if (i->cid_start == CID_START_POLARITY_IN) {
11395 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11396 } else {
11397 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11398 }
11399
11400 if (!chan) {
11401 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11402 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11403 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11404 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11405 if (res < 0) {
11406 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11407 }
11408 ast_hangup(chan);
11409 }
11410 break;
11411 default:
11412 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11413 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11414 if (res < 0)
11415 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11416 return NULL;
11417 }
11418 break;
11419 case DAHDI_EVENT_NOALARM:
11420 switch (i->sig) {
11421 #if defined(HAVE_PRI)
11422 case SIG_PRI_LIB_HANDLE_CASES:
11423 ast_mutex_lock(&i->lock);
11424 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11425 ast_mutex_unlock(&i->lock);
11426 break;
11427 #endif
11428 #if defined(HAVE_SS7)
11429 case SIG_SS7:
11430 sig_ss7_set_alarm(i->sig_pvt, 0);
11431 break;
11432 #endif
11433 default:
11434 i->inalarm = 0;
11435 break;
11436 }
11437 handle_clear_alarms(i);
11438 break;
11439 case DAHDI_EVENT_ALARM:
11440 switch (i->sig) {
11441 #if defined(HAVE_PRI)
11442 case SIG_PRI_LIB_HANDLE_CASES:
11443 ast_mutex_lock(&i->lock);
11444 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11445 ast_mutex_unlock(&i->lock);
11446 break;
11447 #endif
11448 #if defined(HAVE_SS7)
11449 case SIG_SS7:
11450 sig_ss7_set_alarm(i->sig_pvt, 1);
11451 break;
11452 #endif
11453 default:
11454 i->inalarm = 1;
11455 break;
11456 }
11457 res = get_alarms(i);
11458 handle_alarms(i, res);
11459
11460 case DAHDI_EVENT_ONHOOK:
11461 if (i->radio)
11462 break;
11463
11464 switch (i->sig) {
11465 case SIG_FXOLS:
11466 case SIG_FXOGS:
11467 case SIG_FEATD:
11468 case SIG_FEATDMF:
11469 case SIG_FEATDMF_TA:
11470 case SIG_E911:
11471 case SIG_FGC_CAMA:
11472 case SIG_FGC_CAMAMF:
11473 case SIG_FEATB:
11474 case SIG_EM:
11475 case SIG_EM_E1:
11476 case SIG_EMWINK:
11477 case SIG_SF_FEATD:
11478 case SIG_SF_FEATDMF:
11479 case SIG_SF_FEATB:
11480 case SIG_SF:
11481 case SIG_SFWINK:
11482 case SIG_FXSLS:
11483 case SIG_FXSGS:
11484 case SIG_FXSKS:
11485 case SIG_FXOKS:
11486 dahdi_disable_ec(i);
11487
11488 #ifdef ZHONE_HACK
11489 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11490 usleep(1);
11491 #endif
11492 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11493 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11494 break;
11495 case SIG_SS7:
11496 case SIG_PRI_LIB_HANDLE_CASES:
11497 dahdi_disable_ec(i);
11498 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11499 break;
11500 default:
11501 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11502 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11503 return NULL;
11504 }
11505 break;
11506 case DAHDI_EVENT_POLARITY:
11507 switch (i->sig) {
11508 case SIG_FXSLS:
11509 case SIG_FXSKS:
11510 case SIG_FXSGS:
11511
11512
11513
11514
11515 if (i->hanguponpolarityswitch)
11516 i->polarity = POLARITY_REV;
11517 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11518 i->polarity = POLARITY_REV;
11519 ast_verb(2, "Starting post polarity "
11520 "CID detection on channel %d\n",
11521 i->channel);
11522 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11523 if (!chan) {
11524 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11525 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11526 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11527 }
11528 }
11529 break;
11530 default:
11531 ast_log(LOG_WARNING, "handle_init_event detected "
11532 "polarity reversal on non-FXO (SIG_FXS) "
11533 "interface %d\n", i->channel);
11534 }
11535 break;
11536 case DAHDI_EVENT_REMOVED:
11537 ast_log(LOG_NOTICE,
11538 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11539 i->channel);
11540 return i;
11541 case DAHDI_EVENT_NEONMWI_ACTIVE:
11542 if (i->mwimonitor_neon) {
11543 notify_message(i->mailbox, 1);
11544 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11545 }
11546 break;
11547 case DAHDI_EVENT_NEONMWI_INACTIVE:
11548 if (i->mwimonitor_neon) {
11549 notify_message(i->mailbox, 0);
11550 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11551 }
11552 break;
11553 }
11554 return NULL;
11555 }
11556
11557 static void *do_monitor(void *data)
11558 {
11559 int count, res, res2, spoint, pollres=0;
11560 struct dahdi_pvt *i;
11561 struct dahdi_pvt *last = NULL;
11562 struct dahdi_pvt *doomed;
11563 time_t thispass = 0, lastpass = 0;
11564 int found;
11565 char buf[1024];
11566 struct pollfd *pfds=NULL;
11567 int lastalloc = -1;
11568
11569
11570
11571 #if 0
11572 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11573 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11574 return NULL;
11575 }
11576 ast_debug(1, "Monitor starting...\n");
11577 #endif
11578 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11579
11580 for (;;) {
11581
11582 ast_mutex_lock(&iflock);
11583 if (!pfds || (lastalloc != ifcount)) {
11584 if (pfds) {
11585 ast_free(pfds);
11586 pfds = NULL;
11587 }
11588 if (ifcount) {
11589 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11590 ast_mutex_unlock(&iflock);
11591 return NULL;
11592 }
11593 }
11594 lastalloc = ifcount;
11595 }
11596
11597
11598 count = 0;
11599 for (i = iflist; i; i = i->next) {
11600 ast_mutex_lock(&i->lock);
11601 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11602 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11603 struct analog_pvt *p = i->sig_pvt;
11604
11605 if (!p)
11606 ast_log(LOG_ERROR, "No sig_pvt?\n");
11607
11608 if (!p->owner && !p->subs[SUB_REAL].owner) {
11609
11610 pfds[count].fd = i->subs[SUB_REAL].dfd;
11611 pfds[count].events = POLLPRI;
11612 pfds[count].revents = 0;
11613
11614 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11615 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11616 pfds[count].events |= POLLIN;
11617 }
11618 count++;
11619 }
11620 } else {
11621 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11622
11623 pfds[count].fd = i->subs[SUB_REAL].dfd;
11624 pfds[count].events = POLLPRI;
11625 pfds[count].revents = 0;
11626
11627
11628 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11629 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11630 pfds[count].events |= POLLIN;
11631 }
11632 count++;
11633 }
11634 }
11635 }
11636 ast_mutex_unlock(&i->lock);
11637 }
11638
11639 ast_mutex_unlock(&iflock);
11640
11641 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11642 pthread_testcancel();
11643
11644 res = poll(pfds, count, 1000);
11645 pthread_testcancel();
11646 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11647
11648
11649 if (res < 0) {
11650 if ((errno != EAGAIN) && (errno != EINTR))
11651 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11652 continue;
11653 }
11654
11655
11656 ast_mutex_lock(&iflock);
11657 found = 0;
11658 spoint = 0;
11659 lastpass = thispass;
11660 thispass = time(NULL);
11661 doomed = NULL;
11662 for (i = iflist;; i = i->next) {
11663 if (doomed) {
11664 int res;
11665 res = dahdi_destroy_channel_bynum(doomed->channel);
11666 if (res != RESULT_SUCCESS) {
11667 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11668 }
11669 doomed = NULL;
11670 }
11671 if (!i) {
11672 break;
11673 }
11674
11675 if (thispass != lastpass) {
11676 if (!found && ((i == last) || ((i == iflist) && !last))) {
11677 last = i;
11678 if (last) {
11679 struct analog_pvt *analog_p = last->sig_pvt;
11680
11681 if (analog_p
11682 && !last->mwisendactive
11683 && (last->sig & __DAHDI_SIG_FXO)
11684 && !analog_p->fxsoffhookstate
11685 && !last->owner
11686 && !ast_strlen_zero(last->mailbox)
11687 && (thispass - analog_p->onhooktime > 3)) {
11688 res = has_voicemail(last);
11689 if (analog_p->msgstate != res) {
11690
11691 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11692 if (res2) {
11693
11694 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11695 }
11696
11697 if (mwi_send_init(last)) {
11698 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11699 }
11700 analog_p->msgstate = res;
11701 found ++;
11702 }
11703 }
11704 last = last->next;
11705 }
11706 }
11707 }
11708 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11709 if (i->radio && !i->owner)
11710 {
11711 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11712 if (res)
11713 {
11714 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11715
11716 ast_mutex_unlock(&iflock);
11717 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11718 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11719 else
11720 doomed = handle_init_event(i, res);
11721 ast_mutex_lock(&iflock);
11722 }
11723 continue;
11724 }
11725 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11726 if (pollres & POLLIN) {
11727 if (i->owner || i->subs[SUB_REAL].owner) {
11728 #ifdef HAVE_PRI
11729 if (!i->pri)
11730 #endif
11731 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11732 continue;
11733 }
11734 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11735 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11736 continue;
11737 }
11738 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11739 if (res > 0) {
11740 if (i->mwimonitor_fsk) {
11741 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11742 pthread_attr_t attr;
11743 pthread_t threadid;
11744 struct mwi_thread_data *mtd;
11745
11746 pthread_attr_init(&attr);
11747 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11748
11749 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11750 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11751 mtd->pvt = i;
11752 memcpy(mtd->buf, buf, res);
11753 mtd->len = res;
11754 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11755 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11756 ast_free(mtd);
11757 }
11758 i->mwimonitoractive = 1;
11759 }
11760 }
11761
11762 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11763 int energy;
11764 struct timeval now;
11765
11766
11767
11768 if (1 == i->dtmfcid_holdoff_state) {
11769 gettimeofday(&i->dtmfcid_delay, NULL);
11770 i->dtmfcid_holdoff_state = 2;
11771 } else if (2 == i->dtmfcid_holdoff_state) {
11772 gettimeofday(&now, NULL);
11773 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11774 i->dtmfcid_holdoff_state = 0;
11775 }
11776 } else {
11777 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11778 if (!i->mwisendactive && energy > dtmfcid_level) {
11779 pthread_t threadid;
11780 struct ast_channel *chan;
11781 ast_mutex_unlock(&iflock);
11782 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11783
11784 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11785 i->dtmfcid_holdoff_state = 1;
11786 } else {
11787 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11788 if (!chan) {
11789 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11790 } else {
11791 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11792 if (res) {
11793 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11794 } else {
11795 i->dtmfcid_holdoff_state = 1;
11796 }
11797 }
11798 }
11799 ast_mutex_lock(&iflock);
11800 }
11801 }
11802 }
11803 if (i->mwisendactive) {
11804 mwi_send_process_buffer(i, res);
11805 }
11806 } else {
11807 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11808 }
11809 }
11810 if (pollres & POLLPRI) {
11811 if (i->owner || i->subs[SUB_REAL].owner) {
11812 #ifdef HAVE_PRI
11813 if (!i->pri)
11814 #endif
11815 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11816 continue;
11817 }
11818 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11819 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11820
11821 ast_mutex_unlock(&iflock);
11822 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11823 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11824 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11825 else
11826 doomed = handle_init_event(i, res);
11827 }
11828 ast_mutex_lock(&iflock);
11829 }
11830 }
11831 }
11832 ast_mutex_unlock(&iflock);
11833 }
11834
11835 return NULL;
11836
11837 }
11838
11839 static int restart_monitor(void)
11840 {
11841
11842 if (monitor_thread == AST_PTHREADT_STOP)
11843 return 0;
11844 ast_mutex_lock(&monlock);
11845 if (monitor_thread == pthread_self()) {
11846 ast_mutex_unlock(&monlock);
11847 ast_log(LOG_WARNING, "Cannot kill myself\n");
11848 return -1;
11849 }
11850 if (monitor_thread != AST_PTHREADT_NULL) {
11851
11852 pthread_kill(monitor_thread, SIGURG);
11853 } else {
11854
11855 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11856 ast_mutex_unlock(&monlock);
11857 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11858 return -1;
11859 }
11860 }
11861 ast_mutex_unlock(&monlock);
11862 return 0;
11863 }
11864
11865 #if defined(HAVE_PRI)
11866 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11867 {
11868 int x;
11869 int trunkgroup;
11870
11871 trunkgroup = pris[*span].mastertrunkgroup;
11872 if (trunkgroup) {
11873
11874 for (x = 0; x < NUM_SPANS; x++) {
11875 if (pris[x].pri.trunkgroup == trunkgroup) {
11876 *span = x;
11877 return 0;
11878 }
11879 }
11880 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11881 *span = -1;
11882 } else {
11883 if (pris[*span].pri.trunkgroup) {
11884 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);
11885 *span = -1;
11886 } else if (pris[*span].mastertrunkgroup) {
11887 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11888 *span = -1;
11889 } else {
11890 if (si->totalchans == 31) {
11891
11892 pris[*span].dchannels[0] = 16 + offset;
11893 } else if (si->totalchans == 24) {
11894
11895 pris[*span].dchannels[0] = 24 + offset;
11896 } else if (si->totalchans == 3) {
11897
11898 pris[*span].dchannels[0] = 3 + offset;
11899 } else {
11900 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);
11901 *span = -1;
11902 return 0;
11903 }
11904 pris[*span].pri.span = *span + 1;
11905 }
11906 }
11907 return 0;
11908 }
11909 #endif
11910
11911 #if defined(HAVE_PRI)
11912 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11913 {
11914 struct dahdi_spaninfo si;
11915 struct dahdi_params p;
11916 int fd;
11917 int span;
11918 int ospan=0;
11919 int x,y;
11920 for (x = 0; x < NUM_SPANS; x++) {
11921 if (pris[x].pri.trunkgroup == trunkgroup) {
11922 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11923 return -1;
11924 }
11925 }
11926 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11927 if (!channels[y])
11928 break;
11929 memset(&si, 0, sizeof(si));
11930 memset(&p, 0, sizeof(p));
11931 fd = open("/dev/dahdi/channel", O_RDWR);
11932 if (fd < 0) {
11933 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11934 return -1;
11935 }
11936 x = channels[y];
11937 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11938 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11939 close(fd);
11940 return -1;
11941 }
11942 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11943 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11944 return -1;
11945 }
11946 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11947 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11948 close(fd);
11949 return -1;
11950 }
11951 span = p.spanno - 1;
11952 if (pris[span].pri.trunkgroup) {
11953 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11954 close(fd);
11955 return -1;
11956 }
11957 if (pris[span].pri.pvts[0]) {
11958 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11959 close(fd);
11960 return -1;
11961 }
11962 if (!y) {
11963 pris[span].pri.trunkgroup = trunkgroup;
11964 ospan = span;
11965 }
11966 pris[ospan].dchannels[y] = channels[y];
11967 pris[span].pri.span = span + 1;
11968 close(fd);
11969 }
11970 return 0;
11971 }
11972 #endif
11973
11974 #if defined(HAVE_PRI)
11975 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11976 {
11977 if (pris[span].mastertrunkgroup) {
11978 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);
11979 return -1;
11980 }
11981 pris[span].mastertrunkgroup = trunkgroup;
11982 pris[span].prilogicalspan = logicalspan;
11983 return 0;
11984 }
11985 #endif
11986
11987 #if defined(HAVE_SS7)
11988 static unsigned int parse_pointcode(const char *pcstring)
11989 {
11990 unsigned int code1, code2, code3;
11991 int numvals;
11992
11993 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11994 if (numvals == 1)
11995 return code1;
11996 if (numvals == 3)
11997 return (code1 << 16) | (code2 << 8) | code3;
11998
11999 return 0;
12000 }
12001 #endif
12002
12003 #if defined(HAVE_SS7)
12004 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12005 {
12006 if ((linkset < 0) || (linkset >= NUM_SPANS))
12007 return NULL;
12008 else
12009 return &linksets[linkset - 1];
12010 }
12011 #endif
12012
12013 #ifdef HAVE_OPENR2
12014 static void dahdi_r2_destroy_links(void)
12015 {
12016 int i = 0;
12017 if (!r2links) {
12018 return;
12019 }
12020 for (; i < r2links_count; i++) {
12021 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12022 pthread_cancel(r2links[i]->r2master);
12023 pthread_join(r2links[i]->r2master, NULL);
12024 openr2_context_delete(r2links[i]->protocol_context);
12025 }
12026 ast_free(r2links[i]);
12027 }
12028 ast_free(r2links);
12029 r2links = NULL;
12030 r2links_count = 0;
12031 }
12032
12033 #define R2_LINK_CAPACITY 10
12034 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12035 {
12036 struct dahdi_mfcr2 *new_r2link = NULL;
12037 struct dahdi_mfcr2 **new_r2links = NULL;
12038
12039
12040 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12041 new_r2link = ast_calloc(1, sizeof(**r2links));
12042 if (!new_r2link) {
12043 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12044 return NULL;
12045 }
12046 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12047 if (!new_r2links) {
12048 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12049 ast_free(new_r2link);
12050 return NULL;
12051 }
12052 r2links = new_r2links;
12053 new_r2link->r2master = AST_PTHREADT_NULL;
12054 r2links[r2links_count] = new_r2link;
12055 r2links_count++;
12056 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12057 }
12058 return r2links[r2links_count - 1];
12059 }
12060
12061 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12062 {
12063 char tmplogdir[] = "/tmp";
12064 char logdir[OR2_MAX_PATH];
12065 int threshold = 0;
12066 int snres = 0;
12067 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12068 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12069 conf->mfcr2.max_dnis);
12070 if (!r2_link->protocol_context) {
12071 return -1;
12072 }
12073 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12074 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12075 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12076 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12077 #endif
12078 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12079 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12080 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12081 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12082 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12083 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12084 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12085 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12086 }
12087 } else {
12088 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12089 if (snres >= sizeof(logdir)) {
12090 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12091 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12092 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12093 }
12094 } else {
12095 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12096 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12097 }
12098 }
12099 }
12100 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12101 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12102 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12103 }
12104 }
12105 r2_link->monitored_count = 0;
12106 return 0;
12107 }
12108 #endif
12109
12110
12111
12112
12113
12114
12115 static int sigtype_to_signalling(int sigtype)
12116 {
12117 return sigtype;
12118 }
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12133 {
12134 struct stat stbuf;
12135 int num;
12136
12137 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12138 if (stat(path, &stbuf) < 0) {
12139 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12140 return -errno;
12141 }
12142 if (!S_ISCHR(stbuf.st_mode)) {
12143 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12144 return -EINVAL;
12145 }
12146 num = minor(stbuf.st_rdev);
12147 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12148 return num;
12149
12150 }
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12167 {
12168
12169 struct dahdi_pvt *tmp;
12170 char fn[80];
12171 struct dahdi_bufferinfo bi;
12172
12173 int res;
12174 #if defined(HAVE_PRI)
12175 int span = 0;
12176 #endif
12177 int here = 0;
12178 int x;
12179 struct analog_pvt *analog_p = NULL;
12180 struct dahdi_params p;
12181 #if defined(HAVE_PRI)
12182 struct dahdi_spaninfo si;
12183 struct sig_pri_chan *pri_chan = NULL;
12184 #endif
12185 #if defined(HAVE_SS7)
12186 struct sig_ss7_chan *ss7_chan = NULL;
12187 #endif
12188
12189
12190 for (tmp = iflist; tmp; tmp = tmp->next) {
12191 if (!tmp->destroy) {
12192 if (tmp->channel == channel) {
12193
12194 here = 1;
12195 break;
12196 }
12197 if (tmp->channel > channel) {
12198
12199 tmp = NULL;
12200 break;
12201 }
12202 }
12203 }
12204
12205 if (!here && reloading != 1) {
12206 tmp = ast_calloc(1, sizeof(*tmp));
12207 if (!tmp) {
12208 return NULL;
12209 }
12210 tmp->cc_params = ast_cc_config_params_init();
12211 if (!tmp->cc_params) {
12212 ast_free(tmp);
12213 return NULL;
12214 }
12215 ast_mutex_init(&tmp->lock);
12216 ifcount++;
12217 for (x = 0; x < 3; x++)
12218 tmp->subs[x].dfd = -1;
12219 tmp->channel = channel;
12220 tmp->priindication_oob = conf->chan.priindication_oob;
12221 }
12222
12223 if (tmp) {
12224 int chan_sig = conf->chan.sig;
12225
12226
12227 if (reloading && tmp->vars) {
12228 ast_variables_destroy(tmp->vars);
12229 tmp->vars = NULL;
12230 }
12231
12232
12233 if (!here) {
12234
12235 if ((channel != CHAN_PSEUDO)) {
12236 int count = 0;
12237
12238 snprintf(fn, sizeof(fn), "%d", channel);
12239
12240 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12241 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12242 usleep(1);
12243 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12244 count++;
12245 }
12246
12247 if (tmp->subs[SUB_REAL].dfd < 0) {
12248 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);
12249 destroy_dahdi_pvt(tmp);
12250 return NULL;
12251 }
12252 memset(&p, 0, sizeof(p));
12253 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12254 if (res < 0) {
12255 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12256 destroy_dahdi_pvt(tmp);
12257 return NULL;
12258 }
12259 if (conf->is_sig_auto)
12260 chan_sig = sigtype_to_signalling(p.sigtype);
12261 if (p.sigtype != (chan_sig & 0x3ffff)) {
12262 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));
12263 destroy_dahdi_pvt(tmp);
12264 return NULL;
12265 }
12266 tmp->law_default = p.curlaw;
12267 tmp->law = p.curlaw;
12268 tmp->span = p.spanno;
12269 #if defined(HAVE_PRI)
12270 span = p.spanno - 1;
12271 #endif
12272 } else {
12273 chan_sig = 0;
12274 }
12275 tmp->sig = chan_sig;
12276 tmp->outsigmod = conf->chan.outsigmod;
12277
12278 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12279 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12280 if (!analog_p) {
12281 destroy_dahdi_pvt(tmp);
12282 return NULL;
12283 }
12284 tmp->sig_pvt = analog_p;
12285 }
12286 #if defined(HAVE_SS7)
12287 if (chan_sig == SIG_SS7) {
12288 struct dahdi_ss7 *ss7;
12289 int clear = 0;
12290
12291 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12292 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12293 destroy_dahdi_pvt(tmp);
12294 return NULL;
12295 }
12296
12297 ss7 = ss7_resolve_linkset(cur_linkset);
12298 if (!ss7) {
12299 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12300 destroy_dahdi_pvt(tmp);
12301 return NULL;
12302 }
12303 ss7->ss7.span = cur_linkset;
12304 if (cur_cicbeginswith < 0) {
12305 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12306 destroy_dahdi_pvt(tmp);
12307 return NULL;
12308 }
12309 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12310 if (!ss7_chan) {
12311 destroy_dahdi_pvt(tmp);
12312 return NULL;
12313 }
12314 tmp->sig_pvt = ss7_chan;
12315 tmp->ss7 = &ss7->ss7;
12316
12317 ss7_chan->channel = tmp->channel;
12318 ss7_chan->cic = cur_cicbeginswith++;
12319
12320
12321 ss7_chan->dpc = cur_defaultdpc;
12322
12323 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12324
12325 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12326 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12327 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12328 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12329
12330 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12331 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12332 }
12333 #endif
12334 #ifdef HAVE_OPENR2
12335 if (chan_sig == SIG_MFCR2) {
12336 struct dahdi_mfcr2 *r2_link;
12337 r2_link = dahdi_r2_get_link();
12338 if (!r2_link) {
12339 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12340 destroy_dahdi_pvt(tmp);
12341 return NULL;
12342 }
12343 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12344 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12345 destroy_dahdi_pvt(tmp);
12346 return NULL;
12347 }
12348 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12349 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12350 destroy_dahdi_pvt(tmp);
12351 return NULL;
12352 }
12353 r2_link->pvts[r2_link->numchans++] = tmp;
12354 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12355 tmp->subs[SUB_REAL].dfd,
12356 NULL, NULL);
12357 if (!tmp->r2chan) {
12358 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12359 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12360 destroy_dahdi_pvt(tmp);
12361 return NULL;
12362 }
12363 tmp->mfcr2 = r2_link;
12364 if (conf->mfcr2.call_files) {
12365 openr2_chan_enable_call_files(tmp->r2chan);
12366 }
12367 openr2_chan_set_client_data(tmp->r2chan, tmp);
12368
12369 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12370 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12371 tmp->mfcr2_category = conf->mfcr2.category;
12372 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12373 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12374 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12375 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12376 tmp->mfcr2call = 0;
12377 tmp->mfcr2_dnis_index = 0;
12378 tmp->mfcr2_ani_index = 0;
12379 r2_link->monitored_count++;
12380 }
12381 #endif
12382 #ifdef HAVE_PRI
12383 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12384 int offset;
12385 int matchesdchan;
12386 int x,y;
12387 int myswitchtype = 0;
12388
12389 offset = 0;
12390 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12391 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12392 destroy_dahdi_pvt(tmp);
12393 return NULL;
12394 }
12395 if (span >= NUM_SPANS) {
12396 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12397 destroy_dahdi_pvt(tmp);
12398 return NULL;
12399 } else {
12400 si.spanno = 0;
12401 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12402 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12403 destroy_dahdi_pvt(tmp);
12404 return NULL;
12405 }
12406
12407 tmp->logicalspan = pris[span].prilogicalspan;
12408 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12409 if (span < 0) {
12410 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12411 destroy_dahdi_pvt(tmp);
12412 return NULL;
12413 }
12414 myswitchtype = conf->pri.pri.switchtype;
12415
12416 matchesdchan=0;
12417 for (x = 0; x < NUM_SPANS; x++) {
12418 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12419 if (pris[x].dchannels[y] == tmp->channel) {
12420 matchesdchan = 1;
12421 break;
12422 }
12423 }
12424 }
12425 if (!matchesdchan) {
12426 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12427 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12428 destroy_dahdi_pvt(tmp);
12429 return NULL;
12430 }
12431 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12432 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12433 destroy_dahdi_pvt(tmp);
12434 return NULL;
12435 }
12436 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12437 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));
12438 destroy_dahdi_pvt(tmp);
12439 return NULL;
12440 }
12441 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12442 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12443 destroy_dahdi_pvt(tmp);
12444 return NULL;
12445 }
12446 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12447 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12448 destroy_dahdi_pvt(tmp);
12449 return NULL;
12450 }
12451 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12452 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12453 destroy_dahdi_pvt(tmp);
12454 return NULL;
12455 }
12456 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12457 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12458 destroy_dahdi_pvt(tmp);
12459 return NULL;
12460 }
12461 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12462 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12463 pris[span].pri.trunkgroup);
12464 destroy_dahdi_pvt(tmp);
12465 return NULL;
12466 }
12467
12468 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12469 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12470 if (!pri_chan) {
12471 destroy_dahdi_pvt(tmp);
12472 return NULL;
12473 }
12474 tmp->sig_pvt = pri_chan;
12475 tmp->pri = &pris[span].pri;
12476
12477 tmp->priexclusive = conf->chan.priexclusive;
12478
12479 if (!tmp->pri->cc_params) {
12480 tmp->pri->cc_params = ast_cc_config_params_init();
12481 if (!tmp->pri->cc_params) {
12482 destroy_dahdi_pvt(tmp);
12483 return NULL;
12484 }
12485 }
12486 ast_cc_copy_config_params(tmp->pri->cc_params,
12487 conf->chan.cc_params);
12488
12489 pris[span].pri.sig = chan_sig;
12490 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12491 pris[span].pri.switchtype = myswitchtype;
12492 pris[span].pri.nsf = conf->pri.pri.nsf;
12493 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12494 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12495 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12496 pris[span].pri.minunused = conf->pri.pri.minunused;
12497 pris[span].pri.minidle = conf->pri.pri.minidle;
12498 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12499 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12500 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12501 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12502 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12503 #endif
12504 #ifdef HAVE_PRI_INBANDDISCONNECT
12505 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12506 #endif
12507 #if defined(HAVE_PRI_CALL_HOLD)
12508 pris[span].pri.hold_disconnect_transfer =
12509 conf->pri.pri.hold_disconnect_transfer;
12510 #endif
12511 #if defined(HAVE_PRI_CCSS)
12512 pris[span].pri.cc_ptmp_recall_mode =
12513 conf->pri.pri.cc_ptmp_recall_mode;
12514 pris[span].pri.cc_qsig_signaling_link_req =
12515 conf->pri.pri.cc_qsig_signaling_link_req;
12516 pris[span].pri.cc_qsig_signaling_link_rsp =
12517 conf->pri.pri.cc_qsig_signaling_link_rsp;
12518 #endif
12519 #if defined(HAVE_PRI_CALL_WAITING)
12520 pris[span].pri.max_call_waiting_calls =
12521 conf->pri.pri.max_call_waiting_calls;
12522 pris[span].pri.allow_call_waiting_calls =
12523 conf->pri.pri.allow_call_waiting_calls;
12524 #endif
12525 pris[span].pri.transfer = conf->chan.transfer;
12526 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12527 #if defined(HAVE_PRI_L2_PERSISTENCE)
12528 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12529 #endif
12530 #if defined(HAVE_PRI_AOC_EVENTS)
12531 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12532 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12533 #endif
12534 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12535 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12536 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12537 #if defined(HAVE_PRI_MWI)
12538 ast_copy_string(pris[span].pri.mwi_mailboxes,
12539 conf->pri.pri.mwi_mailboxes,
12540 sizeof(pris[span].pri.mwi_mailboxes));
12541 #endif
12542 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12543 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12544 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12545 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12546 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12547 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12548 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12549 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12550
12551 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12552 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12553 }
12554
12555 #if defined(HAVE_PRI_CALL_WAITING)
12556
12557 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12558 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12559 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12560 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12561 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12562 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12563 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12564 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12565 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12566 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12567 #endif
12568 } else {
12569 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12570 destroy_dahdi_pvt(tmp);
12571 return NULL;
12572 }
12573 }
12574 }
12575 #endif
12576 } else {
12577
12578 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));
12579 chan_sig = tmp->sig;
12580 if (tmp->subs[SUB_REAL].dfd > -1) {
12581 memset(&p, 0, sizeof(p));
12582 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12583 }
12584 }
12585
12586 switch (chan_sig) {
12587 case SIG_FXSKS:
12588 case SIG_FXSLS:
12589 case SIG_EM:
12590 case SIG_EM_E1:
12591 case SIG_EMWINK:
12592 case SIG_FEATD:
12593 case SIG_FEATDMF:
12594 case SIG_FEATDMF_TA:
12595 case SIG_FEATB:
12596 case SIG_E911:
12597 case SIG_SF:
12598 case SIG_SFWINK:
12599 case SIG_FGC_CAMA:
12600 case SIG_FGC_CAMAMF:
12601 case SIG_SF_FEATD:
12602 case SIG_SF_FEATDMF:
12603 case SIG_SF_FEATB:
12604 p.starttime = 250;
12605 break;
12606 }
12607
12608 if (tmp->radio) {
12609
12610 p.channo = channel;
12611 p.rxwinktime = 1;
12612 p.rxflashtime = 1;
12613 p.starttime = 1;
12614 p.debouncetime = 5;
12615 } else {
12616 p.channo = channel;
12617
12618 if (conf->timing.prewinktime >= 0)
12619 p.prewinktime = conf->timing.prewinktime;
12620 if (conf->timing.preflashtime >= 0)
12621 p.preflashtime = conf->timing.preflashtime;
12622 if (conf->timing.winktime >= 0)
12623 p.winktime = conf->timing.winktime;
12624 if (conf->timing.flashtime >= 0)
12625 p.flashtime = conf->timing.flashtime;
12626 if (conf->timing.starttime >= 0)
12627 p.starttime = conf->timing.starttime;
12628 if (conf->timing.rxwinktime >= 0)
12629 p.rxwinktime = conf->timing.rxwinktime;
12630 if (conf->timing.rxflashtime >= 0)
12631 p.rxflashtime = conf->timing.rxflashtime;
12632 if (conf->timing.debouncetime >= 0)
12633 p.debouncetime = conf->timing.debouncetime;
12634 }
12635
12636
12637 if (tmp->subs[SUB_REAL].dfd >= 0)
12638 {
12639 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12640 if (res < 0) {
12641 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12642 destroy_dahdi_pvt(tmp);
12643 return NULL;
12644 }
12645 }
12646 #if 1
12647 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12648 memset(&bi, 0, sizeof(bi));
12649 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12650 if (!res) {
12651 bi.txbufpolicy = conf->chan.buf_policy;
12652 bi.rxbufpolicy = conf->chan.buf_policy;
12653 bi.numbufs = conf->chan.buf_no;
12654 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12655 if (res < 0) {
12656 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12657 }
12658 } else {
12659 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12660 }
12661 tmp->buf_policy = conf->chan.buf_policy;
12662 tmp->buf_no = conf->chan.buf_no;
12663 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12664 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12665 tmp->faxbuf_no = conf->chan.faxbuf_no;
12666
12667
12668
12669
12670 tmp->bufsize = bi.bufsize;
12671 }
12672 #endif
12673 tmp->immediate = conf->chan.immediate;
12674 tmp->transfertobusy = conf->chan.transfertobusy;
12675 if (chan_sig & __DAHDI_SIG_FXS) {
12676 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12677 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12678 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12679 }
12680 tmp->ringt_base = ringt_base;
12681 tmp->firstradio = 0;
12682 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12683 tmp->permcallwaiting = conf->chan.callwaiting;
12684 else
12685 tmp->permcallwaiting = 0;
12686
12687 tmp->destroy = 0;
12688 tmp->drings = conf->chan.drings;
12689
12690
12691 if (tmp->drings.ringnum[0].range == 0)
12692 tmp->drings.ringnum[0].range = 10;
12693 if (tmp->drings.ringnum[1].range == 0)
12694 tmp->drings.ringnum[1].range = 10;
12695 if (tmp->drings.ringnum[2].range == 0)
12696 tmp->drings.ringnum[2].range = 10;
12697
12698 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12699 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12700 tmp->threewaycalling = conf->chan.threewaycalling;
12701 tmp->adsi = conf->chan.adsi;
12702 tmp->use_smdi = conf->chan.use_smdi;
12703 tmp->permhidecallerid = conf->chan.hidecallerid;
12704 tmp->hidecalleridname = conf->chan.hidecalleridname;
12705 tmp->callreturn = conf->chan.callreturn;
12706 tmp->echocancel = conf->chan.echocancel;
12707 tmp->echotraining = conf->chan.echotraining;
12708 tmp->pulse = conf->chan.pulse;
12709 if (tmp->echocancel.head.tap_length) {
12710 tmp->echocanbridged = conf->chan.echocanbridged;
12711 } else {
12712 if (conf->chan.echocanbridged)
12713 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12714 tmp->echocanbridged = 0;
12715 }
12716 tmp->busydetect = conf->chan.busydetect;
12717 tmp->busycount = conf->chan.busycount;
12718 tmp->busycompare = conf->chan.busycompare;
12719 tmp->busytonelength = conf->chan.busytonelength;
12720 tmp->busyquietlength = conf->chan.busyquietlength;
12721 tmp->busyfuzziness = conf->chan.busyfuzziness;
12722 tmp->silencethreshold = conf->chan.silencethreshold;
12723 tmp->callprogress = conf->chan.callprogress;
12724 tmp->waitfordialtone = conf->chan.waitfordialtone;
12725 tmp->cancallforward = conf->chan.cancallforward;
12726 tmp->dtmfrelax = conf->chan.dtmfrelax;
12727 tmp->callwaiting = tmp->permcallwaiting;
12728 tmp->hidecallerid = tmp->permhidecallerid;
12729 tmp->channel = channel;
12730 tmp->stripmsd = conf->chan.stripmsd;
12731 tmp->use_callerid = conf->chan.use_callerid;
12732 tmp->cid_signalling = conf->chan.cid_signalling;
12733 tmp->cid_start = conf->chan.cid_start;
12734 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12735 tmp->restrictcid = conf->chan.restrictcid;
12736 tmp->use_callingpres = conf->chan.use_callingpres;
12737 if (tmp->usedistinctiveringdetection) {
12738 if (!tmp->use_callerid) {
12739 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12740 tmp->use_callerid = 1;
12741 }
12742 }
12743
12744 if (tmp->cid_signalling == CID_SIG_SMDI) {
12745 if (!tmp->use_smdi) {
12746 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12747 tmp->use_smdi = 1;
12748 }
12749 }
12750 if (tmp->use_smdi) {
12751 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12752 if (!(tmp->smdi_iface)) {
12753 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12754 tmp->use_smdi = 0;
12755 }
12756 }
12757
12758 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12759 tmp->amaflags = conf->chan.amaflags;
12760 if (!here) {
12761 tmp->confno = -1;
12762 tmp->propconfno = -1;
12763 }
12764 tmp->canpark = conf->chan.canpark;
12765 tmp->transfer = conf->chan.transfer;
12766 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12767 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12768 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12769 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12770 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12771 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12772 tmp->cid_ton = 0;
12773 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12774 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12775 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12776 } else {
12777 tmp->cid_num[0] = '\0';
12778 tmp->cid_name[0] = '\0';
12779 }
12780 #if defined(HAVE_PRI)
12781 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12782 tmp->cid_tag[0] = '\0';
12783 } else
12784 #endif
12785 {
12786 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12787 }
12788 tmp->cid_subaddr[0] = '\0';
12789 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12790 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12791 char *mailbox, *context;
12792 mailbox = context = ast_strdupa(tmp->mailbox);
12793 strsep(&context, "@");
12794 if (ast_strlen_zero(context))
12795 context = "default";
12796 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12797 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12798 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12799 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12800 AST_EVENT_IE_END);
12801 }
12802 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12803 tmp->mwisend_setting = conf->chan.mwisend_setting;
12804 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12805 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12806 #endif
12807
12808 tmp->group = conf->chan.group;
12809 tmp->callgroup = conf->chan.callgroup;
12810 tmp->pickupgroup= conf->chan.pickupgroup;
12811 if (conf->chan.vars) {
12812 struct ast_variable *v, *tmpvar;
12813 for (v = conf->chan.vars ; v ; v = v->next) {
12814 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12815 tmpvar->next = tmp->vars;
12816 tmp->vars = tmpvar;
12817 }
12818 }
12819 }
12820 tmp->cid_rxgain = conf->chan.cid_rxgain;
12821 tmp->rxgain = conf->chan.rxgain;
12822 tmp->txgain = conf->chan.txgain;
12823 tmp->txdrc = conf->chan.txdrc;
12824 tmp->rxdrc = conf->chan.rxdrc;
12825 tmp->tonezone = conf->chan.tonezone;
12826 if (tmp->subs[SUB_REAL].dfd > -1) {
12827 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12828 if (tmp->dsp)
12829 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12830 update_conf(tmp);
12831 if (!here) {
12832 switch (chan_sig) {
12833 case SIG_PRI_LIB_HANDLE_CASES:
12834 case SIG_SS7:
12835 case SIG_MFCR2:
12836 break;
12837 default:
12838
12839 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12840 break;
12841 }
12842 }
12843 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12844 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12845
12846 switch (tmp->sig) {
12847 #ifdef HAVE_PRI
12848 case SIG_PRI_LIB_HANDLE_CASES:
12849 sig_pri_set_alarm(tmp->sig_pvt, 1);
12850 break;
12851 #endif
12852 #if defined(HAVE_SS7)
12853 case SIG_SS7:
12854 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12855 break;
12856 #endif
12857 default:
12858
12859 analog_p = tmp->sig_pvt;
12860 if (analog_p) {
12861 analog_p->inalarm = 1;
12862 }
12863 tmp->inalarm = 1;
12864 break;
12865 }
12866 handle_alarms(tmp, res);
12867 }
12868 }
12869
12870 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12871 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12872 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12873 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12874 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12875
12876 if (!here) {
12877 tmp->locallyblocked = 0;
12878 tmp->remotelyblocked = 0;
12879 switch (tmp->sig) {
12880 #if defined(HAVE_PRI)
12881 case SIG_PRI_LIB_HANDLE_CASES:
12882 tmp->inservice = 1;
12883 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12884 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12885 if (chan_sig == SIG_PRI) {
12886 char db_chan_name[20];
12887 char db_answer[5];
12888
12889
12890
12891
12892
12893 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12894 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12895 unsigned *why;
12896
12897 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12898 if (tmp->pri->enable_service_message_support) {
12899 char state;
12900
12901 sscanf(db_answer, "%1c:%30u", &state, why);
12902
12903
12904 *why &= (SRVST_NEAREND | SRVST_FAREND);
12905 }
12906 if (!*why) {
12907 ast_db_del(db_chan_name, SRVST_DBKEY);
12908 }
12909 }
12910 }
12911 #endif
12912 break;
12913 #endif
12914 #if defined(HAVE_SS7)
12915 case SIG_SS7:
12916 tmp->inservice = 0;
12917 break;
12918 #endif
12919 default:
12920
12921 tmp->inservice = 1;
12922 break;
12923 }
12924 }
12925
12926 switch (tmp->sig) {
12927 #if defined(HAVE_PRI)
12928 case SIG_PRI_LIB_HANDLE_CASES:
12929 if (pri_chan) {
12930 pri_chan->channel = tmp->channel;
12931 pri_chan->hidecallerid = tmp->hidecallerid;
12932 pri_chan->hidecalleridname = tmp->hidecalleridname;
12933 pri_chan->immediate = tmp->immediate;
12934 pri_chan->inalarm = tmp->inalarm;
12935 pri_chan->priexclusive = tmp->priexclusive;
12936 pri_chan->priindication_oob = tmp->priindication_oob;
12937 pri_chan->use_callerid = tmp->use_callerid;
12938 pri_chan->use_callingpres = tmp->use_callingpres;
12939 ast_copy_string(pri_chan->context, tmp->context,
12940 sizeof(pri_chan->context));
12941 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12942 sizeof(pri_chan->mohinterpret));
12943 pri_chan->stripmsd = tmp->stripmsd;
12944 }
12945 break;
12946 #endif
12947 #if defined(HAVE_SS7)
12948 case SIG_SS7:
12949 if (ss7_chan) {
12950 ss7_chan->inalarm = tmp->inalarm;
12951
12952 ss7_chan->stripmsd = tmp->stripmsd;
12953 ss7_chan->hidecallerid = tmp->hidecallerid;
12954 ss7_chan->use_callerid = tmp->use_callerid;
12955 ss7_chan->use_callingpres = tmp->use_callingpres;
12956 ss7_chan->immediate = tmp->immediate;
12957 ss7_chan->locallyblocked = tmp->locallyblocked;
12958 ss7_chan->remotelyblocked = tmp->remotelyblocked;
12959 ast_copy_string(ss7_chan->context, tmp->context,
12960 sizeof(ss7_chan->context));
12961 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12962 sizeof(ss7_chan->mohinterpret));
12963 }
12964 break;
12965 #endif
12966 default:
12967
12968 analog_p = tmp->sig_pvt;
12969 if (analog_p) {
12970 analog_p->channel = tmp->channel;
12971 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12972 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12973 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12974 analog_p->permcallwaiting = conf->chan.callwaiting;
12975 analog_p->callreturn = conf->chan.callreturn;
12976 analog_p->cancallforward = conf->chan.cancallforward;
12977 analog_p->canpark = conf->chan.canpark;
12978 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12979 analog_p->immediate = conf->chan.immediate;
12980 analog_p->permhidecallerid = conf->chan.permhidecallerid;
12981 analog_p->pulse = conf->chan.pulse;
12982 analog_p->threewaycalling = conf->chan.threewaycalling;
12983 analog_p->transfer = conf->chan.transfer;
12984 analog_p->transfertobusy = conf->chan.transfertobusy;
12985 analog_p->use_callerid = tmp->use_callerid;
12986 analog_p->use_smdi = tmp->use_smdi;
12987 analog_p->smdi_iface = tmp->smdi_iface;
12988 analog_p->outsigmod = ANALOG_SIG_NONE;
12989 analog_p->echotraining = conf->chan.echotraining;
12990 analog_p->cid_signalling = conf->chan.cid_signalling;
12991 analog_p->stripmsd = conf->chan.stripmsd;
12992 switch (conf->chan.cid_start) {
12993 case CID_START_POLARITY:
12994 analog_p->cid_start = ANALOG_CID_START_POLARITY;
12995 break;
12996 case CID_START_POLARITY_IN:
12997 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12998 break;
12999 case CID_START_DTMF_NOALERT:
13000 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13001 break;
13002 default:
13003 analog_p->cid_start = ANALOG_CID_START_RING;
13004 break;
13005 }
13006 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13007 analog_p->ringt = conf->chan.ringt;
13008 analog_p->ringt_base = ringt_base;
13009 analog_p->chan_tech = &dahdi_tech;
13010 analog_p->onhooktime = time(NULL);
13011 if (chan_sig & __DAHDI_SIG_FXO) {
13012 memset(&p, 0, sizeof(p));
13013 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13014 if (!res) {
13015 analog_p->fxsoffhookstate = p.rxisoffhook;
13016 }
13017 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13018 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13019 #endif
13020 }
13021 analog_p->msgstate = -1;
13022
13023 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13024 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13025 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13026
13027 analog_config_complete(analog_p);
13028 }
13029 break;
13030 }
13031 #if defined(HAVE_PRI)
13032 if (tmp->channel == CHAN_PSEUDO) {
13033
13034
13035
13036
13037 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13038 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13039 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13040 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13041 }
13042 #endif
13043 }
13044 if (tmp && !here) {
13045
13046 dahdi_iflist_insert(tmp);
13047 }
13048 return tmp;
13049 }
13050
13051 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13052 {
13053 #if defined(HAVE_PRI)
13054 if (0 < span) {
13055
13056 if (!p->pri || p->pri->span != span) {
13057 return 0;
13058 }
13059 if (!groupmatch && channelmatch == -1) {
13060
13061 *groupmatched = 1;
13062 return 1;
13063 }
13064 }
13065 #endif
13066
13067 if (groupmatch) {
13068 if ((p->group & groupmatch) != groupmatch)
13069
13070 return 0;
13071 *groupmatched = 1;
13072 }
13073
13074 if (channelmatch != -1) {
13075 if (p->channel != channelmatch)
13076
13077 return 0;
13078 *channelmatched = 1;
13079 }
13080
13081 return 1;
13082 }
13083
13084 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13085 {
13086 struct dahdi_pvt *p = *pvt;
13087
13088 if (p->inalarm)
13089 return 0;
13090
13091 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13092 return analog_available(p->sig_pvt);
13093
13094 switch (p->sig) {
13095 #if defined(HAVE_PRI)
13096 case SIG_PRI_LIB_HANDLE_CASES:
13097 {
13098 struct sig_pri_chan *pvt_chan;
13099 int res;
13100
13101 pvt_chan = p->sig_pvt;
13102 res = sig_pri_available(&pvt_chan, is_specific_channel);
13103 *pvt = pvt_chan->chan_pvt;
13104 return res;
13105 }
13106 #endif
13107 #if defined(HAVE_SS7)
13108 case SIG_SS7:
13109 return sig_ss7_available(p->sig_pvt);
13110 #endif
13111 default:
13112 break;
13113 }
13114
13115 if (p->locallyblocked || p->remotelyblocked) {
13116 return 0;
13117 }
13118
13119
13120 if (!p->owner) {
13121 #ifdef HAVE_OPENR2
13122
13123 if (p->mfcr2) {
13124 if (p->mfcr2call) {
13125 return 0;
13126 } else {
13127 return 1;
13128 }
13129 }
13130 #endif
13131 return 1;
13132 }
13133
13134 return 0;
13135 }
13136
13137 #if defined(HAVE_PRI)
13138 #if defined(HAVE_PRI_CALL_WAITING)
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149
13150
13151 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13152 {
13153 struct dahdi_pvt *pvt = priv;
13154
13155 pvt->stripmsd = pri->ch_cfg.stripmsd;
13156 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13157 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13158 pvt->immediate = pri->ch_cfg.immediate;
13159 pvt->priexclusive = pri->ch_cfg.priexclusive;
13160 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13161 pvt->use_callerid = pri->ch_cfg.use_callerid;
13162 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13163 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13164 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13165 }
13166 #endif
13167 #endif
13168
13169 #if defined(HAVE_PRI)
13170
13171
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13183 {
13184 int pvt_idx;
13185 int res;
13186 unsigned idx;
13187 struct dahdi_pvt *pvt;
13188 struct sig_pri_chan *chan;
13189 struct dahdi_bufferinfo bi;
13190
13191 static int nobch_channel = CHAN_PSEUDO;
13192
13193
13194 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13195 if (!pri->pvts[pvt_idx]) {
13196 break;
13197 }
13198 }
13199 if (pri->numchans == pvt_idx) {
13200 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13201 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13202 return -1;
13203 }
13204
13205
13206 pri->pvts[pvt_idx] = NULL;
13207 ++pri->numchans;
13208 }
13209
13210 pvt = ast_calloc(1, sizeof(*pvt));
13211 if (!pvt) {
13212 return -1;
13213 }
13214 pvt->cc_params = ast_cc_config_params_init();
13215 if (!pvt->cc_params) {
13216 ast_free(pvt);
13217 return -1;
13218 }
13219 ast_mutex_init(&pvt->lock);
13220 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13221 pvt->subs[idx].dfd = -1;
13222 }
13223 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13224 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13225 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13226 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13227
13228 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13229 if (!chan) {
13230 destroy_dahdi_pvt(pvt);
13231 return -1;
13232 }
13233 chan->no_b_channel = 1;
13234
13235
13236
13237
13238
13239
13240 pvt->law_default = DAHDI_LAW_ALAW;
13241
13242 pvt->sig = pri->sig;
13243 pvt->outsigmod = -1;
13244 pvt->pri = pri;
13245 pvt->sig_pvt = chan;
13246 pri->pvts[pvt_idx] = chan;
13247
13248 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13249 if (pvt->subs[SUB_REAL].dfd < 0) {
13250 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13251 strerror(errno));
13252 destroy_dahdi_pvt(pvt);
13253 return -1;
13254 }
13255 memset(&bi, 0, sizeof(bi));
13256 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13257 if (!res) {
13258 pvt->bufsize = bi.bufsize;
13259 bi.txbufpolicy = pvt->buf_policy;
13260 bi.rxbufpolicy = pvt->buf_policy;
13261 bi.numbufs = pvt->buf_no;
13262 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13263 if (res < 0) {
13264 ast_log(LOG_WARNING,
13265 "Unable to set buffer policy on no B channel interface: %s\n",
13266 strerror(errno));
13267 }
13268 } else
13269 ast_log(LOG_WARNING,
13270 "Unable to check buffer policy on no B channel interface: %s\n",
13271 strerror(errno));
13272
13273 --nobch_channel;
13274 if (CHAN_PSEUDO < nobch_channel) {
13275 nobch_channel = CHAN_PSEUDO - 1;
13276 }
13277 pvt->channel = nobch_channel;
13278 pvt->span = pri->span;
13279 chan->channel = pvt->channel;
13280
13281 dahdi_nobch_insert(pri, pvt);
13282
13283 return pvt_idx;
13284 }
13285 #endif
13286
13287
13288
13289
13290
13291
13292 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13293 {
13294 struct dahdi_pvt *p;
13295 struct dahdi_bufferinfo bi;
13296 int res;
13297
13298 p = ast_malloc(sizeof(*p));
13299 if (!p) {
13300 return NULL;
13301 }
13302 *p = *src;
13303
13304
13305 p->cc_params = ast_cc_config_params_init();
13306 if (!p->cc_params) {
13307 ast_free(p);
13308 return NULL;
13309 }
13310 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13311
13312 p->which_iflist = DAHDI_IFLIST_NONE;
13313 p->next = NULL;
13314 p->prev = NULL;
13315 ast_mutex_init(&p->lock);
13316 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13317 if (p->subs[SUB_REAL].dfd < 0) {
13318 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13319 destroy_dahdi_pvt(p);
13320 return NULL;
13321 }
13322 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13323 if (!res) {
13324 bi.txbufpolicy = src->buf_policy;
13325 bi.rxbufpolicy = src->buf_policy;
13326 bi.numbufs = src->buf_no;
13327 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13328 if (res < 0) {
13329 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13330 }
13331 } else
13332 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13333 p->destroy = 1;
13334 dahdi_iflist_insert(p);
13335 return p;
13336 }
13337
13338 struct dahdi_starting_point {
13339
13340 ast_group_t groupmatch;
13341
13342 int channelmatch;
13343
13344 int rr_starting_point;
13345
13346 int span;
13347
13348 int cadance;
13349
13350 char opt;
13351
13352 char backwards;
13353
13354 char roundrobin;
13355 };
13356 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13357 {
13358 char *dest;
13359 char *s;
13360 int x;
13361 int res = 0;
13362 struct dahdi_pvt *p;
13363 char *subdir = NULL;
13364 AST_DECLARE_APP_ARGS(args,
13365 AST_APP_ARG(group);
13366
13367
13368 AST_APP_ARG(other);
13369 );
13370
13371
13372
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385
13386
13387
13388
13389
13390
13391
13392
13393
13394 if (data) {
13395 dest = ast_strdupa(data);
13396 } else {
13397 ast_log(LOG_WARNING, "Channel requested with no data\n");
13398 return NULL;
13399 }
13400 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13401 if (!args.argc || ast_strlen_zero(args.group)) {
13402 ast_log(LOG_WARNING, "No channel/group specified\n");
13403 return NULL;
13404 }
13405
13406
13407 memset(param, 0, sizeof(*param));
13408 param->channelmatch = -1;
13409
13410 if (strchr(args.group, '!') != NULL) {
13411 char *prev = args.group;
13412 while ((s = strchr(prev, '!')) != NULL) {
13413 *s++ = '/';
13414 prev = s;
13415 }
13416 *(prev - 1) = '\0';
13417 subdir = args.group;
13418 args.group = prev;
13419 } else if (args.group[0] == 'i') {
13420
13421 res = sscanf(args.group + 1, "%30d", &x);
13422 if (res < 1) {
13423 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13424 return NULL;
13425 }
13426 param->span = x;
13427
13428
13429 s = strchr(args.group, '-');
13430 if (!s) {
13431
13432 return iflist;
13433 }
13434 args.group = s + 1;
13435 res = 0;
13436 }
13437 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13438
13439 s = args.group + 1;
13440 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13441 if (res < 1) {
13442 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13443 return NULL;
13444 }
13445 param->groupmatch = ((ast_group_t) 1 << x);
13446
13447 if (toupper(args.group[0]) == 'G') {
13448 if (args.group[0] == 'G') {
13449 param->backwards = 1;
13450 p = ifend;
13451 } else
13452 p = iflist;
13453 } else {
13454 if (ARRAY_LEN(round_robin) <= x) {
13455 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13456 x, data);
13457 return NULL;
13458 }
13459 if (args.group[0] == 'R') {
13460 param->backwards = 1;
13461 p = round_robin[x] ? round_robin[x]->prev : ifend;
13462 if (!p)
13463 p = ifend;
13464 } else {
13465 p = round_robin[x] ? round_robin[x]->next : iflist;
13466 if (!p)
13467 p = iflist;
13468 }
13469 param->roundrobin = 1;
13470 param->rr_starting_point = x;
13471 }
13472 } else {
13473 s = args.group;
13474 if (!strcasecmp(s, "pseudo")) {
13475
13476 x = CHAN_PSEUDO;
13477 param->channelmatch = x;
13478 } else {
13479 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13480 if (res < 1) {
13481 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13482 return NULL;
13483 } else {
13484 param->channelmatch = x;
13485 }
13486 }
13487 if (subdir) {
13488 char path[PATH_MAX];
13489 struct stat stbuf;
13490
13491 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13492 subdir, param->channelmatch);
13493 if (stat(path, &stbuf) < 0) {
13494 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13495 path, strerror(errno));
13496 return NULL;
13497 }
13498 if (!S_ISCHR(stbuf.st_mode)) {
13499 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13500 path);
13501 return NULL;
13502 }
13503 param->channelmatch = minor(stbuf.st_rdev);
13504 }
13505
13506 p = iflist;
13507 }
13508
13509 if (param->opt == 'r' && res < 3) {
13510 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13511 param->opt = '\0';
13512 }
13513
13514 return p;
13515 }
13516
13517 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13518 {
13519 int callwait = 0;
13520 struct dahdi_pvt *p;
13521 struct ast_channel *tmp = NULL;
13522 struct dahdi_pvt *exitpvt;
13523 int channelmatched = 0;
13524 int groupmatched = 0;
13525 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13526 int transcapdigital = 0;
13527 #endif
13528 struct dahdi_starting_point start;
13529
13530 ast_mutex_lock(&iflock);
13531 p = determine_starting_point(data, &start);
13532 if (!p) {
13533
13534 ast_mutex_unlock(&iflock);
13535 return NULL;
13536 }
13537
13538
13539 exitpvt = p;
13540 while (p && !tmp) {
13541 if (start.roundrobin)
13542 round_robin[start.rr_starting_point] = p;
13543
13544 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13545 && available(&p, channelmatched)) {
13546 ast_debug(1, "Using channel %d\n", p->channel);
13547
13548 callwait = (p->owner != NULL);
13549 #ifdef HAVE_OPENR2
13550 if (p->mfcr2) {
13551 ast_mutex_lock(&p->lock);
13552 if (p->mfcr2call) {
13553 ast_mutex_unlock(&p->lock);
13554 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13555 goto next;
13556 }
13557 p->mfcr2call = 1;
13558 ast_mutex_unlock(&p->lock);
13559 }
13560 #endif
13561 if (p->channel == CHAN_PSEUDO) {
13562 p = duplicate_pseudo(p);
13563 if (!p) {
13564 break;
13565 }
13566 }
13567
13568 p->distinctivering = 0;
13569
13570 switch (start.opt) {
13571 case '\0':
13572
13573 break;
13574 case 'c':
13575
13576 p->confirmanswer = 1;
13577 break;
13578 case 'r':
13579
13580 p->distinctivering = start.cadance;
13581 break;
13582 case 'd':
13583 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13584
13585 transcapdigital = AST_TRANS_CAP_DIGITAL;
13586 #endif
13587 break;
13588 default:
13589 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13590 break;
13591 }
13592
13593 p->outgoing = 1;
13594 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13595 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13596 #ifdef HAVE_PRI
13597 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13598
13599
13600
13601
13602
13603 ast_mutex_lock(&p->lock);
13604 ast_mutex_unlock(&p->lock);
13605
13606 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13607 sizeof(p->dnid));
13608 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13609 #endif
13610 #if defined(HAVE_SS7)
13611 } else if (p->sig == SIG_SS7) {
13612 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13613 #endif
13614 } else {
13615 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13616 }
13617 if (!tmp) {
13618 p->outgoing = 0;
13619 #if defined(HAVE_PRI)
13620 switch (p->sig) {
13621 case SIG_PRI_LIB_HANDLE_CASES:
13622 #if defined(HAVE_PRI_CALL_WAITING)
13623 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13624 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13625 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13626 }
13627 #endif
13628
13629
13630
13631
13632 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13633 break;
13634 default:
13635 break;
13636 }
13637 #endif
13638 } else {
13639 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13640 }
13641 break;
13642 }
13643 #ifdef HAVE_OPENR2
13644 next:
13645 #endif
13646 if (start.backwards) {
13647 p = p->prev;
13648 if (!p)
13649 p = ifend;
13650 } else {
13651 p = p->next;
13652 if (!p)
13653 p = iflist;
13654 }
13655
13656 if (p == exitpvt)
13657 break;
13658 }
13659 ast_mutex_unlock(&iflock);
13660 restart_monitor();
13661 if (cause && !tmp) {
13662 if (callwait || channelmatched) {
13663 *cause = AST_CAUSE_BUSY;
13664 } else if (groupmatched) {
13665 *cause = AST_CAUSE_CONGESTION;
13666 } else {
13667
13668
13669
13670
13671 }
13672 }
13673
13674 return tmp;
13675 }
13676
13677
13678
13679
13680
13681
13682
13683
13684
13685
13686
13687 static int dahdi_devicestate(void *data)
13688 {
13689 #if defined(HAVE_PRI)
13690 char *device;
13691 unsigned span;
13692 int res;
13693
13694 device = data;
13695
13696 if (*device != 'I') {
13697
13698 return AST_DEVICE_UNKNOWN;
13699 }
13700 res = sscanf(device, "I%30u", &span);
13701 if (res != 1 || !span || NUM_SPANS < span) {
13702
13703 return AST_DEVICE_UNKNOWN;
13704 }
13705 device = strchr(device, '/');
13706 if (!device) {
13707
13708 return AST_DEVICE_UNKNOWN;
13709 }
13710
13711
13712
13713
13714
13715 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13716 ++device;
13717 if (!strcmp(device, "congestion"))
13718 #endif
13719 {
13720 return pris[span - 1].pri.congestion_devstate;
13721 }
13722 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13723 else if (!strcmp(device, "threshold")) {
13724 return pris[span - 1].pri.threshold_devstate;
13725 }
13726 return AST_DEVICE_UNKNOWN;
13727 #endif
13728 #else
13729 return AST_DEVICE_UNKNOWN;
13730 #endif
13731 }
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
13749 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13750 {
13751 struct dahdi_pvt *p;
13752 struct dahdi_pvt *exitpvt;
13753 struct dahdi_starting_point start;
13754 int groupmatched = 0;
13755 int channelmatched = 0;
13756
13757 ast_mutex_lock(&iflock);
13758 p = determine_starting_point(dest, &start);
13759 if (!p) {
13760 ast_mutex_unlock(&iflock);
13761 return -1;
13762 }
13763 exitpvt = p;
13764 for (;;) {
13765 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13766
13767 struct ast_str *device_name;
13768 char *dash;
13769 const char *monitor_type;
13770 char dialstring[AST_CHANNEL_NAME];
13771 char full_device_name[AST_CHANNEL_NAME];
13772
13773 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13774 case AST_CC_MONITOR_NEVER:
13775 break;
13776 case AST_CC_MONITOR_NATIVE:
13777 case AST_CC_MONITOR_ALWAYS:
13778 case AST_CC_MONITOR_GENERIC:
13779 #if defined(HAVE_PRI)
13780 if (dahdi_sig_pri_lib_handles(p->sig)) {
13781
13782
13783
13784
13785 snprintf(full_device_name, sizeof(full_device_name),
13786 "DAHDI/I%d/congestion", p->pri->span);
13787 } else
13788 #endif
13789 {
13790 #if defined(HAVE_PRI)
13791 device_name = create_channel_name(p, 1, "");
13792 #else
13793 device_name = create_channel_name(p);
13794 #endif
13795 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13796 device_name ? ast_str_buffer(device_name) : "");
13797 ast_free(device_name);
13798
13799
13800
13801
13802
13803 dash = strrchr(full_device_name, '-');
13804 if (dash) {
13805 *dash = '\0';
13806 }
13807 }
13808 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13809
13810
13811
13812
13813
13814
13815
13816 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13817 callback(inbound,
13818 #if defined(HAVE_PRI)
13819 p->pri ? p->pri->cc_params : p->cc_params,
13820 #else
13821 p->cc_params,
13822 #endif
13823 monitor_type, full_device_name, dialstring, NULL);
13824 break;
13825 }
13826 }
13827 p = start.backwards ? p->prev : p->next;
13828 if (!p) {
13829 p = start.backwards ? ifend : iflist;
13830 }
13831 if (p == exitpvt) {
13832 break;
13833 }
13834 }
13835 ast_mutex_unlock(&iflock);
13836 return 0;
13837 }
13838
13839 #if defined(HAVE_SS7)
13840 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13841 {
13842 int i;
13843
13844 if (ss7) {
13845 for (i = 0; i < NUM_SPANS; i++) {
13846 if (linksets[i].ss7.ss7 == ss7) {
13847 ast_verbose("[%d] %s", i + 1, s);
13848 return;
13849 }
13850 }
13851 }
13852 ast_verbose("%s", s);
13853 }
13854 #endif
13855
13856 #if defined(HAVE_SS7)
13857 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13858 {
13859 int i;
13860
13861 if (ss7) {
13862 for (i = 0; i < NUM_SPANS; i++) {
13863 if (linksets[i].ss7.ss7 == ss7) {
13864 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13865 return;
13866 }
13867 }
13868 }
13869 ast_log(LOG_ERROR, "%s", s);
13870 }
13871 #endif
13872
13873 #if defined(HAVE_OPENR2)
13874 static void *mfcr2_monitor(void *data)
13875 {
13876 struct dahdi_mfcr2 *mfcr2 = data;
13877
13878
13879
13880
13881
13882 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13883 int res = 0;
13884 int i = 0;
13885 int oldstate = 0;
13886 int quit_loop = 0;
13887 int maxsleep = 20;
13888 int was_idle = 0;
13889 int pollsize = 0;
13890
13891
13892 for (i = 0; i < mfcr2->numchans; i++) {
13893 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13894 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13895 }
13896 while (1) {
13897
13898
13899 pollsize = 0;
13900 for (i = 0; i < mfcr2->numchans; i++) {
13901 pollers[i].revents = 0;
13902 pollers[i].events = 0;
13903 if (mfcr2->pvts[i]->owner) {
13904 continue;
13905 }
13906 if (!mfcr2->pvts[i]->r2chan) {
13907 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13908 quit_loop = 1;
13909 break;
13910 }
13911 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13912 pollers[i].events = POLLIN | POLLPRI;
13913 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13914 pollsize++;
13915 }
13916 if (quit_loop) {
13917 break;
13918 }
13919 if (pollsize == 0) {
13920 if (!was_idle) {
13921 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13922 was_idle = 1;
13923 }
13924 poll(NULL, 0, maxsleep);
13925 continue;
13926 }
13927 was_idle = 0;
13928
13929
13930 pthread_testcancel();
13931 res = poll(pollers, mfcr2->numchans, maxsleep);
13932 pthread_testcancel();
13933 if ((res < 0) && (errno != EINTR)) {
13934 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13935 break;
13936 }
13937
13938 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13939 for (i = 0; i < mfcr2->numchans; i++) {
13940 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13941 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13942 }
13943 }
13944 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13945 }
13946 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13947 return 0;
13948 }
13949 #endif
13950
13951 #if defined(HAVE_PRI)
13952 #ifndef PRI_RESTART
13953 #error "Upgrade your libpri"
13954 #endif
13955 static void dahdi_pri_message(struct pri *pri, char *s)
13956 {
13957 int x;
13958 int y;
13959 int dchan = -1;
13960 int span = -1;
13961 int dchancount = 0;
13962
13963 if (pri) {
13964 for (x = 0; x < NUM_SPANS; x++) {
13965 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13966 if (pris[x].pri.dchans[y]) {
13967 dchancount++;
13968 }
13969
13970 if (pris[x].pri.dchans[y] == pri) {
13971 dchan = y;
13972 }
13973 }
13974 if (dchan >= 0) {
13975 span = x;
13976 break;
13977 }
13978 dchancount = 0;
13979 }
13980 if (-1 < span) {
13981 if (1 < dchancount) {
13982 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13983 } else {
13984 ast_verbose("PRI Span: %d %s", span + 1, s);
13985 }
13986 } else {
13987 ast_verbose("PRI Span: ? %s", s);
13988 }
13989 } else {
13990 ast_verbose("PRI Span: ? %s", s);
13991 }
13992
13993 ast_mutex_lock(&pridebugfdlock);
13994
13995 if (pridebugfd >= 0) {
13996 if (write(pridebugfd, s, strlen(s)) < 0) {
13997 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13998 }
13999 }
14000
14001 ast_mutex_unlock(&pridebugfdlock);
14002 }
14003 #endif
14004
14005 #if defined(HAVE_PRI)
14006 static void dahdi_pri_error(struct pri *pri, char *s)
14007 {
14008 int x;
14009 int y;
14010 int dchan = -1;
14011 int span = -1;
14012 int dchancount = 0;
14013
14014 if (pri) {
14015 for (x = 0; x < NUM_SPANS; x++) {
14016 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14017 if (pris[x].pri.dchans[y]) {
14018 dchancount++;
14019 }
14020
14021 if (pris[x].pri.dchans[y] == pri) {
14022 dchan = y;
14023 }
14024 }
14025 if (dchan >= 0) {
14026 span = x;
14027 break;
14028 }
14029 dchancount = 0;
14030 }
14031 if (-1 < span) {
14032 if (1 < dchancount) {
14033 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14034 } else {
14035 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14036 }
14037 } else {
14038 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14039 }
14040 } else {
14041 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14042 }
14043
14044 ast_mutex_lock(&pridebugfdlock);
14045
14046 if (pridebugfd >= 0) {
14047 if (write(pridebugfd, s, strlen(s)) < 0) {
14048 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14049 }
14050 }
14051
14052 ast_mutex_unlock(&pridebugfdlock);
14053 }
14054 #endif
14055
14056 #if defined(HAVE_PRI)
14057 static int prepare_pri(struct dahdi_pri *pri)
14058 {
14059 int i, res, x;
14060 struct dahdi_params p;
14061 struct dahdi_bufferinfo bi;
14062 struct dahdi_spaninfo si;
14063
14064 pri->pri.calls = &dahdi_pri_callbacks;
14065
14066 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14067 if (!pri->dchannels[i])
14068 break;
14069 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14070 x = pri->dchannels[i];
14071 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14072 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14073 return -1;
14074 }
14075 memset(&p, 0, sizeof(p));
14076 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14077 if (res) {
14078 dahdi_close_pri_fd(pri, i);
14079 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14080 return -1;
14081 }
14082 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14083 dahdi_close_pri_fd(pri, i);
14084 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14085 return -1;
14086 }
14087 memset(&si, 0, sizeof(si));
14088 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14089 if (res) {
14090 dahdi_close_pri_fd(pri, i);
14091 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14092 }
14093 if (!si.alarms) {
14094 pri_event_noalarm(&pri->pri, i, 1);
14095 } else {
14096 pri_event_alarm(&pri->pri, i, 1);
14097 }
14098 memset(&bi, 0, sizeof(bi));
14099 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14100 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14101 bi.numbufs = 32;
14102 bi.bufsize = 1024;
14103 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14104 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14105 dahdi_close_pri_fd(pri, i);
14106 return -1;
14107 }
14108 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14109 }
14110 return 0;
14111 }
14112 #endif
14113
14114 #if defined(HAVE_PRI)
14115 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14116 {
14117 int which, span;
14118 char *ret = NULL;
14119
14120 if (pos != rpos)
14121 return ret;
14122
14123 for (which = span = 0; span < NUM_SPANS; span++) {
14124 if (pris[span].pri.pri && ++which > state) {
14125 if (asprintf(&ret, "%d", span + 1) < 0) {
14126 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14127 }
14128 break;
14129 }
14130 }
14131 return ret;
14132 }
14133 #endif
14134
14135 #if defined(HAVE_PRI)
14136 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14137 {
14138 return complete_span_helper(line,word,pos,state,3);
14139 }
14140 #endif
14141
14142 #if defined(HAVE_PRI)
14143 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14144 {
14145 int myfd;
14146 switch (cmd) {
14147 case CLI_INIT:
14148 e->command = "pri set debug file";
14149 e->usage = "Usage: pri set debug file [output-file]\n"
14150 " Sends PRI debug output to the specified output file\n";
14151 return NULL;
14152 case CLI_GENERATE:
14153 return NULL;
14154 }
14155 if (a->argc < 5)
14156 return CLI_SHOWUSAGE;
14157
14158 if (ast_strlen_zero(a->argv[4]))
14159 return CLI_SHOWUSAGE;
14160
14161 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14162 if (myfd < 0) {
14163 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14164 return CLI_SUCCESS;
14165 }
14166
14167 ast_mutex_lock(&pridebugfdlock);
14168
14169 if (pridebugfd >= 0)
14170 close(pridebugfd);
14171
14172 pridebugfd = myfd;
14173 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14174 ast_mutex_unlock(&pridebugfdlock);
14175 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14176 return CLI_SUCCESS;
14177 }
14178 #endif
14179
14180 #if defined(HAVE_PRI)
14181 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14182 {
14183 int span;
14184 int x;
14185 int level = 0;
14186 switch (cmd) {
14187 case CLI_INIT:
14188 e->command = "pri set debug {on|off|0|1|2} span";
14189 e->usage =
14190 "Usage: pri set debug {<level>|on|off} span <span>\n"
14191 " Enables debugging on a given PRI span\n";
14192 return NULL;
14193 case CLI_GENERATE:
14194 return complete_span_4(a->line, a->word, a->pos, a->n);
14195 }
14196 if (a->argc < 6) {
14197 return CLI_SHOWUSAGE;
14198 }
14199
14200 if (!strcasecmp(a->argv[3], "on")) {
14201 level = 1;
14202 } else if (!strcasecmp(a->argv[3], "off")) {
14203 level = 0;
14204 } else {
14205 level = atoi(a->argv[3]);
14206 }
14207 span = atoi(a->argv[5]);
14208 if ((span < 1) || (span > NUM_SPANS)) {
14209 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14210 return CLI_SUCCESS;
14211 }
14212 if (!pris[span-1].pri.pri) {
14213 ast_cli(a->fd, "No PRI running on span %d\n", span);
14214 return CLI_SUCCESS;
14215 }
14216
14217
14218 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14219 if (pris[span - 1].pri.dchans[x]) {
14220 switch (level) {
14221 case 0:
14222 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14223 break;
14224 case 1:
14225 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14226 break;
14227 default:
14228 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14229 break;
14230 }
14231 }
14232 }
14233 if (level == 0) {
14234
14235 ast_mutex_lock(&pridebugfdlock);
14236 if (0 <= pridebugfd) {
14237 close(pridebugfd);
14238 pridebugfd = -1;
14239 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14240 pridebugfilename);
14241 }
14242 ast_mutex_unlock(&pridebugfdlock);
14243 }
14244 pris[span - 1].pri.debug = (level) ? 1 : 0;
14245 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14246 return CLI_SUCCESS;
14247 }
14248 #endif
14249
14250 #if defined(HAVE_PRI)
14251 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14252 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14253 {
14254 unsigned *why;
14255 int channel;
14256 int trunkgroup;
14257 int x, y, fd = a->fd;
14258 int interfaceid = 0;
14259 char *c;
14260 char db_chan_name[20], db_answer[5];
14261 struct dahdi_pvt *tmp;
14262 struct dahdi_pri *pri;
14263
14264 if (a->argc < 5 || a->argc > 6)
14265 return CLI_SHOWUSAGE;
14266 if ((c = strchr(a->argv[4], ':'))) {
14267 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14268 return CLI_SHOWUSAGE;
14269 if ((trunkgroup < 1) || (channel < 1))
14270 return CLI_SHOWUSAGE;
14271 pri = NULL;
14272 for (x=0;x<NUM_SPANS;x++) {
14273 if (pris[x].pri.trunkgroup == trunkgroup) {
14274 pri = pris + x;
14275 break;
14276 }
14277 }
14278 if (!pri) {
14279 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14280 return CLI_FAILURE;
14281 }
14282 } else
14283 channel = atoi(a->argv[4]);
14284
14285 if (a->argc == 6)
14286 interfaceid = atoi(a->argv[5]);
14287
14288
14289 for (x = 0; x < NUM_SPANS; x++) {
14290 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14291 if (pris[x].dchannels[y] == channel) {
14292 pri = pris + x;
14293 if (pri->pri.enable_service_message_support) {
14294 ast_mutex_lock(&pri->pri.lock);
14295 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14296 ast_mutex_unlock(&pri->pri.lock);
14297 } else {
14298 ast_cli(fd,
14299 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14300 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14301 }
14302 return CLI_SUCCESS;
14303 }
14304 }
14305 }
14306
14307
14308 ast_mutex_lock(&iflock);
14309 for (tmp = iflist; tmp; tmp = tmp->next) {
14310 if (tmp->pri && tmp->channel == channel) {
14311 ast_mutex_unlock(&iflock);
14312 ast_mutex_lock(&tmp->pri->lock);
14313 if (!tmp->pri->enable_service_message_support) {
14314 ast_mutex_unlock(&tmp->pri->lock);
14315 ast_cli(fd,
14316 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14317 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14318 return CLI_SUCCESS;
14319 }
14320 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14321 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14322 switch(changestatus) {
14323 case 0:
14324
14325 ast_db_del(db_chan_name, SRVST_DBKEY);
14326 *why &= ~SRVST_NEAREND;
14327 if (*why) {
14328 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14329 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14330 } else {
14331 dahdi_pri_update_span_devstate(tmp->pri);
14332 }
14333 break;
14334
14335 case 2:
14336
14337 ast_db_del(db_chan_name, SRVST_DBKEY);
14338 *why |= SRVST_NEAREND;
14339 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14340 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14341 dahdi_pri_update_span_devstate(tmp->pri);
14342 break;
14343
14344
14345 default:
14346 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14347 break;
14348 }
14349 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14350 ast_mutex_unlock(&tmp->pri->lock);
14351 return CLI_SUCCESS;
14352 }
14353 }
14354 ast_mutex_unlock(&iflock);
14355
14356 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14357 return CLI_FAILURE;
14358 }
14359
14360 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14361 {
14362 switch (cmd) {
14363 case CLI_INIT:
14364 e->command = "pri service enable channel";
14365 e->usage =
14366 "Usage: pri service enable channel <channel> [<interface id>]\n"
14367 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14368 " to restore a channel to service, with optional interface id\n"
14369 " as agreed upon with remote switch operator\n";
14370 return NULL;
14371 case CLI_GENERATE:
14372 return NULL;
14373 }
14374 return handle_pri_service_generic(e, cmd, a, 0);
14375 }
14376
14377 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14378 {
14379 switch (cmd) {
14380 case CLI_INIT:
14381 e->command = "pri service disable channel";
14382 e->usage =
14383 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14384 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14385 " to remove a channel from service, with optional interface id\n"
14386 " as agreed upon with remote switch operator\n";
14387 return NULL;
14388 case CLI_GENERATE:
14389 return NULL;
14390 }
14391 return handle_pri_service_generic(e, cmd, a, 2);
14392 }
14393 #endif
14394 #endif
14395
14396 #if defined(HAVE_PRI)
14397 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14398 {
14399 int span;
14400
14401 switch (cmd) {
14402 case CLI_INIT:
14403 e->command = "pri show channels";
14404 e->usage =
14405 "Usage: pri show channels\n"
14406 " Displays PRI channel information such as the current mapping\n"
14407 " of DAHDI B channels to Asterisk channel names and which calls\n"
14408 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14409 " are not associated with any B channel.\n";
14410 return NULL;
14411 case CLI_GENERATE:
14412 return NULL;
14413 }
14414
14415 if (a->argc != 3)
14416 return CLI_SHOWUSAGE;
14417
14418 sig_pri_cli_show_channels_header(a->fd);
14419 for (span = 0; span < NUM_SPANS; ++span) {
14420 if (pris[span].pri.pri) {
14421 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14422 }
14423 }
14424 return CLI_SUCCESS;
14425 }
14426 #endif
14427
14428 #if defined(HAVE_PRI)
14429 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14430 {
14431 int span;
14432
14433 switch (cmd) {
14434 case CLI_INIT:
14435 e->command = "pri show spans";
14436 e->usage =
14437 "Usage: pri show spans\n"
14438 " Displays PRI span information\n";
14439 return NULL;
14440 case CLI_GENERATE:
14441 return NULL;
14442 }
14443
14444 if (a->argc != 3)
14445 return CLI_SHOWUSAGE;
14446
14447 for (span = 0; span < NUM_SPANS; span++) {
14448 if (pris[span].pri.pri) {
14449 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14450 }
14451 }
14452 return CLI_SUCCESS;
14453 }
14454 #endif
14455
14456 #if defined(HAVE_PRI)
14457 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14458 {
14459 int span;
14460
14461 switch (cmd) {
14462 case CLI_INIT:
14463 e->command = "pri show span";
14464 e->usage =
14465 "Usage: pri show span <span>\n"
14466 " Displays PRI Information on a given PRI span\n";
14467 return NULL;
14468 case CLI_GENERATE:
14469 return complete_span_4(a->line, a->word, a->pos, a->n);
14470 }
14471
14472 if (a->argc < 4)
14473 return CLI_SHOWUSAGE;
14474 span = atoi(a->argv[3]);
14475 if ((span < 1) || (span > NUM_SPANS)) {
14476 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14477 return CLI_SUCCESS;
14478 }
14479 if (!pris[span-1].pri.pri) {
14480 ast_cli(a->fd, "No PRI running on span %d\n", span);
14481 return CLI_SUCCESS;
14482 }
14483
14484 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14485
14486 return CLI_SUCCESS;
14487 }
14488 #endif
14489
14490 #if defined(HAVE_PRI)
14491 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14492 {
14493 int x;
14494 int span;
14495 int count=0;
14496 int debug;
14497
14498 switch (cmd) {
14499 case CLI_INIT:
14500 e->command = "pri show debug";
14501 e->usage =
14502 "Usage: pri show debug\n"
14503 " Show the debug state of pri spans\n";
14504 return NULL;
14505 case CLI_GENERATE:
14506 return NULL;
14507 }
14508
14509 for (span = 0; span < NUM_SPANS; span++) {
14510 if (pris[span].pri.pri) {
14511 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14512 if (pris[span].pri.dchans[x]) {
14513 debug = pri_get_debug(pris[span].pri.dchans[x]);
14514 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" );
14515 count++;
14516 }
14517 }
14518 }
14519
14520 }
14521 ast_mutex_lock(&pridebugfdlock);
14522 if (pridebugfd >= 0)
14523 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14524 ast_mutex_unlock(&pridebugfdlock);
14525
14526 if (!count)
14527 ast_cli(a->fd, "No PRI running\n");
14528 return CLI_SUCCESS;
14529 }
14530 #endif
14531
14532 #if defined(HAVE_PRI)
14533 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14534 {
14535 switch (cmd) {
14536 case CLI_INIT:
14537 e->command = "pri show version";
14538 e->usage =
14539 "Usage: pri show version\n"
14540 "Show libpri version information\n";
14541 return NULL;
14542 case CLI_GENERATE:
14543 return NULL;
14544 }
14545
14546 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14547
14548 return CLI_SUCCESS;
14549 }
14550 #endif
14551
14552 #if defined(HAVE_PRI)
14553 static struct ast_cli_entry dahdi_pri_cli[] = {
14554 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14555 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14556 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14557 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14558 #endif
14559 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14560 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14561 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14562 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14563 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14564 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14565 };
14566 #endif
14567
14568 #ifdef HAVE_OPENR2
14569
14570 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14571 {
14572 switch (cmd) {
14573 case CLI_INIT:
14574 e->command = "mfcr2 show version";
14575 e->usage =
14576 "Usage: mfcr2 show version\n"
14577 " Shows the version of the OpenR2 library being used.\n";
14578 return NULL;
14579 case CLI_GENERATE:
14580 return NULL;
14581 }
14582 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14583 return CLI_SUCCESS;
14584 }
14585
14586 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588 #define FORMAT "%4s %40s\n"
14589 int i = 0;
14590 int numvariants = 0;
14591 const openr2_variant_entry_t *variants;
14592 switch (cmd) {
14593 case CLI_INIT:
14594 e->command = "mfcr2 show variants";
14595 e->usage =
14596 "Usage: mfcr2 show variants\n"
14597 " Shows the list of MFC/R2 variants supported.\n";
14598 return NULL;
14599 case CLI_GENERATE:
14600 return NULL;
14601 }
14602 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14603 ast_cli(a->fd, "Failed to get list of variants.\n");
14604 return CLI_FAILURE;
14605 }
14606 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14607 for (i = 0; i < numvariants; i++) {
14608 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14609 }
14610 return CLI_SUCCESS;
14611 #undef FORMAT
14612 }
14613
14614 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14615 {
14616 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14617 int filtertype = 0;
14618 int targetnum = 0;
14619 char channo[5];
14620 char anino[5];
14621 char dnisno[5];
14622 struct dahdi_pvt *p;
14623 openr2_context_t *r2context;
14624 openr2_variant_t r2variant;
14625 switch (cmd) {
14626 case CLI_INIT:
14627 e->command = "mfcr2 show channels [group|context]";
14628 e->usage =
14629 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14630 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14631 return NULL;
14632 case CLI_GENERATE:
14633 return NULL;
14634 }
14635 if (!((a->argc == 3) || (a->argc == 5))) {
14636 return CLI_SHOWUSAGE;
14637 }
14638 if (a->argc == 5) {
14639 if (!strcasecmp(a->argv[3], "group")) {
14640 targetnum = atoi(a->argv[4]);
14641 if ((targetnum < 0) || (targetnum > 63))
14642 return CLI_SHOWUSAGE;
14643 targetnum = 1 << targetnum;
14644 filtertype = 1;
14645 } else if (!strcasecmp(a->argv[3], "context")) {
14646 filtertype = 2;
14647 } else {
14648 return CLI_SHOWUSAGE;
14649 }
14650 }
14651 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14652 ast_mutex_lock(&iflock);
14653 for (p = iflist; p; p = p->next) {
14654 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14655 continue;
14656 }
14657 if (filtertype) {
14658 switch(filtertype) {
14659 case 1:
14660 if (p->group != targetnum) {
14661 continue;
14662 }
14663 break;
14664 case 2:
14665 if (strcasecmp(p->context, a->argv[4])) {
14666 continue;
14667 }
14668 break;
14669 default:
14670 ;
14671 }
14672 }
14673 r2context = openr2_chan_get_context(p->r2chan);
14674 r2variant = openr2_context_get_variant(r2context);
14675 snprintf(channo, sizeof(channo), "%d", p->channel);
14676 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14677 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14678 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14679 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14680 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14681 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14682 }
14683 ast_mutex_unlock(&iflock);
14684 return CLI_SUCCESS;
14685 #undef FORMAT
14686 }
14687
14688 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14689 {
14690 struct dahdi_pvt *p = NULL;
14691 int channo = 0;
14692 char *toklevel = NULL;
14693 char *saveptr = NULL;
14694 char *logval = NULL;
14695 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14696 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14697 switch (cmd) {
14698 case CLI_INIT:
14699 e->command = "mfcr2 set debug";
14700 e->usage =
14701 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14702 " Set a new logging level for the specified channel.\n"
14703 " If no channel is specified the logging level will be applied to all channels.\n";
14704 return NULL;
14705 case CLI_GENERATE:
14706 return NULL;
14707 }
14708 if (a->argc < 4) {
14709 return CLI_SHOWUSAGE;
14710 }
14711 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14712 logval = ast_strdupa(a->argv[3]);
14713 toklevel = strtok_r(logval, ",", &saveptr);
14714 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14715 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14716 return CLI_FAILURE;
14717 } else if (OR2_LOG_NOTHING == tmplevel) {
14718 loglevel = tmplevel;
14719 } else {
14720 loglevel |= tmplevel;
14721 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14722 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14723 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14724 continue;
14725 }
14726 loglevel |= tmplevel;
14727 }
14728 }
14729 ast_mutex_lock(&iflock);
14730 for (p = iflist; p; p = p->next) {
14731 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14732 continue;
14733 }
14734 if ((channo != -1) && (p->channel != channo )) {
14735 continue;
14736 }
14737 openr2_chan_set_log_level(p->r2chan, loglevel);
14738 if (channo != -1) {
14739 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14740 break;
14741 }
14742 }
14743 if ((channo != -1) && !p) {
14744 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14745 }
14746 if (channo == -1) {
14747 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14748 }
14749 ast_mutex_unlock(&iflock);
14750 return CLI_SUCCESS;
14751 }
14752
14753 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14754 {
14755 struct dahdi_pvt *p = NULL;
14756 int channo = 0;
14757 switch (cmd) {
14758 case CLI_INIT:
14759 e->command = "mfcr2 call files [on|off]";
14760 e->usage =
14761 "Usage: mfcr2 call files [on|off] <channel>\n"
14762 " Enable call files creation on the specified channel.\n"
14763 " If no channel is specified call files creation policy will be applied to all channels.\n";
14764 return NULL;
14765 case CLI_GENERATE:
14766 return NULL;
14767 }
14768 if (a->argc < 4) {
14769 return CLI_SHOWUSAGE;
14770 }
14771 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14772 ast_mutex_lock(&iflock);
14773 for (p = iflist; p; p = p->next) {
14774 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14775 continue;
14776 }
14777 if ((channo != -1) && (p->channel != channo )) {
14778 continue;
14779 }
14780 if (ast_true(a->argv[3])) {
14781 openr2_chan_enable_call_files(p->r2chan);
14782 } else {
14783 openr2_chan_disable_call_files(p->r2chan);
14784 }
14785 if (channo != -1) {
14786 if (ast_true(a->argv[3])) {
14787 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14788 } else {
14789 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14790 }
14791 break;
14792 }
14793 }
14794 if ((channo != -1) && !p) {
14795 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14796 }
14797 if (channo == -1) {
14798 if (ast_true(a->argv[3])) {
14799 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14800 } else {
14801 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14802 }
14803 }
14804 ast_mutex_unlock(&iflock);
14805 return CLI_SUCCESS;
14806 }
14807
14808 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14809 {
14810 struct dahdi_pvt *p = NULL;
14811 int channo = 0;
14812 switch (cmd) {
14813 case CLI_INIT:
14814 e->command = "mfcr2 set idle";
14815 e->usage =
14816 "Usage: mfcr2 set idle <channel>\n"
14817 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14818 " Force the given channel into IDLE state.\n"
14819 " If no channel is specified, all channels will be set to IDLE.\n";
14820 return NULL;
14821 case CLI_GENERATE:
14822 return NULL;
14823 }
14824 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14825 ast_mutex_lock(&iflock);
14826 for (p = iflist; p; p = p->next) {
14827 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14828 continue;
14829 }
14830 if ((channo != -1) && (p->channel != channo )) {
14831 continue;
14832 }
14833 openr2_chan_set_idle(p->r2chan);
14834 ast_mutex_lock(&p->lock);
14835 p->locallyblocked = 0;
14836 p->mfcr2call = 0;
14837 ast_mutex_unlock(&p->lock);
14838 if (channo != -1) {
14839 break;
14840 }
14841 }
14842 if ((channo != -1) && !p) {
14843 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14844 }
14845 ast_mutex_unlock(&iflock);
14846 return CLI_SUCCESS;
14847 }
14848
14849 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14850 {
14851 struct dahdi_pvt *p = NULL;
14852 int channo = 0;
14853 switch (cmd) {
14854 case CLI_INIT:
14855 e->command = "mfcr2 set blocked";
14856 e->usage =
14857 "Usage: mfcr2 set blocked <channel>\n"
14858 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14859 " Force the given channel into BLOCKED state.\n"
14860 " If no channel is specified, all channels will be set to BLOCKED.\n";
14861 return NULL;
14862 case CLI_GENERATE:
14863 return NULL;
14864 }
14865 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14866 ast_mutex_lock(&iflock);
14867 for (p = iflist; p; p = p->next) {
14868 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14869 continue;
14870 }
14871 if ((channo != -1) && (p->channel != channo )) {
14872 continue;
14873 }
14874 openr2_chan_set_blocked(p->r2chan);
14875 ast_mutex_lock(&p->lock);
14876 p->locallyblocked = 1;
14877 ast_mutex_unlock(&p->lock);
14878 if (channo != -1) {
14879 break;
14880 }
14881 }
14882 if ((channo != -1) && !p) {
14883 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14884 }
14885 ast_mutex_unlock(&iflock);
14886 return CLI_SUCCESS;
14887 }
14888
14889 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14890 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14891 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14892 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14893 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14894 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14895 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14896 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14897 };
14898
14899 #endif
14900
14901 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14902 {
14903 int channel;
14904 int ret;
14905 switch (cmd) {
14906 case CLI_INIT:
14907 e->command = "dahdi destroy channel";
14908 e->usage =
14909 "Usage: dahdi destroy channel <chan num>\n"
14910 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14911 return NULL;
14912 case CLI_GENERATE:
14913 return NULL;
14914 }
14915 if (a->argc != 4)
14916 return CLI_SHOWUSAGE;
14917
14918 channel = atoi(a->argv[3]);
14919 ret = dahdi_destroy_channel_bynum(channel);
14920 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14921 }
14922
14923 static void dahdi_softhangup_all(void)
14924 {
14925 struct dahdi_pvt *p;
14926 retry:
14927 ast_mutex_lock(&iflock);
14928 for (p = iflist; p; p = p->next) {
14929 ast_mutex_lock(&p->lock);
14930 if (p->owner && !p->restartpending) {
14931 if (ast_channel_trylock(p->owner)) {
14932 if (option_debug > 2)
14933 ast_verbose("Avoiding deadlock\n");
14934
14935 ast_mutex_unlock(&p->lock);
14936 ast_mutex_unlock(&iflock);
14937 goto retry;
14938 }
14939 if (option_debug > 2)
14940 ast_verbose("Softhanging up on %s\n", p->owner->name);
14941 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14942 p->restartpending = 1;
14943 num_restart_pending++;
14944 ast_channel_unlock(p->owner);
14945 }
14946 ast_mutex_unlock(&p->lock);
14947 }
14948 ast_mutex_unlock(&iflock);
14949 }
14950
14951 static int setup_dahdi(int reload);
14952 static int dahdi_restart(void)
14953 {
14954 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14955 int i, j;
14956 #endif
14957 int cancel_code;
14958 struct dahdi_pvt *p;
14959
14960 ast_mutex_lock(&restart_lock);
14961 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14962 dahdi_softhangup_all();
14963 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14964 #ifdef HAVE_OPENR2
14965 dahdi_r2_destroy_links();
14966 #endif
14967
14968 #if defined(HAVE_PRI)
14969 for (i = 0; i < NUM_SPANS; i++) {
14970 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14971 cancel_code = pthread_cancel(pris[i].pri.master);
14972 pthread_kill(pris[i].pri.master, SIGURG);
14973 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);
14974 pthread_join(pris[i].pri.master, NULL);
14975 ast_debug(4, "Joined thread of span %d\n", i);
14976 }
14977 }
14978 #endif
14979
14980 #if defined(HAVE_SS7)
14981 for (i = 0; i < NUM_SPANS; i++) {
14982 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14983 cancel_code = pthread_cancel(linksets[i].ss7.master);
14984 pthread_kill(linksets[i].ss7.master, SIGURG);
14985 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);
14986 pthread_join(linksets[i].ss7.master, NULL);
14987 ast_debug(4, "Joined thread of span %d\n", i);
14988 }
14989 }
14990 #endif
14991
14992 ast_mutex_lock(&monlock);
14993 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14994 cancel_code = pthread_cancel(monitor_thread);
14995 pthread_kill(monitor_thread, SIGURG);
14996 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14997 pthread_join(monitor_thread, NULL);
14998 ast_debug(4, "Joined monitor thread\n");
14999 }
15000 monitor_thread = AST_PTHREADT_NULL;
15001
15002 ast_mutex_lock(&ss_thread_lock);
15003 while (ss_thread_count > 0) {
15004 int x = DAHDI_FLASH;
15005 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15006
15007 ast_mutex_lock(&iflock);
15008 for (p = iflist; p; p = p->next) {
15009 if (p->owner) {
15010
15011 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15012 }
15013 }
15014 ast_mutex_unlock(&iflock);
15015 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15016 }
15017
15018
15019 dahdi_softhangup_all();
15020 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15021 destroy_all_channels();
15022 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15023
15024 ast_mutex_unlock(&monlock);
15025
15026 #ifdef HAVE_PRI
15027 for (i = 0; i < NUM_SPANS; i++) {
15028 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15029 dahdi_close_pri_fd(&(pris[i]), j);
15030 }
15031
15032 memset(pris, 0, sizeof(pris));
15033 for (i = 0; i < NUM_SPANS; i++) {
15034 sig_pri_init_pri(&pris[i].pri);
15035 }
15036 pri_set_error(dahdi_pri_error);
15037 pri_set_message(dahdi_pri_message);
15038 #endif
15039 #if defined(HAVE_SS7)
15040 for (i = 0; i < NUM_SPANS; i++) {
15041 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15042 dahdi_close_ss7_fd(&(linksets[i]), j);
15043 }
15044
15045 memset(linksets, 0, sizeof(linksets));
15046 for (i = 0; i < NUM_SPANS; i++) {
15047 sig_ss7_init_linkset(&linksets[i].ss7);
15048 }
15049 ss7_set_error(dahdi_ss7_error);
15050 ss7_set_message(dahdi_ss7_message);
15051 #endif
15052
15053 if (setup_dahdi(2) != 0) {
15054 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15055 ast_mutex_unlock(&ss_thread_lock);
15056 return 1;
15057 }
15058 ast_mutex_unlock(&ss_thread_lock);
15059 ast_mutex_unlock(&restart_lock);
15060 return 0;
15061 }
15062
15063 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15064 {
15065 switch (cmd) {
15066 case CLI_INIT:
15067 e->command = "dahdi restart";
15068 e->usage =
15069 "Usage: dahdi restart\n"
15070 " Restarts the DAHDI channels: destroys them all and then\n"
15071 " re-reads them from chan_dahdi.conf.\n"
15072 " Note that this will STOP any running CALL on DAHDI channels.\n"
15073 "";
15074 return NULL;
15075 case CLI_GENERATE:
15076 return NULL;
15077 }
15078 if (a->argc != 2)
15079 return CLI_SHOWUSAGE;
15080
15081 if (dahdi_restart() != 0)
15082 return CLI_FAILURE;
15083 return CLI_SUCCESS;
15084 }
15085
15086 static int action_dahdirestart(struct mansession *s, const struct message *m)
15087 {
15088 if (dahdi_restart() != 0) {
15089 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15090 return 1;
15091 }
15092 astman_send_ack(s, m, "DAHDIRestart: Success");
15093 return 0;
15094 }
15095
15096 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15097 {
15098 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15099 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15100 unsigned int targetnum = 0;
15101 int filtertype = 0;
15102 struct dahdi_pvt *tmp = NULL;
15103 char tmps[20] = "";
15104 char statestr[20] = "";
15105 char blockstr[20] = "";
15106
15107 switch (cmd) {
15108 case CLI_INIT:
15109 e->command = "dahdi show channels [group|context]";
15110 e->usage =
15111 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15112 " Shows a list of available channels with optional filtering\n"
15113 " <group> must be a number between 0 and 63\n";
15114 return NULL;
15115 case CLI_GENERATE:
15116 return NULL;
15117 }
15118
15119
15120
15121 if (!((a->argc == 3) || (a->argc == 5)))
15122 return CLI_SHOWUSAGE;
15123
15124 if (a->argc == 5) {
15125 if (!strcasecmp(a->argv[3], "group")) {
15126 targetnum = atoi(a->argv[4]);
15127 if ((targetnum < 0) || (targetnum > 63))
15128 return CLI_SHOWUSAGE;
15129 targetnum = 1 << targetnum;
15130 filtertype = 1;
15131 } else if (!strcasecmp(a->argv[3], "context")) {
15132 filtertype = 2;
15133 }
15134 }
15135
15136 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15137 ast_mutex_lock(&iflock);
15138 for (tmp = iflist; tmp; tmp = tmp->next) {
15139 if (filtertype) {
15140 switch(filtertype) {
15141 case 1:
15142 if (!(tmp->group & targetnum)) {
15143 continue;
15144 }
15145 break;
15146 case 2:
15147 if (strcasecmp(tmp->context, a->argv[4])) {
15148 continue;
15149 }
15150 break;
15151 default:
15152 break;
15153 }
15154 }
15155 if (tmp->channel > 0) {
15156 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15157 } else
15158 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15159
15160 if (tmp->locallyblocked)
15161 blockstr[0] = 'L';
15162 else
15163 blockstr[0] = ' ';
15164
15165 if (tmp->remotelyblocked)
15166 blockstr[1] = 'R';
15167 else
15168 blockstr[1] = ' ';
15169
15170 blockstr[2] = '\0';
15171
15172 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15173
15174 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15175 }
15176 ast_mutex_unlock(&iflock);
15177 return CLI_SUCCESS;
15178 #undef FORMAT
15179 #undef FORMAT2
15180 }
15181
15182 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15183 {
15184 int channel;
15185 struct dahdi_pvt *tmp = NULL;
15186 struct dahdi_confinfo ci;
15187 struct dahdi_params ps;
15188 int x;
15189
15190 switch (cmd) {
15191 case CLI_INIT:
15192 e->command = "dahdi show channel";
15193 e->usage =
15194 "Usage: dahdi show channel <chan num>\n"
15195 " Detailed information about a given channel\n";
15196 return NULL;
15197 case CLI_GENERATE:
15198 return NULL;
15199 }
15200
15201 if (a->argc != 4)
15202 return CLI_SHOWUSAGE;
15203
15204 channel = atoi(a->argv[3]);
15205
15206 ast_mutex_lock(&iflock);
15207 for (tmp = iflist; tmp; tmp = tmp->next) {
15208 if (tmp->channel == channel) {
15209 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15210 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15211 ast_cli(a->fd, "Span: %d\n", tmp->span);
15212 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15213 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15214 ast_cli(a->fd, "Context: %s\n", tmp->context);
15215 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15216 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15217 #if defined(HAVE_PRI)
15218 #if defined(HAVE_PRI_SUBADDR)
15219 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15220 #endif
15221 #endif
15222 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15223 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15224 if (tmp->vars) {
15225 struct ast_variable *v;
15226 ast_cli(a->fd, "Variables:\n");
15227 for (v = tmp->vars ; v ; v = v->next)
15228 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15229 }
15230 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15231 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15232 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15233 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15234 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15235 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)" : "");
15236 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)" : "");
15237 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)" : "");
15238 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15239 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15240 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15241 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15242 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15243 if (tmp->busydetect) {
15244 #if defined(BUSYDETECT_TONEONLY)
15245 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15246 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15247 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15248 #endif
15249 #ifdef BUSYDETECT_DEBUG
15250 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15251 #endif
15252 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15253 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15254 }
15255 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15256 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15257 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15258 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15259 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15260 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15261 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15262 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15263 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15264 ast_cli(a->fd, "Echo Cancellation:\n");
15265
15266 if (tmp->echocancel.head.tap_length) {
15267 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15268 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15269 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15270 }
15271 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15272 } else {
15273 ast_cli(a->fd, "\tnone\n");
15274 }
15275 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15276 if (tmp->master)
15277 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15278 for (x = 0; x < MAX_SLAVES; x++) {
15279 if (tmp->slaves[x])
15280 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15281 }
15282 #ifdef HAVE_OPENR2
15283 if (tmp->mfcr2) {
15284 char calldir[OR2_MAX_PATH];
15285 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15286 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15287 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15288 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15289 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15290 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15291 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15292 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15293 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15294 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15295 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15296 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15297 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15298 #endif
15299 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15300 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15301 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15302 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15303 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15304 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15305 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15306 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15307 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15308 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15309 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15310 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15311 }
15312 #endif
15313 #if defined(HAVE_SS7)
15314 if (tmp->ss7) {
15315 struct sig_ss7_chan *chan = tmp->sig_pvt;
15316
15317 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15318 }
15319 #endif
15320 #ifdef HAVE_PRI
15321 if (tmp->pri) {
15322 struct sig_pri_chan *chan = tmp->sig_pvt;
15323
15324 ast_cli(a->fd, "PRI Flags: ");
15325 if (chan->resetting)
15326 ast_cli(a->fd, "Resetting ");
15327 if (chan->call)
15328 ast_cli(a->fd, "Call ");
15329 if (chan->allocated) {
15330 ast_cli(a->fd, "Allocated ");
15331 }
15332 ast_cli(a->fd, "\n");
15333 if (tmp->logicalspan)
15334 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15335 else
15336 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15337 }
15338 #endif
15339 memset(&ci, 0, sizeof(ci));
15340 ps.channo = tmp->channel;
15341 if (tmp->subs[SUB_REAL].dfd > -1) {
15342 memset(&ci, 0, sizeof(ci));
15343 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15344 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15345 }
15346 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15347 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15348 }
15349 memset(&ps, 0, sizeof(ps));
15350 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15351 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15352 } else {
15353 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15354 }
15355 }
15356 if (ISTRUNK(tmp)) {
15357 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
15358 if (!ast_strlen_zero(progzone))
15359 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15360 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
15361 if(tmp->busydetect) {
15362 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15363 if(tmp->busytonelength > 0) {
15364 ast_cli(a->fd, "Busy Pattern:\n");
15365 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15366 if (tmp->busyquietlength > 0)
15367 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15368 else
15369 ast_cli(a->fd, " -- Detect Tone Only\n");
15370 if(tmp->busyfuzziness > 0)
15371 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15372 }
15373 }
15374 }
15375 ast_mutex_unlock(&iflock);
15376 return CLI_SUCCESS;
15377 }
15378 }
15379 ast_mutex_unlock(&iflock);
15380
15381 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15382 return CLI_FAILURE;
15383 }
15384
15385 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15386 {
15387 int i, j;
15388 switch (cmd) {
15389 case CLI_INIT:
15390 e->command = "dahdi show cadences";
15391 e->usage =
15392 "Usage: dahdi show cadences\n"
15393 " Shows all cadences currently defined\n";
15394 return NULL;
15395 case CLI_GENERATE:
15396 return NULL;
15397 }
15398 for (i = 0; i < num_cadence; i++) {
15399 char output[1024];
15400 char tmp[16], tmp2[64];
15401 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15402 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15403
15404 for (j = 0; j < 16; j++) {
15405 if (cadences[i].ringcadence[j] == 0)
15406 break;
15407 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15408 if (cidrings[i] * 2 - 1 == j)
15409 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15410 else
15411 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15412 if (j != 0)
15413 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15414 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15415 }
15416 ast_cli(a->fd,"%s\n",output);
15417 }
15418 return CLI_SUCCESS;
15419 }
15420
15421
15422 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15423 {
15424 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15425 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15426 int span;
15427 int res;
15428 char alarmstr[50];
15429
15430 int ctl;
15431 struct dahdi_spaninfo s;
15432
15433 switch (cmd) {
15434 case CLI_INIT:
15435 e->command = "dahdi show status";
15436 e->usage =
15437 "Usage: dahdi show status\n"
15438 " Shows a list of DAHDI cards with status\n";
15439 return NULL;
15440 case CLI_GENERATE:
15441 return NULL;
15442 }
15443 ctl = open("/dev/dahdi/ctl", O_RDWR);
15444 if (ctl < 0) {
15445 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15446 return CLI_FAILURE;
15447 }
15448 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15449
15450 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15451 s.spanno = span;
15452 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15453 if (res) {
15454 continue;
15455 }
15456 alarmstr[0] = '\0';
15457 if (s.alarms > 0) {
15458 if (s.alarms & DAHDI_ALARM_BLUE)
15459 strcat(alarmstr, "BLU/");
15460 if (s.alarms & DAHDI_ALARM_YELLOW)
15461 strcat(alarmstr, "YEL/");
15462 if (s.alarms & DAHDI_ALARM_RED)
15463 strcat(alarmstr, "RED/");
15464 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15465 strcat(alarmstr, "LB/");
15466 if (s.alarms & DAHDI_ALARM_RECOVER)
15467 strcat(alarmstr, "REC/");
15468 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15469 strcat(alarmstr, "NOP/");
15470 if (!strlen(alarmstr))
15471 strcat(alarmstr, "UUU/");
15472 if (strlen(alarmstr)) {
15473
15474 alarmstr[strlen(alarmstr) - 1] = '\0';
15475 }
15476 } else {
15477 if (s.numchans)
15478 strcpy(alarmstr, "OK");
15479 else
15480 strcpy(alarmstr, "UNCONFIGURED");
15481 }
15482
15483 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15484 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15485 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15486 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15487 "CAS",
15488 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15489 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15490 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15491 "Unk",
15492 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15493 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15494 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15495 lbostr[s.lbo]
15496 );
15497 }
15498 close(ctl);
15499
15500 return CLI_SUCCESS;
15501 #undef FORMAT
15502 #undef FORMAT2
15503 }
15504
15505 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15506 {
15507 int pseudo_fd = -1;
15508 struct dahdi_versioninfo vi;
15509
15510 switch (cmd) {
15511 case CLI_INIT:
15512 e->command = "dahdi show version";
15513 e->usage =
15514 "Usage: dahdi show version\n"
15515 " Shows the DAHDI version in use\n";
15516 return NULL;
15517 case CLI_GENERATE:
15518 return NULL;
15519 }
15520 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15521 ast_cli(a->fd, "Failed to open control file to get version.\n");
15522 return CLI_SUCCESS;
15523 }
15524
15525 strcpy(vi.version, "Unknown");
15526 strcpy(vi.echo_canceller, "Unknown");
15527
15528 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15529 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15530 else
15531 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15532
15533 close(pseudo_fd);
15534
15535 return CLI_SUCCESS;
15536 }
15537
15538 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15539 {
15540 int channel;
15541 int gain;
15542 int tx;
15543 struct dahdi_hwgain hwgain;
15544 struct dahdi_pvt *tmp = NULL;
15545
15546 switch (cmd) {
15547 case CLI_INIT:
15548 e->command = "dahdi set hwgain";
15549 e->usage =
15550 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15551 " Sets the hardware gain on a a given channel, overriding the\n"
15552 " value provided at module loadtime, whether the channel is in\n"
15553 " use or not. Changes take effect immediately.\n"
15554 " <rx|tx> which direction do you want to change (relative to our module)\n"
15555 " <chan num> is the channel number relative to the device\n"
15556 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15557 return NULL;
15558 case CLI_GENERATE:
15559 return NULL;
15560 }
15561
15562 if (a->argc != 6)
15563 return CLI_SHOWUSAGE;
15564
15565 if (!strcasecmp("rx", a->argv[3]))
15566 tx = 0;
15567 else if (!strcasecmp("tx", a->argv[3]))
15568 tx = 1;
15569 else
15570 return CLI_SHOWUSAGE;
15571
15572 channel = atoi(a->argv[4]);
15573 gain = atof(a->argv[5])*10.0;
15574
15575 ast_mutex_lock(&iflock);
15576
15577 for (tmp = iflist; tmp; tmp = tmp->next) {
15578
15579 if (tmp->channel != channel)
15580 continue;
15581
15582 if (tmp->subs[SUB_REAL].dfd == -1)
15583 break;
15584
15585 hwgain.newgain = gain;
15586 hwgain.tx = tx;
15587 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15588 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15589 ast_mutex_unlock(&iflock);
15590 return CLI_FAILURE;
15591 }
15592 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15593 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15594 break;
15595 }
15596
15597 ast_mutex_unlock(&iflock);
15598
15599 if (tmp)
15600 return CLI_SUCCESS;
15601
15602 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15603 return CLI_FAILURE;
15604
15605 }
15606
15607 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15608 {
15609 int channel;
15610 float gain;
15611 int tx;
15612 int res;
15613 struct dahdi_pvt *tmp = NULL;
15614
15615 switch (cmd) {
15616 case CLI_INIT:
15617 e->command = "dahdi set swgain";
15618 e->usage =
15619 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15620 " Sets the software gain on a a given channel, overriding the\n"
15621 " value provided at module loadtime, whether the channel is in\n"
15622 " use or not. Changes take effect immediately.\n"
15623 " <rx|tx> which direction do you want to change (relative to our module)\n"
15624 " <chan num> is the channel number relative to the device\n"
15625 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15626 return NULL;
15627 case CLI_GENERATE:
15628 return NULL;
15629 }
15630
15631 if (a->argc != 6)
15632 return CLI_SHOWUSAGE;
15633
15634 if (!strcasecmp("rx", a->argv[3]))
15635 tx = 0;
15636 else if (!strcasecmp("tx", a->argv[3]))
15637 tx = 1;
15638 else
15639 return CLI_SHOWUSAGE;
15640
15641 channel = atoi(a->argv[4]);
15642 gain = atof(a->argv[5]);
15643
15644 ast_mutex_lock(&iflock);
15645 for (tmp = iflist; tmp; tmp = tmp->next) {
15646
15647 if (tmp->channel != channel)
15648 continue;
15649
15650 if (tmp->subs[SUB_REAL].dfd == -1)
15651 break;
15652
15653 if (tx)
15654 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15655 else
15656 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15657
15658 if (res) {
15659 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15660 ast_mutex_unlock(&iflock);
15661 return CLI_FAILURE;
15662 }
15663
15664 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15665 tx ? "tx" : "rx", gain, channel);
15666 break;
15667 }
15668 ast_mutex_unlock(&iflock);
15669
15670 if (tmp)
15671 return CLI_SUCCESS;
15672
15673 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15674 return CLI_FAILURE;
15675
15676 }
15677
15678 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15679 {
15680 int channel;
15681 int on;
15682 struct dahdi_pvt *dahdi_chan = NULL;
15683
15684 switch (cmd) {
15685 case CLI_INIT:
15686 e->command = "dahdi set dnd";
15687 e->usage =
15688 "Usage: dahdi set dnd <chan#> <on|off>\n"
15689 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15690 " Changes take effect immediately.\n"
15691 " <chan num> is the channel number\n"
15692 " <on|off> Enable or disable DND mode?\n"
15693 ;
15694 return NULL;
15695 case CLI_GENERATE:
15696 return NULL;
15697 }
15698
15699 if (a->argc != 5)
15700 return CLI_SHOWUSAGE;
15701
15702 if ((channel = atoi(a->argv[3])) <= 0) {
15703 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15704 return CLI_SHOWUSAGE;
15705 }
15706
15707 if (ast_true(a->argv[4]))
15708 on = 1;
15709 else if (ast_false(a->argv[4]))
15710 on = 0;
15711 else {
15712 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15713 return CLI_SHOWUSAGE;
15714 }
15715
15716 ast_mutex_lock(&iflock);
15717 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15718 if (dahdi_chan->channel != channel)
15719 continue;
15720
15721
15722 dahdi_dnd(dahdi_chan, on);
15723 break;
15724 }
15725 ast_mutex_unlock(&iflock);
15726
15727 if (!dahdi_chan) {
15728 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15729 return CLI_FAILURE;
15730 }
15731
15732 return CLI_SUCCESS;
15733 }
15734
15735 static struct ast_cli_entry dahdi_cli[] = {
15736 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15737 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15738 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15739 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15740 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15741 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15742 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15743 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15744 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15745 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15746 };
15747
15748 #define TRANSFER 0
15749 #define HANGUP 1
15750
15751 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15752 {
15753 if (p) {
15754 switch (mode) {
15755 case TRANSFER:
15756 p->fake_event = DAHDI_EVENT_WINKFLASH;
15757 break;
15758 case HANGUP:
15759 p->fake_event = DAHDI_EVENT_ONHOOK;
15760 break;
15761 default:
15762 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15763 }
15764 }
15765 return 0;
15766 }
15767 static struct dahdi_pvt *find_channel(int channel)
15768 {
15769 struct dahdi_pvt *p;
15770
15771 ast_mutex_lock(&iflock);
15772 for (p = iflist; p; p = p->next) {
15773 if (p->channel == channel) {
15774 break;
15775 }
15776 }
15777 ast_mutex_unlock(&iflock);
15778 return p;
15779 }
15780
15781
15782
15783
15784
15785
15786
15787
15788
15789
15790 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15791 {
15792 int chan_num;
15793
15794 if (sscanf(channel, "%30d", &chan_num) != 1) {
15795
15796 return NULL;
15797 }
15798
15799 return find_channel(chan_num);
15800 }
15801
15802 static int action_dahdidndon(struct mansession *s, const struct message *m)
15803 {
15804 struct dahdi_pvt *p;
15805 const char *channel = astman_get_header(m, "DAHDIChannel");
15806
15807 if (ast_strlen_zero(channel)) {
15808 astman_send_error(s, m, "No channel specified");
15809 return 0;
15810 }
15811 p = find_channel_from_str(channel);
15812 if (!p) {
15813 astman_send_error(s, m, "No such channel");
15814 return 0;
15815 }
15816 dahdi_dnd(p, 1);
15817 astman_send_ack(s, m, "DND Enabled");
15818 return 0;
15819 }
15820
15821 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15822 {
15823 struct dahdi_pvt *p;
15824 const char *channel = astman_get_header(m, "DAHDIChannel");
15825
15826 if (ast_strlen_zero(channel)) {
15827 astman_send_error(s, m, "No channel specified");
15828 return 0;
15829 }
15830 p = find_channel_from_str(channel);
15831 if (!p) {
15832 astman_send_error(s, m, "No such channel");
15833 return 0;
15834 }
15835 dahdi_dnd(p, 0);
15836 astman_send_ack(s, m, "DND Disabled");
15837 return 0;
15838 }
15839
15840 static int action_transfer(struct mansession *s, const struct message *m)
15841 {
15842 struct dahdi_pvt *p;
15843 const char *channel = astman_get_header(m, "DAHDIChannel");
15844
15845 if (ast_strlen_zero(channel)) {
15846 astman_send_error(s, m, "No channel specified");
15847 return 0;
15848 }
15849 p = find_channel_from_str(channel);
15850 if (!p) {
15851 astman_send_error(s, m, "No such channel");
15852 return 0;
15853 }
15854 if (!analog_lib_handles(p->sig, 0, 0)) {
15855 astman_send_error(s, m, "Channel signaling is not analog");
15856 return 0;
15857 }
15858 dahdi_fake_event(p,TRANSFER);
15859 astman_send_ack(s, m, "DAHDITransfer");
15860 return 0;
15861 }
15862
15863 static int action_transferhangup(struct mansession *s, const struct message *m)
15864 {
15865 struct dahdi_pvt *p;
15866 const char *channel = astman_get_header(m, "DAHDIChannel");
15867
15868 if (ast_strlen_zero(channel)) {
15869 astman_send_error(s, m, "No channel specified");
15870 return 0;
15871 }
15872 p = find_channel_from_str(channel);
15873 if (!p) {
15874 astman_send_error(s, m, "No such channel");
15875 return 0;
15876 }
15877 if (!analog_lib_handles(p->sig, 0, 0)) {
15878 astman_send_error(s, m, "Channel signaling is not analog");
15879 return 0;
15880 }
15881 dahdi_fake_event(p,HANGUP);
15882 astman_send_ack(s, m, "DAHDIHangup");
15883 return 0;
15884 }
15885
15886 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15887 {
15888 struct dahdi_pvt *p;
15889 const char *channel = astman_get_header(m, "DAHDIChannel");
15890 const char *number = astman_get_header(m, "Number");
15891 int i;
15892
15893 if (ast_strlen_zero(channel)) {
15894 astman_send_error(s, m, "No channel specified");
15895 return 0;
15896 }
15897 if (ast_strlen_zero(number)) {
15898 astman_send_error(s, m, "No number specified");
15899 return 0;
15900 }
15901 p = find_channel_from_str(channel);
15902 if (!p) {
15903 astman_send_error(s, m, "No such channel");
15904 return 0;
15905 }
15906 if (!p->owner) {
15907 astman_send_error(s, m, "Channel does not have it's owner");
15908 return 0;
15909 }
15910 for (i = 0; i < strlen(number); i++) {
15911 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15912 dahdi_queue_frame(p, &f);
15913 }
15914 astman_send_ack(s, m, "DAHDIDialOffhook");
15915 return 0;
15916 }
15917
15918 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15919 {
15920 struct dahdi_pvt *tmp = NULL;
15921 const char *id = astman_get_header(m, "ActionID");
15922 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15923 char idText[256] = "";
15924 int channels = 0;
15925 int dahdichanquery;
15926
15927 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15928
15929 dahdichanquery = -1;
15930 }
15931
15932 astman_send_ack(s, m, "DAHDI channel status will follow");
15933 if (!ast_strlen_zero(id))
15934 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15935
15936 ast_mutex_lock(&iflock);
15937
15938 for (tmp = iflist; tmp; tmp = tmp->next) {
15939 if (tmp->channel > 0) {
15940 int alm;
15941
15942
15943 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15944 continue;
15945
15946 alm = get_alarms(tmp);
15947 channels++;
15948 if (tmp->owner) {
15949
15950 astman_append(s,
15951 "Event: DAHDIShowChannels\r\n"
15952 "DAHDIChannel: %d\r\n"
15953 "Channel: %s\r\n"
15954 "Uniqueid: %s\r\n"
15955 "AccountCode: %s\r\n"
15956 "Signalling: %s\r\n"
15957 "SignallingCode: %d\r\n"
15958 "Context: %s\r\n"
15959 "DND: %s\r\n"
15960 "Alarm: %s\r\n"
15961 "%s"
15962 "\r\n",
15963 tmp->channel,
15964 tmp->owner->name,
15965 tmp->owner->uniqueid,
15966 tmp->owner->accountcode,
15967 sig2str(tmp->sig),
15968 tmp->sig,
15969 tmp->context,
15970 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15971 alarm2str(alm), idText);
15972 } else {
15973 astman_append(s,
15974 "Event: DAHDIShowChannels\r\n"
15975 "DAHDIChannel: %d\r\n"
15976 "Signalling: %s\r\n"
15977 "SignallingCode: %d\r\n"
15978 "Context: %s\r\n"
15979 "DND: %s\r\n"
15980 "Alarm: %s\r\n"
15981 "%s"
15982 "\r\n",
15983 tmp->channel, sig2str(tmp->sig), tmp->sig,
15984 tmp->context,
15985 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15986 alarm2str(alm), idText);
15987 }
15988 }
15989 }
15990
15991 ast_mutex_unlock(&iflock);
15992
15993 astman_append(s,
15994 "Event: DAHDIShowChannelsComplete\r\n"
15995 "%s"
15996 "Items: %d\r\n"
15997 "\r\n",
15998 idText,
15999 channels);
16000 return 0;
16001 }
16002
16003 #if defined(HAVE_SS7)
16004 static int linkset_addsigchan(int sigchan)
16005 {
16006 struct dahdi_ss7 *link;
16007 int res;
16008 int curfd;
16009 struct dahdi_params params;
16010 struct dahdi_bufferinfo bi;
16011 struct dahdi_spaninfo si;
16012
16013 if (sigchan < 0) {
16014 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16015 return -1;
16016 }
16017 if (cur_ss7type < 0) {
16018 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16019 return -1;
16020 }
16021 if (cur_pointcode < 0) {
16022 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16023 return -1;
16024 }
16025 if (cur_adjpointcode < 0) {
16026 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16027 return -1;
16028 }
16029 if (cur_defaultdpc < 0) {
16030 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16031 return -1;
16032 }
16033 if (cur_networkindicator < 0) {
16034 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16035 return -1;
16036 }
16037 link = ss7_resolve_linkset(cur_linkset);
16038 if (!link) {
16039 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16040 return -1;
16041 }
16042 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16043 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16044 return -1;
16045 }
16046
16047 curfd = link->ss7.numsigchans;
16048
16049
16050 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16051 if (link->ss7.fds[curfd] < 0) {
16052 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16053 strerror(errno));
16054 return -1;
16055 }
16056 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16057 dahdi_close_ss7_fd(link, curfd);
16058 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16059 strerror(errno));
16060 return -1;
16061 }
16062
16063
16064 memset(¶ms, 0, sizeof(params));
16065 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16066 if (res) {
16067 dahdi_close_ss7_fd(link, curfd);
16068 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16069 strerror(errno));
16070 return -1;
16071 }
16072 if (params.sigtype != DAHDI_SIG_HDLCFCS
16073 && params.sigtype != DAHDI_SIG_HARDHDLC
16074 && params.sigtype != DAHDI_SIG_MTP2) {
16075 dahdi_close_ss7_fd(link, curfd);
16076 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16077 return -1;
16078 }
16079
16080
16081 memset(&bi, 0, sizeof(bi));
16082 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16083 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16084 bi.numbufs = 32;
16085 bi.bufsize = 512;
16086 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16087 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16088 sigchan, strerror(errno));
16089 dahdi_close_ss7_fd(link, curfd);
16090 return -1;
16091 }
16092
16093
16094 memset(&si, 0, sizeof(si));
16095 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16096 if (res) {
16097 dahdi_close_ss7_fd(link, curfd);
16098 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16099 strerror(errno));
16100 }
16101
16102 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16103 (params.sigtype == DAHDI_SIG_MTP2)
16104 ? SS7_TRANSPORT_DAHDIMTP2
16105 : SS7_TRANSPORT_DAHDIDCHAN,
16106 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16107 if (res) {
16108 dahdi_close_ss7_fd(link, curfd);
16109 return -1;
16110 }
16111
16112 ++link->ss7.numsigchans;
16113
16114 return 0;
16115 }
16116 #endif
16117
16118 #if defined(HAVE_SS7)
16119 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16120 {
16121 int span;
16122 switch (cmd) {
16123 case CLI_INIT:
16124 e->command = "ss7 set debug {on|off} linkset";
16125 e->usage =
16126 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16127 " Enables debugging on a given SS7 linkset\n";
16128 return NULL;
16129 case CLI_GENERATE:
16130 return NULL;
16131 }
16132 if (a->argc < 6)
16133 return CLI_SHOWUSAGE;
16134 span = atoi(a->argv[5]);
16135 if ((span < 1) || (span > NUM_SPANS)) {
16136 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16137 return CLI_SUCCESS;
16138 }
16139 if (!linksets[span-1].ss7.ss7) {
16140 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16141 } else {
16142 if (!strcasecmp(a->argv[3], "on")) {
16143 linksets[span - 1].ss7.debug = 1;
16144 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16145 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16146 } else {
16147 linksets[span - 1].ss7.debug = 0;
16148 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16149 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16150 }
16151 }
16152
16153 return CLI_SUCCESS;
16154 }
16155 #endif
16156
16157 #if defined(HAVE_SS7)
16158 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16159 {
16160 int linkset, cic;
16161 int blocked = -1, i;
16162 switch (cmd) {
16163 case CLI_INIT:
16164 e->command = "ss7 block cic";
16165 e->usage =
16166 "Usage: ss7 block cic <linkset> <CIC>\n"
16167 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16168 return NULL;
16169 case CLI_GENERATE:
16170 return NULL;
16171 }
16172 if (a->argc == 5)
16173 linkset = atoi(a->argv[3]);
16174 else
16175 return CLI_SHOWUSAGE;
16176
16177 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16178 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16179 return CLI_SUCCESS;
16180 }
16181
16182 if (!linksets[linkset-1].ss7.ss7) {
16183 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16184 return CLI_SUCCESS;
16185 }
16186
16187 cic = atoi(a->argv[4]);
16188
16189 if (cic < 1) {
16190 ast_cli(a->fd, "Invalid CIC specified!\n");
16191 return CLI_SUCCESS;
16192 }
16193
16194 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16195 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16196 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16197 if (!blocked) {
16198 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16199 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16200 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16201 }
16202 }
16203 }
16204
16205 if (blocked < 0) {
16206 ast_cli(a->fd, "Invalid CIC specified!\n");
16207 return CLI_SUCCESS;
16208 }
16209
16210 if (!blocked)
16211 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16212 else
16213 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16214
16215
16216 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16217
16218 return CLI_SUCCESS;
16219 }
16220 #endif
16221
16222 #if defined(HAVE_SS7)
16223 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16224 {
16225 int linkset;
16226 int i;
16227 switch (cmd) {
16228 case CLI_INIT:
16229 e->command = "ss7 block linkset";
16230 e->usage =
16231 "Usage: ss7 block linkset <linkset number>\n"
16232 " Sends a remote blocking request for all CICs on the given linkset\n";
16233 return NULL;
16234 case CLI_GENERATE:
16235 return NULL;
16236 }
16237 if (a->argc == 4)
16238 linkset = atoi(a->argv[3]);
16239 else
16240 return CLI_SHOWUSAGE;
16241
16242 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16243 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16244 return CLI_SUCCESS;
16245 }
16246
16247 if (!linksets[linkset-1].ss7.ss7) {
16248 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16249 return CLI_SUCCESS;
16250 }
16251
16252 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16253 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16254 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16255 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16256 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16257 }
16258
16259
16260 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16261
16262 return CLI_SUCCESS;
16263 }
16264 #endif
16265
16266 #if defined(HAVE_SS7)
16267 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16268 {
16269 int linkset, cic;
16270 int i, blocked = -1;
16271 switch (cmd) {
16272 case CLI_INIT:
16273 e->command = "ss7 unblock cic";
16274 e->usage =
16275 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16276 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16277 return NULL;
16278 case CLI_GENERATE:
16279 return NULL;
16280 }
16281
16282 if (a->argc == 5)
16283 linkset = atoi(a->argv[3]);
16284 else
16285 return CLI_SHOWUSAGE;
16286
16287 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16288 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16289 return CLI_SUCCESS;
16290 }
16291
16292 if (!linksets[linkset-1].ss7.ss7) {
16293 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16294 return CLI_SUCCESS;
16295 }
16296
16297 cic = atoi(a->argv[4]);
16298
16299 if (cic < 1) {
16300 ast_cli(a->fd, "Invalid CIC specified!\n");
16301 return CLI_SUCCESS;
16302 }
16303
16304 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16305 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16306 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16307 if (blocked) {
16308 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16309 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16310 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16311 }
16312 }
16313 }
16314
16315 if (blocked > 0)
16316 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16317
16318
16319 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16320
16321 return CLI_SUCCESS;
16322 }
16323 #endif
16324
16325 #if defined(HAVE_SS7)
16326 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16327 {
16328 int linkset;
16329 int i;
16330 switch (cmd) {
16331 case CLI_INIT:
16332 e->command = "ss7 unblock linkset";
16333 e->usage =
16334 "Usage: ss7 unblock linkset <linkset number>\n"
16335 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16336 return NULL;
16337 case CLI_GENERATE:
16338 return NULL;
16339 }
16340
16341 if (a->argc == 4)
16342 linkset = atoi(a->argv[3]);
16343 else
16344 return CLI_SHOWUSAGE;
16345
16346 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16347 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16348 return CLI_SUCCESS;
16349 }
16350
16351 if (!linksets[linkset-1].ss7.ss7) {
16352 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16353 return CLI_SUCCESS;
16354 }
16355
16356 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16357 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16358 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16359 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16360 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16361 }
16362
16363
16364 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16365
16366 return CLI_SUCCESS;
16367 }
16368 #endif
16369
16370 #if defined(HAVE_SS7)
16371 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16372 {
16373 int linkset;
16374 struct sig_ss7_linkset *ss7;
16375 switch (cmd) {
16376 case CLI_INIT:
16377 e->command = "ss7 show linkset";
16378 e->usage =
16379 "Usage: ss7 show linkset <span>\n"
16380 " Shows the status of an SS7 linkset.\n";
16381 return NULL;
16382 case CLI_GENERATE:
16383 return NULL;
16384 }
16385
16386 if (a->argc < 4)
16387 return CLI_SHOWUSAGE;
16388 linkset = atoi(a->argv[3]);
16389 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16390 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16391 return CLI_SUCCESS;
16392 }
16393 ss7 = &linksets[linkset - 1].ss7;
16394 if (!ss7->ss7) {
16395 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16396 return CLI_SUCCESS;
16397 }
16398
16399 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16400
16401 return CLI_SUCCESS;
16402 }
16403 #endif
16404
16405 #if defined(HAVE_SS7)
16406 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16407 {
16408 int linkset;
16409
16410 switch (cmd) {
16411 case CLI_INIT:
16412 e->command = "ss7 show channels";
16413 e->usage =
16414 "Usage: ss7 show channels\n"
16415 " Displays SS7 channel information at a glance.\n";
16416 return NULL;
16417 case CLI_GENERATE:
16418 return NULL;
16419 }
16420
16421 if (a->argc != 3)
16422 return CLI_SHOWUSAGE;
16423
16424 sig_ss7_cli_show_channels_header(a->fd);
16425 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16426 if (linksets[linkset].ss7.ss7) {
16427 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16428 }
16429 }
16430 return CLI_SUCCESS;
16431 }
16432 #endif
16433
16434 #if defined(HAVE_SS7)
16435 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16436 {
16437 switch (cmd) {
16438 case CLI_INIT:
16439 e->command = "ss7 show version";
16440 e->usage =
16441 "Usage: ss7 show version\n"
16442 " Show the libss7 version\n";
16443 return NULL;
16444 case CLI_GENERATE:
16445 return NULL;
16446 }
16447
16448 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16449
16450 return CLI_SUCCESS;
16451 }
16452 #endif
16453
16454 #if defined(HAVE_SS7)
16455 static struct ast_cli_entry dahdi_ss7_cli[] = {
16456 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16457 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16458 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16459 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16460 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16461 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16462 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16463 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16464 };
16465 #endif
16466
16467 #if defined(HAVE_PRI)
16468 #if defined(HAVE_PRI_CCSS)
16469
16470
16471
16472
16473
16474
16475
16476
16477
16478
16479
16480
16481
16482
16483
16484
16485
16486 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16487 {
16488 struct dahdi_pvt *pvt;
16489 struct sig_pri_chan *pvt_chan;
16490 int res;
16491
16492 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16493
16494 pvt = chan->tech_pvt;
16495 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16496 pvt_chan = pvt->sig_pvt;
16497 } else {
16498 pvt_chan = NULL;
16499 }
16500 if (!pvt_chan) {
16501 return -1;
16502 }
16503
16504 ast_module_ref(ast_module_info->self);
16505
16506 res = sig_pri_cc_agent_init(agent, pvt_chan);
16507 if (res) {
16508 ast_module_unref(ast_module_info->self);
16509 }
16510 return res;
16511 }
16512 #endif
16513 #endif
16514
16515 #if defined(HAVE_PRI)
16516 #if defined(HAVE_PRI_CCSS)
16517
16518
16519
16520
16521
16522
16523
16524
16525
16526
16527
16528
16529
16530 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16531 {
16532 sig_pri_cc_agent_destructor(agent);
16533
16534 ast_module_unref(ast_module_info->self);
16535 }
16536 #endif
16537 #endif
16538
16539 #if defined(HAVE_PRI)
16540 #if defined(HAVE_PRI_CCSS)
16541 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16542 .type = dahdi_pri_cc_type,
16543 .init = dahdi_pri_cc_agent_init,
16544 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16545 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16546 .respond = sig_pri_cc_agent_req_rsp,
16547 .status_request = sig_pri_cc_agent_status_req,
16548 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16549 .party_b_free = sig_pri_cc_agent_party_b_free,
16550 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16551 .callee_available = sig_pri_cc_agent_callee_available,
16552 .destructor = dahdi_pri_cc_agent_destructor,
16553 };
16554 #endif
16555 #endif
16556
16557 #if defined(HAVE_PRI)
16558 #if defined(HAVE_PRI_CCSS)
16559 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16560 .type = dahdi_pri_cc_type,
16561 .request_cc = sig_pri_cc_monitor_req_cc,
16562 .suspend = sig_pri_cc_monitor_suspend,
16563 .unsuspend = sig_pri_cc_monitor_unsuspend,
16564 .status_response = sig_pri_cc_monitor_status_rsp,
16565 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16566 .destructor = sig_pri_cc_monitor_destructor,
16567 };
16568 #endif
16569 #endif
16570
16571 static int __unload_module(void)
16572 {
16573 struct dahdi_pvt *p;
16574 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16575 int i, j;
16576 #endif
16577
16578 #ifdef HAVE_PRI
16579 for (i = 0; i < NUM_SPANS; i++) {
16580 if (pris[i].pri.master != AST_PTHREADT_NULL)
16581 pthread_cancel(pris[i].pri.master);
16582 }
16583 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16584 ast_unregister_application(dahdi_send_keypad_facility_app);
16585 #ifdef HAVE_PRI_PROG_W_CAUSE
16586 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16587 #endif
16588 #endif
16589 #if defined(HAVE_SS7)
16590 for (i = 0; i < NUM_SPANS; i++) {
16591 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16592 pthread_cancel(linksets[i].ss7.master);
16593 }
16594 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16595 #endif
16596 #if defined(HAVE_OPENR2)
16597 dahdi_r2_destroy_links();
16598 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16599 ast_unregister_application(dahdi_accept_r2_call_app);
16600 #endif
16601
16602 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16603 ast_manager_unregister("DAHDIDialOffhook");
16604 ast_manager_unregister("DAHDIHangup");
16605 ast_manager_unregister("DAHDITransfer");
16606 ast_manager_unregister("DAHDIDNDoff");
16607 ast_manager_unregister("DAHDIDNDon");
16608 ast_manager_unregister("DAHDIShowChannels");
16609 ast_manager_unregister("DAHDIRestart");
16610 ast_data_unregister(NULL);
16611 ast_channel_unregister(&dahdi_tech);
16612
16613
16614 ast_mutex_lock(&iflock);
16615 for (p = iflist; p; p = p->next) {
16616 if (p->owner)
16617 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16618 }
16619 ast_mutex_unlock(&iflock);
16620
16621 ast_mutex_lock(&monlock);
16622 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16623 pthread_cancel(monitor_thread);
16624 pthread_kill(monitor_thread, SIGURG);
16625 pthread_join(monitor_thread, NULL);
16626 }
16627 monitor_thread = AST_PTHREADT_STOP;
16628 ast_mutex_unlock(&monlock);
16629
16630 destroy_all_channels();
16631
16632 #if defined(HAVE_PRI)
16633 for (i = 0; i < NUM_SPANS; i++) {
16634 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16635 pthread_join(pris[i].pri.master, NULL);
16636 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16637 dahdi_close_pri_fd(&(pris[i]), j);
16638 }
16639 sig_pri_stop_pri(&pris[i].pri);
16640 }
16641 #if defined(HAVE_PRI_CCSS)
16642 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16643 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16644 #endif
16645 sig_pri_unload();
16646 #endif
16647
16648 #if defined(HAVE_SS7)
16649 for (i = 0; i < NUM_SPANS; i++) {
16650 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16651 pthread_join(linksets[i].ss7.master, NULL);
16652 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16653 dahdi_close_ss7_fd(&(linksets[i]), j);
16654 }
16655 }
16656 #endif
16657 ast_cond_destroy(&ss_thread_complete);
16658 return 0;
16659 }
16660
16661 static int unload_module(void)
16662 {
16663 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16664 int y;
16665 #endif
16666 #ifdef HAVE_PRI
16667 for (y = 0; y < NUM_SPANS; y++)
16668 ast_mutex_destroy(&pris[y].pri.lock);
16669 #endif
16670 #if defined(HAVE_SS7)
16671 for (y = 0; y < NUM_SPANS; y++)
16672 ast_mutex_destroy(&linksets[y].ss7.lock);
16673 #endif
16674 return __unload_module();
16675 }
16676
16677 static void string_replace(char *str, int char1, int char2)
16678 {
16679 for (; *str; str++) {
16680 if (*str == char1) {
16681 *str = char2;
16682 }
16683 }
16684 }
16685
16686 static char *parse_spanchan(char *chanstr, char **subdir)
16687 {
16688 char *p;
16689
16690 if ((p = strrchr(chanstr, '!')) == NULL) {
16691 *subdir = NULL;
16692 return chanstr;
16693 }
16694 *p++ = '\0';
16695 string_replace(chanstr, '!', '/');
16696 *subdir = chanstr;
16697 return p;
16698 }
16699
16700 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16701 {
16702 char *c, *chan;
16703 char *subdir;
16704 int x, start, finish;
16705 struct dahdi_pvt *tmp;
16706
16707 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16708 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16709 return -1;
16710 }
16711
16712 c = ast_strdupa(value);
16713 c = parse_spanchan(c, &subdir);
16714
16715 while ((chan = strsep(&c, ","))) {
16716 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16717
16718 } else if (sscanf(chan, "%30d", &start)) {
16719
16720 finish = start;
16721 } else if (!strcasecmp(chan, "pseudo")) {
16722 finish = start = CHAN_PSEUDO;
16723 if (found_pseudo)
16724 *found_pseudo = 1;
16725 } else {
16726 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16727 return -1;
16728 }
16729 if (finish < start) {
16730 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16731 x = finish;
16732 finish = start;
16733 start = x;
16734 }
16735
16736 for (x = start; x <= finish; x++) {
16737 char fn[PATH_MAX];
16738 int real_channel = x;
16739
16740 if (!ast_strlen_zero(subdir)) {
16741 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16742 if (real_channel < 0) {
16743 if (conf->ignore_failed_channels) {
16744 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16745 subdir, x, real_channel);
16746 continue;
16747 } else {
16748 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16749 subdir, x, real_channel);
16750 return -1;
16751 }
16752 }
16753 }
16754 tmp = mkintf(real_channel, conf, reload);
16755
16756 if (tmp) {
16757 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16758 } else {
16759 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16760 (reload == 1) ? "reconfigure" : "register", value);
16761 return -1;
16762 }
16763 }
16764 }
16765
16766 return 0;
16767 }
16768
16769
16770
16771 #define MAX_CHANLIST_LEN 80
16772
16773 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16774 {
16775 char *parse = ast_strdupa(data);
16776 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16777 unsigned int param_count;
16778 unsigned int x;
16779
16780 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16781 return;
16782
16783 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16784
16785
16786
16787 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16788
16789 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16790 confp->chan.echocancel.head.tap_length = x;
16791 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16792 confp->chan.echocancel.head.tap_length = 128;
16793
16794
16795
16796 for (x = 1; x < param_count; x++) {
16797 struct {
16798 char *name;
16799 char *value;
16800 } param;
16801
16802 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16803 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16804 continue;
16805 }
16806
16807 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16808 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16809 continue;
16810 }
16811
16812 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16813
16814 if (param.value) {
16815 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16816 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16817 continue;
16818 }
16819 }
16820 confp->chan.echocancel.head.param_count++;
16821 }
16822 }
16823
16824
16825 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16826
16827 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16828
16829 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16830 {
16831 struct dahdi_pvt *tmp;
16832 int y;
16833 int found_pseudo = 0;
16834 struct ast_variable *dahdichan = NULL;
16835
16836 for (; v; v = v->next) {
16837 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16838 continue;
16839
16840
16841 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16842 if (options & PROC_DAHDI_OPT_NOCHAN) {
16843 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16844 continue;
16845 }
16846 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16847 if (confp->ignore_failed_channels) {
16848 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16849 continue;
16850 } else {
16851 return -1;
16852 }
16853 }
16854 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16855 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16856 confp->ignore_failed_channels = ast_true(v->value);
16857 } else if (!strcasecmp(v->name, "buffers")) {
16858 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16859 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16860 confp->chan.buf_no = numbufs;
16861 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16862 }
16863 } else if (!strcasecmp(v->name, "faxbuffers")) {
16864 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16865 confp->chan.usefaxbuffers = 1;
16866 }
16867 } else if (!strcasecmp(v->name, "dahdichan")) {
16868
16869 dahdichan = v;
16870 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16871 usedistinctiveringdetection = ast_true(v->value);
16872 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16873 distinctiveringaftercid = ast_true(v->value);
16874 } else if (!strcasecmp(v->name, "dring1context")) {
16875 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16876 } else if (!strcasecmp(v->name, "dring2context")) {
16877 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16878 } else if (!strcasecmp(v->name, "dring3context")) {
16879 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16880 } else if (!strcasecmp(v->name, "dring1range")) {
16881 confp->chan.drings.ringnum[0].range = atoi(v->value);
16882 } else if (!strcasecmp(v->name, "dring2range")) {
16883 confp->chan.drings.ringnum[1].range = atoi(v->value);
16884 } else if (!strcasecmp(v->name, "dring3range")) {
16885 confp->chan.drings.ringnum[2].range = atoi(v->value);
16886 } else if (!strcasecmp(v->name, "dring1")) {
16887 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]);
16888 } else if (!strcasecmp(v->name, "dring2")) {
16889 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]);
16890 } else if (!strcasecmp(v->name, "dring3")) {
16891 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]);
16892 } else if (!strcasecmp(v->name, "usecallerid")) {
16893 confp->chan.use_callerid = ast_true(v->value);
16894 } else if (!strcasecmp(v->name, "cidsignalling")) {
16895 if (!strcasecmp(v->value, "bell"))
16896 confp->chan.cid_signalling = CID_SIG_BELL;
16897 else if (!strcasecmp(v->value, "v23"))
16898 confp->chan.cid_signalling = CID_SIG_V23;
16899 else if (!strcasecmp(v->value, "dtmf"))
16900 confp->chan.cid_signalling = CID_SIG_DTMF;
16901 else if (!strcasecmp(v->value, "smdi"))
16902 confp->chan.cid_signalling = CID_SIG_SMDI;
16903 else if (!strcasecmp(v->value, "v23_jp"))
16904 confp->chan.cid_signalling = CID_SIG_V23_JP;
16905 else if (ast_true(v->value))
16906 confp->chan.cid_signalling = CID_SIG_BELL;
16907 } else if (!strcasecmp(v->name, "cidstart")) {
16908 if (!strcasecmp(v->value, "ring"))
16909 confp->chan.cid_start = CID_START_RING;
16910 else if (!strcasecmp(v->value, "polarity_in"))
16911 confp->chan.cid_start = CID_START_POLARITY_IN;
16912 else if (!strcasecmp(v->value, "polarity"))
16913 confp->chan.cid_start = CID_START_POLARITY;
16914 else if (!strcasecmp(v->value, "dtmf"))
16915 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16916 else if (ast_true(v->value))
16917 confp->chan.cid_start = CID_START_RING;
16918 } else if (!strcasecmp(v->name, "threewaycalling")) {
16919 confp->chan.threewaycalling = ast_true(v->value);
16920 } else if (!strcasecmp(v->name, "cancallforward")) {
16921 confp->chan.cancallforward = ast_true(v->value);
16922 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16923 if (ast_true(v->value))
16924 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16925 else
16926 confp->chan.dtmfrelax = 0;
16927 } else if (!strcasecmp(v->name, "mailbox")) {
16928 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16929 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16930 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16931 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16932 }
16933 } else if (!strcasecmp(v->name, "adsi")) {
16934 confp->chan.adsi = ast_true(v->value);
16935 } else if (!strcasecmp(v->name, "usesmdi")) {
16936 confp->chan.use_smdi = ast_true(v->value);
16937 } else if (!strcasecmp(v->name, "smdiport")) {
16938 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16939 } else if (!strcasecmp(v->name, "transfer")) {
16940 confp->chan.transfer = ast_true(v->value);
16941 } else if (!strcasecmp(v->name, "canpark")) {
16942 confp->chan.canpark = ast_true(v->value);
16943 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16944 confp->chan.echocanbridged = ast_true(v->value);
16945 } else if (!strcasecmp(v->name, "busydetect")) {
16946 confp->chan.busydetect = ast_true(v->value);
16947 } else if (!strcasecmp(v->name, "busycount")) {
16948 confp->chan.busycount = atoi(v->value);
16949 } else if (!strcasecmp(v->name, "silencethreshold")) {
16950 confp->chan.silencethreshold = atoi(v->value);
16951 } else if (!strcasecmp(v->name, "busycompare")) {
16952 confp->chan.busycompare = ast_true(v->value);
16953 } else if (!strcasecmp(v->name, "busypattern")) {
16954 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
16955 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16956 }
16957 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
16958 if (count == 1)
16959 confp->chan.busyquietlength = 0;
16960 else if (count < 1)
16961 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
16962 } else if (!strcasecmp(v->name, "busyfuzziness")) {
16963 confp->chan.busyfuzziness = atoi(v->value);
16964 } else if (!strcasecmp(v->name, "callprogress")) {
16965 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16966 if (ast_true(v->value))
16967 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16968 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16969 confp->chan.waitfordialtone = atoi(v->value);
16970 } else if (!strcasecmp(v->name, "faxdetect")) {
16971 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16972 if (!strcasecmp(v->value, "incoming")) {
16973 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16974 } else if (!strcasecmp(v->value, "outgoing")) {
16975 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16976 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16977 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16978 } else if (!strcasecmp(v->name, "echocancel")) {
16979 process_echocancel(confp, v->value, v->lineno);
16980 } else if (!strcasecmp(v->name, "echotraining")) {
16981 if (sscanf(v->value, "%30d", &y) == 1) {
16982 if ((y < 10) || (y > 4000)) {
16983 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16984 } else {
16985 confp->chan.echotraining = y;
16986 }
16987 } else if (ast_true(v->value)) {
16988 confp->chan.echotraining = 400;
16989 } else
16990 confp->chan.echotraining = 0;
16991 } else if (!strcasecmp(v->name, "hidecallerid")) {
16992 confp->chan.hidecallerid = ast_true(v->value);
16993 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16994 confp->chan.hidecalleridname = ast_true(v->value);
16995 } else if (!strcasecmp(v->name, "pulsedial")) {
16996 confp->chan.pulse = ast_true(v->value);
16997 } else if (!strcasecmp(v->name, "callreturn")) {
16998 confp->chan.callreturn = ast_true(v->value);
16999 } else if (!strcasecmp(v->name, "callwaiting")) {
17000 confp->chan.callwaiting = ast_true(v->value);
17001 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17002 confp->chan.callwaitingcallerid = ast_true(v->value);
17003 } else if (!strcasecmp(v->name, "context")) {
17004 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17005 } else if (!strcasecmp(v->name, "language")) {
17006 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17007 } else if (!strcasecmp(v->name, "progzone")) {
17008 ast_copy_string(progzone, v->value, sizeof(progzone));
17009 } else if (!strcasecmp(v->name, "mohinterpret")
17010 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17011 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17012 } else if (!strcasecmp(v->name, "mohsuggest")) {
17013 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17014 } else if (!strcasecmp(v->name, "parkinglot")) {
17015 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17016 } else if (!strcasecmp(v->name, "stripmsd")) {
17017 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17018 confp->chan.stripmsd = atoi(v->value);
17019 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17020 numbufs = atoi(v->value);
17021 } else if (!strcasecmp(v->name, "group")) {
17022 confp->chan.group = ast_get_group(v->value);
17023 } else if (!strcasecmp(v->name, "callgroup")) {
17024 if (!strcasecmp(v->value, "none"))
17025 confp->chan.callgroup = 0;
17026 else
17027 confp->chan.callgroup = ast_get_group(v->value);
17028 } else if (!strcasecmp(v->name, "pickupgroup")) {
17029 if (!strcasecmp(v->value, "none"))
17030 confp->chan.pickupgroup = 0;
17031 else
17032 confp->chan.pickupgroup = ast_get_group(v->value);
17033 } else if (!strcasecmp(v->name, "setvar")) {
17034 char *varname = ast_strdupa(v->value), *varval = NULL;
17035 struct ast_variable *tmpvar;
17036 if (varname && (varval = strchr(varname, '='))) {
17037 *varval++ = '\0';
17038 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17039 tmpvar->next = confp->chan.vars;
17040 confp->chan.vars = tmpvar;
17041 }
17042 }
17043 } else if (!strcasecmp(v->name, "immediate")) {
17044 confp->chan.immediate = ast_true(v->value);
17045 } else if (!strcasecmp(v->name, "transfertobusy")) {
17046 confp->chan.transfertobusy = ast_true(v->value);
17047 } else if (!strcasecmp(v->name, "mwimonitor")) {
17048 confp->chan.mwimonitor_neon = 0;
17049 confp->chan.mwimonitor_fsk = 0;
17050 confp->chan.mwimonitor_rpas = 0;
17051 if (strcasestr(v->value, "fsk")) {
17052 confp->chan.mwimonitor_fsk = 1;
17053 }
17054 if (strcasestr(v->value, "rpas")) {
17055 confp->chan.mwimonitor_rpas = 1;
17056 }
17057 if (strcasestr(v->value, "neon")) {
17058 confp->chan.mwimonitor_neon = 1;
17059 }
17060
17061 if (ast_true(v->value)) {
17062 confp->chan.mwimonitor_fsk = 1;
17063 }
17064 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17065 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17066 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17067 }
17068 } else if (!strcasecmp(v->name, "rxgain")) {
17069 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17070 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17071 }
17072 } else if (!strcasecmp(v->name, "txgain")) {
17073 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17074 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17075 }
17076 } else if (!strcasecmp(v->name, "txdrc")) {
17077 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17078 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17079 }
17080 } else if (!strcasecmp(v->name, "rxdrc")) {
17081 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17082 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17083 }
17084 } else if (!strcasecmp(v->name, "tonezone")) {
17085 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17086 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17087 }
17088 } else if (!strcasecmp(v->name, "callerid")) {
17089 if (!strcasecmp(v->value, "asreceived")) {
17090 confp->chan.cid_num[0] = '\0';
17091 confp->chan.cid_name[0] = '\0';
17092 } else {
17093 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17094 }
17095 } else if (!strcasecmp(v->name, "fullname")) {
17096 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17097 } else if (!strcasecmp(v->name, "cid_number")) {
17098 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17099 } else if (!strcasecmp(v->name, "cid_tag")) {
17100 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17101 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17102 confp->chan.dahditrcallerid = ast_true(v->value);
17103 } else if (!strcasecmp(v->name, "restrictcid")) {
17104 confp->chan.restrictcid = ast_true(v->value);
17105 } else if (!strcasecmp(v->name, "usecallingpres")) {
17106 confp->chan.use_callingpres = ast_true(v->value);
17107 } else if (!strcasecmp(v->name, "accountcode")) {
17108 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17109 } else if (!strcasecmp(v->name, "amaflags")) {
17110 y = ast_cdr_amaflags2int(v->value);
17111 if (y < 0)
17112 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17113 else
17114 confp->chan.amaflags = y;
17115 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17116 confp->chan.polarityonanswerdelay = atoi(v->value);
17117 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17118 confp->chan.answeronpolarityswitch = ast_true(v->value);
17119 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17120 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17121 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17122 confp->chan.sendcalleridafter = atoi(v->value);
17123 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17124 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17125 } else if (ast_cc_is_config_param(v->name)) {
17126 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17127 } else if (!strcasecmp(v->name, "mwisendtype")) {
17128 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17129 if (!strcasecmp(v->value, "rpas")) {
17130 mwisend_rpas = 1;
17131 } else {
17132 mwisend_rpas = 0;
17133 }
17134 #else
17135
17136 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17137 if (strcasestr(v->value, "nofsk")) {
17138 confp->chan.mwisend_fsk = 0;
17139 } else {
17140 confp->chan.mwisend_fsk = 1;
17141 }
17142 if (strcasestr(v->value, "rpas")) {
17143 confp->chan.mwisend_rpas = 1;
17144 } else {
17145 confp->chan.mwisend_rpas = 0;
17146 }
17147 if (strcasestr(v->value, "lrev")) {
17148 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17149 }
17150 if (strcasestr(v->value, "hvdc")) {
17151 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17152 }
17153 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17154 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17155 }
17156 #endif
17157 } else if (reload != 1) {
17158 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17159 int orig_radio = confp->chan.radio;
17160 int orig_outsigmod = confp->chan.outsigmod;
17161 int orig_auto = confp->is_sig_auto;
17162
17163 confp->chan.radio = 0;
17164 confp->chan.outsigmod = -1;
17165 confp->is_sig_auto = 0;
17166 if (!strcasecmp(v->value, "em")) {
17167 confp->chan.sig = SIG_EM;
17168 } else if (!strcasecmp(v->value, "em_e1")) {
17169 confp->chan.sig = SIG_EM_E1;
17170 } else if (!strcasecmp(v->value, "em_w")) {
17171 confp->chan.sig = SIG_EMWINK;
17172 } else if (!strcasecmp(v->value, "fxs_ls")) {
17173 confp->chan.sig = SIG_FXSLS;
17174 } else if (!strcasecmp(v->value, "fxs_gs")) {
17175 confp->chan.sig = SIG_FXSGS;
17176 } else if (!strcasecmp(v->value, "fxs_ks")) {
17177 confp->chan.sig = SIG_FXSKS;
17178 } else if (!strcasecmp(v->value, "fxo_ls")) {
17179 confp->chan.sig = SIG_FXOLS;
17180 } else if (!strcasecmp(v->value, "fxo_gs")) {
17181 confp->chan.sig = SIG_FXOGS;
17182 } else if (!strcasecmp(v->value, "fxo_ks")) {
17183 confp->chan.sig = SIG_FXOKS;
17184 } else if (!strcasecmp(v->value, "fxs_rx")) {
17185 confp->chan.sig = SIG_FXSKS;
17186 confp->chan.radio = 1;
17187 } else if (!strcasecmp(v->value, "fxo_rx")) {
17188 confp->chan.sig = SIG_FXOLS;
17189 confp->chan.radio = 1;
17190 } else if (!strcasecmp(v->value, "fxs_tx")) {
17191 confp->chan.sig = SIG_FXSLS;
17192 confp->chan.radio = 1;
17193 } else if (!strcasecmp(v->value, "fxo_tx")) {
17194 confp->chan.sig = SIG_FXOGS;
17195 confp->chan.radio = 1;
17196 } else if (!strcasecmp(v->value, "em_rx")) {
17197 confp->chan.sig = SIG_EM;
17198 confp->chan.radio = 1;
17199 } else if (!strcasecmp(v->value, "em_tx")) {
17200 confp->chan.sig = SIG_EM;
17201 confp->chan.radio = 1;
17202 } else if (!strcasecmp(v->value, "em_rxtx")) {
17203 confp->chan.sig = SIG_EM;
17204 confp->chan.radio = 2;
17205 } else if (!strcasecmp(v->value, "em_txrx")) {
17206 confp->chan.sig = SIG_EM;
17207 confp->chan.radio = 2;
17208 } else if (!strcasecmp(v->value, "sf")) {
17209 confp->chan.sig = SIG_SF;
17210 } else if (!strcasecmp(v->value, "sf_w")) {
17211 confp->chan.sig = SIG_SFWINK;
17212 } else if (!strcasecmp(v->value, "sf_featd")) {
17213 confp->chan.sig = SIG_FEATD;
17214 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17215 confp->chan.sig = SIG_FEATDMF;
17216 } else if (!strcasecmp(v->value, "sf_featb")) {
17217 confp->chan.sig = SIG_SF_FEATB;
17218 } else if (!strcasecmp(v->value, "sf")) {
17219 confp->chan.sig = SIG_SF;
17220 } else if (!strcasecmp(v->value, "sf_rx")) {
17221 confp->chan.sig = SIG_SF;
17222 confp->chan.radio = 1;
17223 } else if (!strcasecmp(v->value, "sf_tx")) {
17224 confp->chan.sig = SIG_SF;
17225 confp->chan.radio = 1;
17226 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17227 confp->chan.sig = SIG_SF;
17228 confp->chan.radio = 2;
17229 } else if (!strcasecmp(v->value, "sf_txrx")) {
17230 confp->chan.sig = SIG_SF;
17231 confp->chan.radio = 2;
17232 } else if (!strcasecmp(v->value, "featd")) {
17233 confp->chan.sig = SIG_FEATD;
17234 } else if (!strcasecmp(v->value, "featdmf")) {
17235 confp->chan.sig = SIG_FEATDMF;
17236 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17237 confp->chan.sig = SIG_FEATDMF_TA;
17238 } else if (!strcasecmp(v->value, "e911")) {
17239 confp->chan.sig = SIG_E911;
17240 } else if (!strcasecmp(v->value, "fgccama")) {
17241 confp->chan.sig = SIG_FGC_CAMA;
17242 } else if (!strcasecmp(v->value, "fgccamamf")) {
17243 confp->chan.sig = SIG_FGC_CAMAMF;
17244 } else if (!strcasecmp(v->value, "featb")) {
17245 confp->chan.sig = SIG_FEATB;
17246 #ifdef HAVE_PRI
17247 } else if (!strcasecmp(v->value, "pri_net")) {
17248 confp->chan.sig = SIG_PRI;
17249 confp->pri.pri.nodetype = PRI_NETWORK;
17250 } else if (!strcasecmp(v->value, "pri_cpe")) {
17251 confp->chan.sig = SIG_PRI;
17252 confp->pri.pri.nodetype = PRI_CPE;
17253 } else if (!strcasecmp(v->value, "bri_cpe")) {
17254 confp->chan.sig = SIG_BRI;
17255 confp->pri.pri.nodetype = PRI_CPE;
17256 } else if (!strcasecmp(v->value, "bri_net")) {
17257 confp->chan.sig = SIG_BRI;
17258 confp->pri.pri.nodetype = PRI_NETWORK;
17259 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17260 confp->chan.sig = SIG_BRI_PTMP;
17261 confp->pri.pri.nodetype = PRI_CPE;
17262 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17263 #if defined(HAVE_PRI_CALL_HOLD)
17264 confp->chan.sig = SIG_BRI_PTMP;
17265 confp->pri.pri.nodetype = PRI_NETWORK;
17266 #else
17267 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17268 #endif
17269 #endif
17270 #if defined(HAVE_SS7)
17271 } else if (!strcasecmp(v->value, "ss7")) {
17272 confp->chan.sig = SIG_SS7;
17273 #endif
17274 #ifdef HAVE_OPENR2
17275 } else if (!strcasecmp(v->value, "mfcr2")) {
17276 confp->chan.sig = SIG_MFCR2;
17277 #endif
17278 } else if (!strcasecmp(v->value, "auto")) {
17279 confp->is_sig_auto = 1;
17280 } else {
17281 confp->chan.outsigmod = orig_outsigmod;
17282 confp->chan.radio = orig_radio;
17283 confp->is_sig_auto = orig_auto;
17284 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17285 }
17286 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17287 if (!strcasecmp(v->value, "em")) {
17288 confp->chan.outsigmod = SIG_EM;
17289 } else if (!strcasecmp(v->value, "em_e1")) {
17290 confp->chan.outsigmod = SIG_EM_E1;
17291 } else if (!strcasecmp(v->value, "em_w")) {
17292 confp->chan.outsigmod = SIG_EMWINK;
17293 } else if (!strcasecmp(v->value, "sf")) {
17294 confp->chan.outsigmod = SIG_SF;
17295 } else if (!strcasecmp(v->value, "sf_w")) {
17296 confp->chan.outsigmod = SIG_SFWINK;
17297 } else if (!strcasecmp(v->value, "sf_featd")) {
17298 confp->chan.outsigmod = SIG_FEATD;
17299 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17300 confp->chan.outsigmod = SIG_FEATDMF;
17301 } else if (!strcasecmp(v->value, "sf_featb")) {
17302 confp->chan.outsigmod = SIG_SF_FEATB;
17303 } else if (!strcasecmp(v->value, "sf")) {
17304 confp->chan.outsigmod = SIG_SF;
17305 } else if (!strcasecmp(v->value, "featd")) {
17306 confp->chan.outsigmod = SIG_FEATD;
17307 } else if (!strcasecmp(v->value, "featdmf")) {
17308 confp->chan.outsigmod = SIG_FEATDMF;
17309 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17310 confp->chan.outsigmod = SIG_FEATDMF_TA;
17311 } else if (!strcasecmp(v->value, "e911")) {
17312 confp->chan.outsigmod = SIG_E911;
17313 } else if (!strcasecmp(v->value, "fgccama")) {
17314 confp->chan.outsigmod = SIG_FGC_CAMA;
17315 } else if (!strcasecmp(v->value, "fgccamamf")) {
17316 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17317 } else if (!strcasecmp(v->value, "featb")) {
17318 confp->chan.outsigmod = SIG_FEATB;
17319 } else {
17320 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17321 }
17322 #ifdef HAVE_PRI
17323 } else if (!strcasecmp(v->name, "pridialplan")) {
17324 if (!strcasecmp(v->value, "national")) {
17325 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17326 } else if (!strcasecmp(v->value, "unknown")) {
17327 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17328 } else if (!strcasecmp(v->value, "private")) {
17329 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17330 } else if (!strcasecmp(v->value, "international")) {
17331 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17332 } else if (!strcasecmp(v->value, "local")) {
17333 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17334 } else if (!strcasecmp(v->value, "dynamic")) {
17335 confp->pri.pri.dialplan = -1;
17336 } else if (!strcasecmp(v->value, "redundant")) {
17337 confp->pri.pri.dialplan = -2;
17338 } else {
17339 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17340 }
17341 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17342 if (!strcasecmp(v->value, "national")) {
17343 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17344 } else if (!strcasecmp(v->value, "unknown")) {
17345 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17346 } else if (!strcasecmp(v->value, "private")) {
17347 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17348 } else if (!strcasecmp(v->value, "international")) {
17349 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17350 } else if (!strcasecmp(v->value, "local")) {
17351 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17352 } else if (!strcasecmp(v->value, "dynamic")) {
17353 confp->pri.pri.localdialplan = -1;
17354 } else if (!strcasecmp(v->value, "redundant")) {
17355 confp->pri.pri.localdialplan = -2;
17356 } else {
17357 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17358 }
17359 } else if (!strcasecmp(v->name, "switchtype")) {
17360 if (!strcasecmp(v->value, "national"))
17361 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17362 else if (!strcasecmp(v->value, "ni1"))
17363 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17364 else if (!strcasecmp(v->value, "dms100"))
17365 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17366 else if (!strcasecmp(v->value, "4ess"))
17367 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17368 else if (!strcasecmp(v->value, "5ess"))
17369 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17370 else if (!strcasecmp(v->value, "euroisdn"))
17371 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17372 else if (!strcasecmp(v->value, "qsig"))
17373 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17374 else {
17375 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17376 return -1;
17377 }
17378 } else if (!strcasecmp(v->name, "msn")) {
17379 ast_copy_string(confp->pri.pri.msn_list, v->value,
17380 sizeof(confp->pri.pri.msn_list));
17381 } else if (!strcasecmp(v->name, "nsf")) {
17382 if (!strcasecmp(v->value, "sdn"))
17383 confp->pri.pri.nsf = PRI_NSF_SDN;
17384 else if (!strcasecmp(v->value, "megacom"))
17385 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17386 else if (!strcasecmp(v->value, "tollfreemegacom"))
17387 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17388 else if (!strcasecmp(v->value, "accunet"))
17389 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17390 else if (!strcasecmp(v->value, "none"))
17391 confp->pri.pri.nsf = PRI_NSF_NONE;
17392 else {
17393 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17394 confp->pri.pri.nsf = PRI_NSF_NONE;
17395 }
17396 } else if (!strcasecmp(v->name, "priindication")) {
17397 if (!strcasecmp(v->value, "outofband"))
17398 confp->chan.priindication_oob = 1;
17399 else if (!strcasecmp(v->value, "inband"))
17400 confp->chan.priindication_oob = 0;
17401 else
17402 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17403 v->value, v->lineno);
17404 } else if (!strcasecmp(v->name, "priexclusive")) {
17405 confp->chan.priexclusive = ast_true(v->value);
17406 } else if (!strcasecmp(v->name, "internationalprefix")) {
17407 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17408 } else if (!strcasecmp(v->name, "nationalprefix")) {
17409 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17410 } else if (!strcasecmp(v->name, "localprefix")) {
17411 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17412 } else if (!strcasecmp(v->name, "privateprefix")) {
17413 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17414 } else if (!strcasecmp(v->name, "unknownprefix")) {
17415 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17416 } else if (!strcasecmp(v->name, "resetinterval")) {
17417 if (!strcasecmp(v->value, "never"))
17418 confp->pri.pri.resetinterval = -1;
17419 else if (atoi(v->value) >= 60)
17420 confp->pri.pri.resetinterval = atoi(v->value);
17421 else
17422 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17423 v->value, v->lineno);
17424 } else if (!strcasecmp(v->name, "minunused")) {
17425 confp->pri.pri.minunused = atoi(v->value);
17426 } else if (!strcasecmp(v->name, "minidle")) {
17427 confp->pri.pri.minidle = atoi(v->value);
17428 } else if (!strcasecmp(v->name, "idleext")) {
17429 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17430 } else if (!strcasecmp(v->name, "idledial")) {
17431 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17432 } else if (!strcasecmp(v->name, "overlapdial")) {
17433 if (ast_true(v->value)) {
17434 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17435 } else if (!strcasecmp(v->value, "incoming")) {
17436 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17437 } else if (!strcasecmp(v->value, "outgoing")) {
17438 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17439 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17440 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17441 } else {
17442 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17443 }
17444 #ifdef HAVE_PRI_PROG_W_CAUSE
17445 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17446 if (!strcasecmp(v->value, "logical")) {
17447 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17448 } else if (!strcasecmp(v->value, "physical")) {
17449 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17450 } else {
17451 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17452 }
17453 #endif
17454 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17455 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17456 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17457 } else if (!strcasecmp(v->name, "service_message_support")) {
17458
17459 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17460 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17461 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17462 confp->pri.pri.enable_service_message_support = 1;
17463 } else {
17464 confp->pri.pri.enable_service_message_support = 0;
17465 }
17466 #endif
17467 #ifdef HAVE_PRI_INBANDDISCONNECT
17468 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17469 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17470 #endif
17471 } else if (!strcasecmp(v->name, "pritimer")) {
17472 #ifdef PRI_GETSET_TIMERS
17473 char tmp[20];
17474 char *timerc;
17475 char *c;
17476 int timer;
17477 int timeridx;
17478
17479 ast_copy_string(tmp, v->value, sizeof(tmp));
17480 c = tmp;
17481 timerc = strsep(&c, ",");
17482 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17483 timeridx = pri_timer2idx(timerc);
17484 timer = atoi(c);
17485 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17486 ast_log(LOG_WARNING,
17487 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17488 v->lineno);
17489 } else if (!timer) {
17490 ast_log(LOG_WARNING,
17491 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17492 c, timerc, v->lineno);
17493 } else {
17494 confp->pri.pri.pritimers[timeridx] = timer;
17495 }
17496 } else {
17497 ast_log(LOG_WARNING,
17498 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17499 v->value, v->lineno);
17500 }
17501 #endif
17502 } else if (!strcasecmp(v->name, "facilityenable")) {
17503 confp->pri.pri.facilityenable = ast_true(v->value);
17504 #if defined(HAVE_PRI_AOC_EVENTS)
17505 } else if (!strcasecmp(v->name, "aoc_enable")) {
17506 confp->pri.pri.aoc_passthrough_flag = 0;
17507 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17508 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17509 }
17510 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17511 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17512 }
17513 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17514 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17515 }
17516 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17517 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17518 #endif
17519 #if defined(HAVE_PRI_CALL_HOLD)
17520 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17521 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17522 #endif
17523 #if defined(HAVE_PRI_CCSS)
17524 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17525 if (!strcasecmp(v->value, "global")) {
17526 confp->pri.pri.cc_ptmp_recall_mode = 0;
17527 } else if (!strcasecmp(v->value, "specific")) {
17528 confp->pri.pri.cc_ptmp_recall_mode = 1;
17529 } else {
17530 confp->pri.pri.cc_ptmp_recall_mode = 1;
17531 }
17532 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17533 if (!strcasecmp(v->value, "release")) {
17534 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17535 } else if (!strcasecmp(v->value, "retain")) {
17536 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17537 } else if (!strcasecmp(v->value, "do_not_care")) {
17538 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17539 } else {
17540 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17541 }
17542 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17543 if (!strcasecmp(v->value, "release")) {
17544 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17545 } else if (!strcasecmp(v->value, "retain")) {
17546 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17547 } else {
17548 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17549 }
17550 #endif
17551 #if defined(HAVE_PRI_CALL_WAITING)
17552 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17553 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17554 if (confp->pri.pri.max_call_waiting_calls < 0) {
17555
17556 confp->pri.pri.max_call_waiting_calls = 0;
17557 }
17558 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17559 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17560 #endif
17561 #if defined(HAVE_PRI_MWI)
17562 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17563 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17564 sizeof(confp->pri.pri.mwi_mailboxes));
17565 #endif
17566 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17567 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17568 #if defined(HAVE_PRI_L2_PERSISTENCE)
17569 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17570 if (!strcasecmp(v->value, "keep_up")) {
17571 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17572 } else if (!strcasecmp(v->value, "leave_down")) {
17573 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17574 } else {
17575 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17576 }
17577 #endif
17578 #endif
17579 #if defined(HAVE_SS7)
17580 } else if (!strcasecmp(v->name, "ss7type")) {
17581 if (!strcasecmp(v->value, "itu")) {
17582 cur_ss7type = SS7_ITU;
17583 } else if (!strcasecmp(v->value, "ansi")) {
17584 cur_ss7type = SS7_ANSI;
17585 } else
17586 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17587 } else if (!strcasecmp(v->name, "linkset")) {
17588 cur_linkset = atoi(v->value);
17589 } else if (!strcasecmp(v->name, "pointcode")) {
17590 cur_pointcode = parse_pointcode(v->value);
17591 } else if (!strcasecmp(v->name, "adjpointcode")) {
17592 cur_adjpointcode = parse_pointcode(v->value);
17593 } else if (!strcasecmp(v->name, "defaultdpc")) {
17594 cur_defaultdpc = parse_pointcode(v->value);
17595 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17596 cur_cicbeginswith = atoi(v->value);
17597 } else if (!strcasecmp(v->name, "networkindicator")) {
17598 if (!strcasecmp(v->value, "national"))
17599 cur_networkindicator = SS7_NI_NAT;
17600 else if (!strcasecmp(v->value, "national_spare"))
17601 cur_networkindicator = SS7_NI_NAT_SPARE;
17602 else if (!strcasecmp(v->value, "international"))
17603 cur_networkindicator = SS7_NI_INT;
17604 else if (!strcasecmp(v->value, "international_spare"))
17605 cur_networkindicator = SS7_NI_INT_SPARE;
17606 else
17607 cur_networkindicator = -1;
17608 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17609 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17610 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17611 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17612 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17613 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17614 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17615 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17616 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17617 if (!strcasecmp(v->value, "national")) {
17618 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17619 } else if (!strcasecmp(v->value, "international")) {
17620 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17621 } else if (!strcasecmp(v->value, "subscriber")) {
17622 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17623 } else if (!strcasecmp(v->value, "unknown")) {
17624 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17625 } else if (!strcasecmp(v->value, "dynamic")) {
17626 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17627 } else {
17628 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17629 }
17630 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17631 if (!strcasecmp(v->value, "national")) {
17632 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17633 } else if (!strcasecmp(v->value, "international")) {
17634 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17635 } else if (!strcasecmp(v->value, "subscriber")) {
17636 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17637 } else if (!strcasecmp(v->value, "unknown")) {
17638 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17639 } else if (!strcasecmp(v->value, "dynamic")) {
17640 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17641 } else {
17642 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17643 }
17644 } else if (!strcasecmp(v->name, "sigchan")) {
17645 int sigchan, res;
17646 sigchan = atoi(v->value);
17647 res = linkset_addsigchan(sigchan);
17648 if (res < 0)
17649 return -1;
17650
17651 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17652 struct dahdi_ss7 *link;
17653 link = ss7_resolve_linkset(cur_linkset);
17654 if (!link) {
17655 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17656 return -1;
17657 }
17658 if (ast_true(v->value))
17659 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17660 #endif
17661 #ifdef HAVE_OPENR2
17662 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17663 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17664 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);
17665 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17666 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17667 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17668 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17669 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17670 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17671 confp->mfcr2.variant = OR2_VAR_ITU;
17672 }
17673 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17674 confp->mfcr2.mfback_timeout = atoi(v->value);
17675 if (!confp->mfcr2.mfback_timeout) {
17676 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17677 confp->mfcr2.mfback_timeout = -1;
17678 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17679 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17680 }
17681 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17682 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17683 if (confp->mfcr2.metering_pulse_timeout > 500) {
17684 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17685 }
17686 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17687 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17688 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17689 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17690 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17691 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17692 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17693 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17694 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17695 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17696 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17697 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17698 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17699 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17700 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17701 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17702 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17703 #endif
17704 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17705 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17706 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17707 confp->mfcr2.max_ani = atoi(v->value);
17708 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17709 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17710 }
17711 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17712 confp->mfcr2.max_dnis = atoi(v->value);
17713 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17714 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17715 }
17716 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17717 confp->mfcr2.category = openr2_proto_get_category(v->value);
17718 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17719 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17720 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17721 v->value, v->lineno);
17722 }
17723 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17724 openr2_log_level_t tmplevel;
17725 char *clevel;
17726 char *logval = ast_strdupa(v->value);
17727 while (logval) {
17728 clevel = strsep(&logval,",");
17729 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17730 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17731 continue;
17732 }
17733 confp->mfcr2.loglevel |= tmplevel;
17734 }
17735 #endif
17736 } else if (!strcasecmp(v->name, "cadence")) {
17737
17738 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17739 int i;
17740 struct dahdi_ring_cadence new_cadence;
17741 int cid_location = -1;
17742 int firstcadencepos = 0;
17743 char original_args[80];
17744 int cadence_is_ok = 1;
17745
17746 ast_copy_string(original_args, v->value, sizeof(original_args));
17747
17748 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]);
17749
17750
17751 if (element_count % 2 == 1) {
17752 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17753 cadence_is_ok = 0;
17754 }
17755
17756
17757 for (i = 0; i < element_count; i++) {
17758 if (c[i] == 0) {
17759 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17760 cadence_is_ok = 0;
17761 break;
17762 } else if (c[i] < 0) {
17763 if (i % 2 == 1) {
17764
17765 if (cid_location == -1) {
17766 cid_location = i;
17767 c[i] *= -1;
17768 } else {
17769 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17770 cadence_is_ok = 0;
17771 break;
17772 }
17773 } else {
17774 if (firstcadencepos == 0) {
17775 firstcadencepos = i;
17776
17777 } else {
17778 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17779 cadence_is_ok = 0;
17780 break;
17781 }
17782 }
17783 }
17784 }
17785
17786
17787 for (i = 0; i < 16; i++) {
17788 new_cadence.ringcadence[i] = c[i];
17789 }
17790
17791 if (cadence_is_ok) {
17792
17793 if (element_count < 2) {
17794 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17795 } else {
17796 if (cid_location == -1) {
17797
17798 cid_location = 1;
17799 } else {
17800
17801 cid_location = (cid_location + 1) / 2;
17802 }
17803
17804 if (!user_has_defined_cadences++)
17805
17806 num_cadence = 0;
17807 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17808 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17809 else {
17810 cadences[num_cadence] = new_cadence;
17811 cidrings[num_cadence++] = cid_location;
17812 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17813 }
17814 }
17815 }
17816 } else if (!strcasecmp(v->name, "ringtimeout")) {
17817 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17818 } else if (!strcasecmp(v->name, "prewink")) {
17819 confp->timing.prewinktime = atoi(v->value);
17820 } else if (!strcasecmp(v->name, "preflash")) {
17821 confp->timing.preflashtime = atoi(v->value);
17822 } else if (!strcasecmp(v->name, "wink")) {
17823 confp->timing.winktime = atoi(v->value);
17824 } else if (!strcasecmp(v->name, "flash")) {
17825 confp->timing.flashtime = atoi(v->value);
17826 } else if (!strcasecmp(v->name, "start")) {
17827 confp->timing.starttime = atoi(v->value);
17828 } else if (!strcasecmp(v->name, "rxwink")) {
17829 confp->timing.rxwinktime = atoi(v->value);
17830 } else if (!strcasecmp(v->name, "rxflash")) {
17831 confp->timing.rxflashtime = atoi(v->value);
17832 } else if (!strcasecmp(v->name, "debounce")) {
17833 confp->timing.debouncetime = atoi(v->value);
17834 } else if (!strcasecmp(v->name, "toneduration")) {
17835 int toneduration;
17836 int ctlfd;
17837 int res;
17838 struct dahdi_dialparams dps;
17839
17840 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17841 if (ctlfd == -1) {
17842 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17843 return -1;
17844 }
17845
17846 toneduration = atoi(v->value);
17847 if (toneduration > -1) {
17848 memset(&dps, 0, sizeof(dps));
17849
17850 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17851 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17852 if (res < 0) {
17853 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17854 close(ctlfd);
17855 return -1;
17856 }
17857 }
17858 close(ctlfd);
17859 } else if (!strcasecmp(v->name, "defaultcic")) {
17860 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17861 } else if (!strcasecmp(v->name, "defaultozz")) {
17862 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17863 } else if (!strcasecmp(v->name, "mwilevel")) {
17864 mwilevel = atoi(v->value);
17865 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17866 dtmfcid_level = atoi(v->value);
17867 } else if (!strcasecmp(v->name, "reportalarms")) {
17868 if (!strcasecmp(v->value, "all"))
17869 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17870 if (!strcasecmp(v->value, "none"))
17871 report_alarms = 0;
17872 else if (!strcasecmp(v->value, "channels"))
17873 report_alarms = REPORT_CHANNEL_ALARMS;
17874 else if (!strcasecmp(v->value, "spans"))
17875 report_alarms = REPORT_SPAN_ALARMS;
17876 }
17877 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17878 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17879 }
17880
17881
17882 if (confp->chan.vars) {
17883 ast_variables_destroy(confp->chan.vars);
17884 confp->chan.vars = NULL;
17885 }
17886
17887 if (dahdichan) {
17888
17889 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17890 &found_pseudo)) {
17891 if (confp->ignore_failed_channels) {
17892 ast_log(LOG_WARNING,
17893 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17894 dahdichan->value);
17895 } else {
17896 return -1;
17897 }
17898 }
17899 }
17900
17901
17902 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17903 if (!tmp->destroy && tmp->span != y) {
17904 tmp->manages_span_alarms = 1;
17905 y = tmp->span;
17906 } else {
17907 tmp->manages_span_alarms = 0;
17908 }
17909 }
17910
17911
17912
17913 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17914
17915
17916
17917
17918 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17919
17920 if (conf.chan.cc_params) {
17921 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17922 } else {
17923 tmp = NULL;
17924 }
17925 if (tmp) {
17926 ast_verb(3, "Automatically generated pseudo channel\n");
17927 } else {
17928 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17929 }
17930 ast_cc_config_params_destroy(conf.chan.cc_params);
17931 }
17932 return 0;
17933 }
17934
17935
17936
17937
17938
17939
17940
17941
17942
17943
17944
17945 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17946 {
17947 struct ast_cc_config_params *cc_params;
17948
17949 cc_params = dest->chan.cc_params;
17950 *dest = *src;
17951 dest->chan.cc_params = cc_params;
17952 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17953 }
17954
17955
17956
17957
17958
17959
17960
17961
17962
17963
17964
17965
17966
17967 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17968 {
17969 struct ast_config *cfg;
17970 struct ast_config *ucfg;
17971 struct ast_variable *v;
17972 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17973 const char *chans;
17974 const char *cat;
17975 int res;
17976
17977 #ifdef HAVE_PRI
17978 char *c;
17979 int spanno;
17980 int i;
17981 int logicalspan;
17982 int trunkgroup;
17983 int dchannels[SIG_PRI_NUM_DCHANS];
17984 #endif
17985 int have_cfg_now;
17986 static int had_cfg_before = 1;
17987
17988 cfg = ast_config_load(config, config_flags);
17989 have_cfg_now = !!cfg;
17990 if (!cfg) {
17991
17992 if (had_cfg_before) {
17993 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17994 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17995 }
17996 cfg = ast_config_new();
17997 if (!cfg) {
17998 return 0;
17999 }
18000 ucfg = ast_config_load("users.conf", config_flags);
18001 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18002 ast_config_destroy(cfg);
18003 return 0;
18004 }
18005 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18006 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18007 ast_config_destroy(cfg);
18008 return 0;
18009 }
18010 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18011 ucfg = ast_config_load("users.conf", config_flags);
18012 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18013 return 0;
18014 }
18015 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18016 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18017 return 0;
18018 }
18019 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18020 cfg = ast_config_load(config, config_flags);
18021 have_cfg_now = !!cfg;
18022 if (!cfg) {
18023 if (had_cfg_before) {
18024
18025 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18026 ast_config_destroy(ucfg);
18027 return 0;
18028 }
18029 cfg = ast_config_new();
18030 if (!cfg) {
18031 ast_config_destroy(ucfg);
18032 return 0;
18033 }
18034 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18035 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18036 ast_config_destroy(ucfg);
18037 return 0;
18038 }
18039 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18040 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18041 return 0;
18042 } else {
18043 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18044 ucfg = ast_config_load("users.conf", config_flags);
18045 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18046 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18047 ast_config_destroy(cfg);
18048 return 0;
18049 }
18050 }
18051 had_cfg_before = have_cfg_now;
18052
18053
18054 ast_mutex_lock(&iflock);
18055 #ifdef HAVE_PRI
18056 if (reload != 1) {
18057
18058 v = ast_variable_browse(cfg, "trunkgroups");
18059 while (v) {
18060 if (!strcasecmp(v->name, "trunkgroup")) {
18061 trunkgroup = atoi(v->value);
18062 if (trunkgroup > 0) {
18063 if ((c = strchr(v->value, ','))) {
18064 i = 0;
18065 memset(dchannels, 0, sizeof(dchannels));
18066 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18067 dchannels[i] = atoi(c + 1);
18068 if (dchannels[i] < 0) {
18069 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);
18070 } else
18071 i++;
18072 c = strchr(c + 1, ',');
18073 }
18074 if (i) {
18075 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18076 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);
18077 } else
18078 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");
18079 } else
18080 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18081 } else
18082 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18083 } else
18084 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18085 } else if (!strcasecmp(v->name, "spanmap")) {
18086 spanno = atoi(v->value);
18087 if (spanno > 0) {
18088 if ((c = strchr(v->value, ','))) {
18089 trunkgroup = atoi(c + 1);
18090 if (trunkgroup > 0) {
18091 if ((c = strchr(c + 1, ',')))
18092 logicalspan = atoi(c + 1);
18093 else
18094 logicalspan = 0;
18095 if (logicalspan >= 0) {
18096 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18097 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18098 } else
18099 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18100 } else
18101 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);
18102 } else
18103 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18104 } else
18105 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18106 } else
18107 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18108 } else {
18109 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18110 }
18111 v = v->next;
18112 }
18113 }
18114 #endif
18115
18116
18117 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18118
18119 mwimonitornotify[0] = '\0';
18120
18121 v = ast_variable_browse(cfg, "channels");
18122 if ((res = process_dahdi(base_conf,
18123 "" ,
18124 v, reload, 0))) {
18125 ast_mutex_unlock(&iflock);
18126 ast_config_destroy(cfg);
18127 if (ucfg) {
18128 ast_config_destroy(ucfg);
18129 }
18130 return res;
18131 }
18132
18133
18134 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18135
18136
18137
18138 if (!strcasecmp(cat, "general") ||
18139 !strcasecmp(cat, "trunkgroups") ||
18140 !strcasecmp(cat, "globals") ||
18141 !strcasecmp(cat, "channels")) {
18142 continue;
18143 }
18144
18145 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18146 if (ast_strlen_zero(chans)) {
18147
18148 continue;
18149 }
18150
18151
18152 deep_copy_dahdi_chan_conf(conf, base_conf);
18153
18154 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18155 ast_mutex_unlock(&iflock);
18156 ast_config_destroy(cfg);
18157 if (ucfg) {
18158 ast_config_destroy(ucfg);
18159 }
18160 return res;
18161 }
18162 }
18163
18164 ast_config_destroy(cfg);
18165
18166 if (ucfg) {
18167
18168 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18169 process_dahdi(base_conf,
18170 "" ,
18171 ast_variable_browse(ucfg, "general"), 1, 0);
18172
18173 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18174 if (!strcasecmp(cat, "general")) {
18175 continue;
18176 }
18177
18178 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18179 if (ast_strlen_zero(chans)) {
18180
18181 continue;
18182 }
18183
18184
18185 deep_copy_dahdi_chan_conf(conf, base_conf);
18186
18187 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18188 ast_config_destroy(ucfg);
18189 ast_mutex_unlock(&iflock);
18190 return res;
18191 }
18192 }
18193 ast_config_destroy(ucfg);
18194 }
18195 ast_mutex_unlock(&iflock);
18196
18197 #ifdef HAVE_PRI
18198 if (reload != 1) {
18199 int x;
18200 for (x = 0; x < NUM_SPANS; x++) {
18201 if (pris[x].pri.pvts[0]) {
18202 prepare_pri(pris + x);
18203 if (sig_pri_start_pri(&pris[x].pri)) {
18204 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18205 return -1;
18206 } else
18207 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18208 }
18209 }
18210 }
18211 #endif
18212 #if defined(HAVE_SS7)
18213 if (reload != 1) {
18214 int x;
18215 for (x = 0; x < NUM_SPANS; x++) {
18216 if (linksets[x].ss7.ss7) {
18217 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18218 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18219 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18220 return -1;
18221 } else
18222 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18223 }
18224 }
18225 }
18226 #endif
18227 #ifdef HAVE_OPENR2
18228 if (reload != 1) {
18229 int x;
18230 for (x = 0; x < r2links_count; x++) {
18231 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18232 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18233 return -1;
18234 } else {
18235 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18236 }
18237 }
18238 }
18239 #endif
18240
18241 restart_monitor();
18242 return 0;
18243 }
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254 static int setup_dahdi(int reload)
18255 {
18256 int res;
18257 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18258 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18259 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18260
18261 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18262 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18263 } else {
18264 res = -1;
18265 }
18266 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18267 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18268 ast_cc_config_params_destroy(conf.chan.cc_params);
18269
18270 return res;
18271 }
18272
18273
18274
18275
18276
18277
18278
18279
18280 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18281 struct ast_data *data_root)
18282 {
18283 int ctl, res, span;
18284 struct ast_data *data_span, *data_alarms;
18285 struct dahdi_spaninfo s;
18286
18287 ctl = open("/dev/dahdi/ctl", O_RDWR);
18288 if (ctl < 0) {
18289 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18290 return -1;
18291 }
18292 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18293 s.spanno = span;
18294 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18295 if (res) {
18296 continue;
18297 }
18298
18299 data_span = ast_data_add_node(data_root, "span");
18300 if (!data_span) {
18301 continue;
18302 }
18303 ast_data_add_str(data_span, "description", s.desc);
18304
18305
18306 data_alarms = ast_data_add_node(data_span, "alarms");
18307 if (!data_alarms) {
18308 continue;
18309 }
18310
18311 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18312 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18313 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18314 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18315 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18316 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18317
18318 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18319 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18320 ast_data_add_int(data_span, "crc4", s.crc4count);
18321 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18322 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18323 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18324 "CAS");
18325 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18326 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18327 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18328 "Unknown");
18329 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18330 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18331 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18332 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18333
18334
18335 if (!ast_data_search_match(search, data_span)) {
18336 ast_data_remove_node(data_root, data_span);
18337 }
18338 }
18339 close(ctl);
18340
18341 return 0;
18342 }
18343
18344
18345
18346
18347
18348
18349
18350
18351 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18352 struct ast_data *data_root)
18353 {
18354 struct dahdi_pvt *tmp;
18355 struct ast_data *data_channel;
18356
18357 ast_mutex_lock(&iflock);
18358 for (tmp = iflist; tmp; tmp = tmp->next) {
18359 data_channel = ast_data_add_node(data_root, "channel");
18360 if (!data_channel) {
18361 continue;
18362 }
18363
18364 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18365
18366
18367 if (!ast_data_search_match(search, data_channel)) {
18368 ast_data_remove_node(data_root, data_channel);
18369 }
18370 }
18371 ast_mutex_unlock(&iflock);
18372
18373 return 0;
18374 }
18375
18376
18377
18378
18379
18380
18381
18382
18383 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18384 struct ast_data *data_root)
18385 {
18386 int pseudo_fd = -1;
18387 struct dahdi_versioninfo vi = {
18388 .version = "Unknown",
18389 .echo_canceller = "Unknown"
18390 };
18391
18392 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18393 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18394 return -1;
18395 }
18396
18397 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18398 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18399 }
18400
18401 close(pseudo_fd);
18402
18403 ast_data_add_str(data_root, "value", vi.version);
18404 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18405
18406 return 0;
18407 }
18408
18409 static const struct ast_data_handler dahdi_status_data_provider = {
18410 .version = AST_DATA_HANDLER_VERSION,
18411 .get = dahdi_status_data_provider_get
18412 };
18413
18414 static const struct ast_data_handler dahdi_channels_data_provider = {
18415 .version = AST_DATA_HANDLER_VERSION,
18416 .get = dahdi_channels_data_provider_get
18417 };
18418
18419 static const struct ast_data_handler dahdi_version_data_provider = {
18420 .version = AST_DATA_HANDLER_VERSION,
18421 .get = dahdi_version_data_provider_get
18422 };
18423
18424 static const struct ast_data_entry dahdi_data_providers[] = {
18425 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18426 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18427 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18428 };
18429
18430 static int load_module(void)
18431 {
18432 int res;
18433 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18434 int y;
18435 #endif
18436
18437 #ifdef HAVE_PRI
18438 memset(pris, 0, sizeof(pris));
18439 for (y = 0; y < NUM_SPANS; y++) {
18440 sig_pri_init_pri(&pris[y].pri);
18441 }
18442 pri_set_error(dahdi_pri_error);
18443 pri_set_message(dahdi_pri_message);
18444 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18445 #ifdef HAVE_PRI_PROG_W_CAUSE
18446 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18447 #endif
18448 #if defined(HAVE_PRI_CCSS)
18449 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18450 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18451 __unload_module();
18452 return AST_MODULE_LOAD_FAILURE;
18453 }
18454 #endif
18455 if (sig_pri_load(
18456 #if defined(HAVE_PRI_CCSS)
18457 dahdi_pri_cc_type
18458 #else
18459 NULL
18460 #endif
18461 )) {
18462 __unload_module();
18463 return AST_MODULE_LOAD_FAILURE;
18464 }
18465 #endif
18466 #if defined(HAVE_SS7)
18467 memset(linksets, 0, sizeof(linksets));
18468 for (y = 0; y < NUM_SPANS; y++) {
18469 sig_ss7_init_linkset(&linksets[y].ss7);
18470 }
18471 ss7_set_error(dahdi_ss7_error);
18472 ss7_set_message(dahdi_ss7_message);
18473 #endif
18474 res = setup_dahdi(0);
18475
18476 if (res)
18477 return AST_MODULE_LOAD_DECLINE;
18478 if (ast_channel_register(&dahdi_tech)) {
18479 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18480 __unload_module();
18481 return AST_MODULE_LOAD_FAILURE;
18482 }
18483 #ifdef HAVE_PRI
18484 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18485 #endif
18486 #if defined(HAVE_SS7)
18487 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18488 #endif
18489 #ifdef HAVE_OPENR2
18490 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18491 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18492 #endif
18493
18494 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18495
18496 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18497 memset(round_robin, 0, sizeof(round_robin));
18498 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18499 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18500 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18501 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18502 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18503 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18504 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18505
18506 ast_cond_init(&ss_thread_complete, NULL);
18507
18508 return res;
18509 }
18510
18511 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18512 {
18513 #define END_SILENCE_LEN 400
18514 #define HEADER_MS 50
18515 #define TRAILER_MS 5
18516 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18517 #define ASCII_BYTES_PER_CHAR 80
18518
18519 unsigned char *buf,*mybuf;
18520 struct dahdi_pvt *p = c->tech_pvt;
18521 struct pollfd fds[1];
18522 int size,res,fd,len,x;
18523 int bytes=0;
18524
18525 float cr = 1.0;
18526 float ci = 0.0;
18527 float scont = 0.0;
18528 int idx;
18529
18530 idx = dahdi_get_index(c, p, 0);
18531 if (idx < 0) {
18532 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18533 return -1;
18534 }
18535 if (!text[0]) return(0);
18536 if ((!p->tdd) && (!p->mate)) return(0);
18537 if (p->mate)
18538 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18539 else
18540 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18541 if (!buf)
18542 return -1;
18543 mybuf = buf;
18544 if (p->mate) {
18545 int codec = AST_LAW(p);
18546 for (x = 0; x < HEADER_MS; x++) {
18547 PUT_CLID_MARKMS;
18548 }
18549
18550 for (x = 0; text[x]; x++) {
18551 PUT_CLID(text[x]);
18552 }
18553 for (x = 0; x < TRAILER_MS; x++) {
18554 PUT_CLID_MARKMS;
18555 }
18556 len = bytes;
18557 buf = mybuf;
18558 } else {
18559 len = tdd_generate(p->tdd, buf, text);
18560 if (len < 1) {
18561 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18562 ast_free(mybuf);
18563 return -1;
18564 }
18565 }
18566 memset(buf + len, 0x7f, END_SILENCE_LEN);
18567 len += END_SILENCE_LEN;
18568 fd = p->subs[idx].dfd;
18569 while (len) {
18570 if (ast_check_hangup(c)) {
18571 ast_free(mybuf);
18572 return -1;
18573 }
18574 size = len;
18575 if (size > READ_SIZE)
18576 size = READ_SIZE;
18577 fds[0].fd = fd;
18578 fds[0].events = POLLOUT | POLLPRI;
18579 fds[0].revents = 0;
18580 res = poll(fds, 1, -1);
18581 if (!res) {
18582 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18583 continue;
18584 }
18585
18586 if (fds[0].revents & POLLPRI) {
18587 ast_free(mybuf);
18588 return -1;
18589 }
18590 if (!(fds[0].revents & POLLOUT)) {
18591 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18592 continue;
18593 }
18594 res = write(fd, buf, size);
18595 if (res != size) {
18596 if (res == -1) {
18597 ast_free(mybuf);
18598 return -1;
18599 }
18600 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18601 break;
18602 }
18603 len -= size;
18604 buf += size;
18605 }
18606 ast_free(mybuf);
18607 return(0);
18608 }
18609
18610
18611 static int reload(void)
18612 {
18613 int res = 0;
18614
18615 res = setup_dahdi(1);
18616 if (res) {
18617 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18618 return -1;
18619 }
18620 return 0;
18621 }
18622
18623
18624
18625
18626
18627 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18628 .load = load_module,
18629 .unload = unload_module,
18630 .reload = reload,
18631 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18632 .nonoptreq = "res_smdi",
18633 );