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: 370017 $")
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_debug(1, "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 *cid_rings, 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 *cid_rings = 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 *cid_rings = 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 static void my_set_outgoing(void *pvt, int is_outgoing)
02264 {
02265 struct dahdi_pvt *p = pvt;
02266
02267 p->outgoing = is_outgoing;
02268 }
02269
02270 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02271 static void my_set_digital(void *pvt, int is_digital)
02272 {
02273 struct dahdi_pvt *p = pvt;
02274
02275 p->digital = is_digital;
02276 }
02277 #endif
02278
02279 #if defined(HAVE_SS7)
02280 static void my_set_inservice(void *pvt, int is_inservice)
02281 {
02282 struct dahdi_pvt *p = pvt;
02283
02284 p->inservice = is_inservice;
02285 }
02286 #endif
02287
02288 #if defined(HAVE_SS7)
02289 static void my_set_locallyblocked(void *pvt, int is_blocked)
02290 {
02291 struct dahdi_pvt *p = pvt;
02292
02293 p->locallyblocked = is_blocked;
02294 }
02295 #endif
02296
02297 #if defined(HAVE_SS7)
02298 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02299 {
02300 struct dahdi_pvt *p = pvt;
02301
02302 p->remotelyblocked = is_blocked;
02303 }
02304 #endif
02305
02306 static void my_set_ringtimeout(void *pvt, int ringt)
02307 {
02308 struct dahdi_pvt *p = pvt;
02309 p->ringt = ringt;
02310 }
02311
02312 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02313 {
02314 struct dahdi_pvt *p = pvt;
02315
02316 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02317 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02318 gettimeofday(&p->waitingfordt, NULL);
02319 ast_setstate(ast, AST_STATE_OFFHOOK);
02320 }
02321 }
02322
02323 static int my_check_waitingfordt(void *pvt)
02324 {
02325 struct dahdi_pvt *p = pvt;
02326
02327 if (p->waitingfordt.tv_usec) {
02328 return 1;
02329 }
02330
02331 return 0;
02332 }
02333
02334 static void my_set_confirmanswer(void *pvt, int flag)
02335 {
02336 struct dahdi_pvt *p = pvt;
02337 p->confirmanswer = flag;
02338 }
02339
02340 static int my_check_confirmanswer(void *pvt)
02341 {
02342 struct dahdi_pvt *p = pvt;
02343 if (p->confirmanswer) {
02344 return 1;
02345 }
02346
02347 return 0;
02348 }
02349
02350 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02351 {
02352 struct dahdi_pvt *p = pvt;
02353
02354 p->callwaiting = callwaiting_enable;
02355 }
02356
02357 static void my_cancel_cidspill(void *pvt)
02358 {
02359 struct dahdi_pvt *p = pvt;
02360
02361 ast_free(p->cidspill);
02362 p->cidspill = NULL;
02363 restore_conference(p);
02364 }
02365
02366 static int my_confmute(void *pvt, int mute)
02367 {
02368 struct dahdi_pvt *p = pvt;
02369 return dahdi_confmute(p, mute);
02370 }
02371
02372 static void my_set_pulsedial(void *pvt, int flag)
02373 {
02374 struct dahdi_pvt *p = pvt;
02375 p->pulsedial = flag;
02376 }
02377
02378 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02379 {
02380 struct dahdi_pvt *p = pvt;
02381
02382 p->owner = new_owner;
02383 }
02384
02385 static const char *my_get_orig_dialstring(void *pvt)
02386 {
02387 struct dahdi_pvt *p = pvt;
02388
02389 return p->dialstring;
02390 }
02391
02392 static void my_increase_ss_count(void)
02393 {
02394 ast_mutex_lock(&ss_thread_lock);
02395 ss_thread_count++;
02396 ast_mutex_unlock(&ss_thread_lock);
02397 }
02398
02399 static void my_decrease_ss_count(void)
02400 {
02401 ast_mutex_lock(&ss_thread_lock);
02402 ss_thread_count--;
02403 ast_cond_signal(&ss_thread_complete);
02404 ast_mutex_unlock(&ss_thread_lock);
02405 }
02406
02407 static void my_all_subchannels_hungup(void *pvt)
02408 {
02409 struct dahdi_pvt *p = pvt;
02410 int res, law;
02411
02412 p->faxhandled = 0;
02413 p->didtdd = 0;
02414
02415 if (p->dsp) {
02416 ast_dsp_free(p->dsp);
02417 p->dsp = NULL;
02418 }
02419
02420 p->law = p->law_default;
02421 law = p->law_default;
02422 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02423 if (res < 0)
02424 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02425
02426 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02427
02428 #if 1
02429 {
02430 int i;
02431 p->owner = NULL;
02432
02433 for (i = 0; i < 3; i++) {
02434 p->subs[i].owner = NULL;
02435 }
02436 }
02437 #endif
02438
02439 reset_conf(p);
02440 if (num_restart_pending == 0) {
02441 restart_monitor();
02442 }
02443 }
02444
02445 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02446
02447 static int my_conf_del(void *pvt, enum analog_sub sub)
02448 {
02449 struct dahdi_pvt *p = pvt;
02450 int x = analogsub_to_dahdisub(sub);
02451
02452 return conf_del(p, &p->subs[x], x);
02453 }
02454
02455 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02456
02457 static int my_conf_add(void *pvt, enum analog_sub sub)
02458 {
02459 struct dahdi_pvt *p = pvt;
02460 int x = analogsub_to_dahdisub(sub);
02461
02462 return conf_add(p, &p->subs[x], x, 0);
02463 }
02464
02465 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02466
02467 static int my_complete_conference_update(void *pvt, int needconference)
02468 {
02469 struct dahdi_pvt *p = pvt;
02470 int needconf = needconference;
02471 int x;
02472 int useslavenative;
02473 struct dahdi_pvt *slave = NULL;
02474
02475 useslavenative = isslavenative(p, &slave);
02476
02477
02478
02479 for (x = 0; x < MAX_SLAVES; x++) {
02480 if (p->slaves[x]) {
02481 if (useslavenative)
02482 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02483 else {
02484 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02485 needconf++;
02486 }
02487 }
02488 }
02489
02490 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02491 if (useslavenative)
02492 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02493 else {
02494 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02495 needconf++;
02496 }
02497 }
02498
02499 if (p->master) {
02500 if (isslavenative(p->master, NULL)) {
02501 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02502 } else {
02503 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02504 }
02505 }
02506 if (!needconf) {
02507
02508
02509 p->confno = -1;
02510 }
02511
02512 return 0;
02513 }
02514
02515 static int check_for_conference(struct dahdi_pvt *p);
02516
02517 static int my_check_for_conference(void *pvt)
02518 {
02519 struct dahdi_pvt *p = pvt;
02520 return check_for_conference(p);
02521 }
02522
02523 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)
02524 {
02525 struct dahdi_pvt *p = pvt;
02526 int da, db;
02527 int tchan;
02528 int tinthreeway;
02529
02530 da = analogsub_to_dahdisub(a);
02531 db = analogsub_to_dahdisub(b);
02532
02533 tchan = p->subs[da].chan;
02534 p->subs[da].chan = p->subs[db].chan;
02535 p->subs[db].chan = tchan;
02536
02537 tinthreeway = p->subs[da].inthreeway;
02538 p->subs[da].inthreeway = p->subs[db].inthreeway;
02539 p->subs[db].inthreeway = tinthreeway;
02540
02541 p->subs[da].owner = ast_a;
02542 p->subs[db].owner = ast_b;
02543
02544 if (ast_a)
02545 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02546 if (ast_b)
02547 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02548
02549 wakeup_sub(p, a);
02550 wakeup_sub(p, b);
02551
02552 return;
02553 }
02554
02555 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02556
02557 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02558 {
02559 struct dahdi_pvt *p = pvt;
02560 int dsub = analogsub_to_dahdisub(sub);
02561
02562 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02563 }
02564
02565 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02566 static int dahdi_setlaw(int dfd, int law)
02567 {
02568 int res;
02569 res = ioctl(dfd, DAHDI_SETLAW, &law);
02570 if (res)
02571 return res;
02572 return 0;
02573 }
02574 #endif
02575
02576 #if defined(HAVE_PRI)
02577 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)
02578 {
02579 struct dahdi_pvt *p = pvt;
02580 int audio;
02581 int newlaw = -1;
02582
02583 switch (p->sig) {
02584 case SIG_PRI_LIB_HANDLE_CASES:
02585 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02586
02587 break;
02588 }
02589
02590 default:
02591
02592 audio = 1;
02593 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02594 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02595 p->channel, audio, strerror(errno));
02596 }
02597 break;
02598 }
02599
02600 if (law != SIG_PRI_DEFLAW) {
02601 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02602 }
02603
02604 ast_copy_string(p->exten, exten, sizeof(p->exten));
02605
02606 switch (law) {
02607 case SIG_PRI_DEFLAW:
02608 newlaw = 0;
02609 break;
02610 case SIG_PRI_ALAW:
02611 newlaw = DAHDI_LAW_ALAW;
02612 break;
02613 case SIG_PRI_ULAW:
02614 newlaw = DAHDI_LAW_MULAW;
02615 break;
02616 }
02617 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02618 }
02619 #endif
02620
02621 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02622
02623 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633 static void my_pri_ss7_open_media(void *p)
02634 {
02635 struct dahdi_pvt *pvt = p;
02636 int res;
02637 int dfd;
02638 int set_val;
02639
02640 dfd = pvt->subs[SUB_REAL].dfd;
02641
02642
02643 set_val = 1;
02644 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02645 if (res < 0) {
02646 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02647 pvt->channel, strerror(errno));
02648 }
02649
02650
02651 res = dahdi_setlaw(dfd, pvt->law);
02652 if (res < 0) {
02653 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02654 }
02655
02656
02657 if (pvt->digital) {
02658 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02659 } else {
02660 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02661 pvt->law);
02662 }
02663 if (res < 0) {
02664 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02665 }
02666
02667 if (pvt->dsp_features && pvt->dsp) {
02668 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02669 pvt->dsp_features = 0;
02670 }
02671 }
02672 #endif
02673
02674 #if defined(HAVE_PRI)
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687 static void my_pri_dial_digits(void *p, const char *dial_string)
02688 {
02689 struct dahdi_dialoperation zo = {
02690 .op = DAHDI_DIAL_OP_APPEND,
02691 };
02692 struct dahdi_pvt *pvt = p;
02693 int res;
02694
02695 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02696 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02697 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02698 if (res) {
02699 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02700 pvt->channel, dial_string, strerror(errno));
02701 } else {
02702 pvt->dialing = 1;
02703 }
02704 }
02705 #endif
02706
02707 static int unalloc_sub(struct dahdi_pvt *p, int x);
02708
02709 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02710 {
02711 struct dahdi_pvt *p = pvt;
02712
02713 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02714 }
02715
02716 static int alloc_sub(struct dahdi_pvt *p, int x);
02717
02718 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02719 {
02720 struct dahdi_pvt *p = pvt;
02721
02722 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02723 }
02724
02725 static int has_voicemail(struct dahdi_pvt *p);
02726
02727 static int my_has_voicemail(void *pvt)
02728 {
02729 struct dahdi_pvt *p = pvt;
02730
02731 return has_voicemail(p);
02732 }
02733
02734 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02735 {
02736 struct dahdi_pvt *p = pvt;
02737 int index;
02738
02739 index = analogsub_to_dahdisub(sub);
02740
02741 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02742 }
02743
02744 static enum analog_event dahdievent_to_analogevent(int event)
02745 {
02746 enum analog_event res;
02747
02748 switch (event) {
02749 case DAHDI_EVENT_ONHOOK:
02750 res = ANALOG_EVENT_ONHOOK;
02751 break;
02752 case DAHDI_EVENT_RINGOFFHOOK:
02753 res = ANALOG_EVENT_RINGOFFHOOK;
02754 break;
02755 case DAHDI_EVENT_WINKFLASH:
02756 res = ANALOG_EVENT_WINKFLASH;
02757 break;
02758 case DAHDI_EVENT_ALARM:
02759 res = ANALOG_EVENT_ALARM;
02760 break;
02761 case DAHDI_EVENT_NOALARM:
02762 res = ANALOG_EVENT_NOALARM;
02763 break;
02764 case DAHDI_EVENT_DIALCOMPLETE:
02765 res = ANALOG_EVENT_DIALCOMPLETE;
02766 break;
02767 case DAHDI_EVENT_RINGERON:
02768 res = ANALOG_EVENT_RINGERON;
02769 break;
02770 case DAHDI_EVENT_RINGEROFF:
02771 res = ANALOG_EVENT_RINGEROFF;
02772 break;
02773 case DAHDI_EVENT_HOOKCOMPLETE:
02774 res = ANALOG_EVENT_HOOKCOMPLETE;
02775 break;
02776 case DAHDI_EVENT_PULSE_START:
02777 res = ANALOG_EVENT_PULSE_START;
02778 break;
02779 case DAHDI_EVENT_POLARITY:
02780 res = ANALOG_EVENT_POLARITY;
02781 break;
02782 case DAHDI_EVENT_RINGBEGIN:
02783 res = ANALOG_EVENT_RINGBEGIN;
02784 break;
02785 case DAHDI_EVENT_EC_DISABLED:
02786 res = ANALOG_EVENT_EC_DISABLED;
02787 break;
02788 case DAHDI_EVENT_REMOVED:
02789 res = ANALOG_EVENT_REMOVED;
02790 break;
02791 case DAHDI_EVENT_NEONMWI_ACTIVE:
02792 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02793 break;
02794 case DAHDI_EVENT_NEONMWI_INACTIVE:
02795 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02796 break;
02797 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02798 case DAHDI_EVENT_TX_CED_DETECTED:
02799 res = ANALOG_EVENT_TX_CED_DETECTED;
02800 break;
02801 case DAHDI_EVENT_RX_CED_DETECTED:
02802 res = ANALOG_EVENT_RX_CED_DETECTED;
02803 break;
02804 case DAHDI_EVENT_EC_NLP_DISABLED:
02805 res = ANALOG_EVENT_EC_NLP_DISABLED;
02806 break;
02807 case DAHDI_EVENT_EC_NLP_ENABLED:
02808 res = ANALOG_EVENT_EC_NLP_ENABLED;
02809 break;
02810 #endif
02811 case DAHDI_EVENT_PULSEDIGIT:
02812 res = ANALOG_EVENT_PULSEDIGIT;
02813 break;
02814 case DAHDI_EVENT_DTMFDOWN:
02815 res = ANALOG_EVENT_DTMFDOWN;
02816 break;
02817 case DAHDI_EVENT_DTMFUP:
02818 res = ANALOG_EVENT_DTMFUP;
02819 break;
02820 default:
02821 switch(event & 0xFFFF0000) {
02822 case DAHDI_EVENT_PULSEDIGIT:
02823 case DAHDI_EVENT_DTMFDOWN:
02824 case DAHDI_EVENT_DTMFUP:
02825
02826
02827
02828
02829 return event;
02830 }
02831
02832 res = ANALOG_EVENT_ERROR;
02833 break;
02834 }
02835
02836 return res;
02837 }
02838
02839 static inline int dahdi_wait_event(int fd);
02840
02841 static int my_wait_event(void *pvt)
02842 {
02843 struct dahdi_pvt *p = pvt;
02844
02845 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02846 }
02847
02848 static int my_get_event(void *pvt)
02849 {
02850 struct dahdi_pvt *p = pvt;
02851 int res;
02852
02853 if (p->fake_event) {
02854 res = p->fake_event;
02855 p->fake_event = 0;
02856 } else
02857 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02858
02859 return dahdievent_to_analogevent(res);
02860 }
02861
02862 static int my_is_off_hook(void *pvt)
02863 {
02864 struct dahdi_pvt *p = pvt;
02865 int res;
02866 struct dahdi_params par;
02867
02868 memset(&par, 0, sizeof(par));
02869
02870 if (p->subs[SUB_REAL].dfd > -1)
02871 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02872 else {
02873
02874 res = 0;
02875 par.rxisoffhook = 0;
02876 }
02877 if (res) {
02878 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02879 }
02880
02881 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02882
02883
02884
02885 return (par.rxbits > -1) || par.rxisoffhook;
02886 }
02887
02888 return par.rxisoffhook;
02889 }
02890
02891 static void dahdi_enable_ec(struct dahdi_pvt *p);
02892 static void dahdi_disable_ec(struct dahdi_pvt *p);
02893
02894 static int my_set_echocanceller(void *pvt, int enable)
02895 {
02896 struct dahdi_pvt *p = pvt;
02897
02898 if (enable)
02899 dahdi_enable_ec(p);
02900 else
02901 dahdi_disable_ec(p);
02902
02903 return 0;
02904 }
02905
02906 static int dahdi_ring_phone(struct dahdi_pvt *p);
02907
02908 static int my_ring(void *pvt)
02909 {
02910 struct dahdi_pvt *p = pvt;
02911
02912 return dahdi_ring_phone(p);
02913 }
02914
02915 static int my_flash(void *pvt)
02916 {
02917 struct dahdi_pvt *p = pvt;
02918 int func = DAHDI_FLASH;
02919 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02920 }
02921
02922 static inline int dahdi_set_hook(int fd, int hs);
02923
02924 static int my_off_hook(void *pvt)
02925 {
02926 struct dahdi_pvt *p = pvt;
02927 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02928 }
02929
02930 static void my_set_needringing(void *pvt, int value)
02931 {
02932 struct dahdi_pvt *p = pvt;
02933 p->subs[SUB_REAL].needringing = value;
02934 }
02935
02936 static void my_set_polarity(void *pvt, int value)
02937 {
02938 struct dahdi_pvt *p = pvt;
02939
02940 if (p->channel == CHAN_PSEUDO) {
02941 return;
02942 }
02943 p->polarity = value;
02944 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02945 }
02946
02947 static void my_start_polarityswitch(void *pvt)
02948 {
02949 struct dahdi_pvt *p = pvt;
02950
02951 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02952 my_set_polarity(pvt, 0);
02953 }
02954 }
02955
02956 static void my_answer_polarityswitch(void *pvt)
02957 {
02958 struct dahdi_pvt *p = pvt;
02959
02960 if (!p->answeronpolarityswitch) {
02961 return;
02962 }
02963
02964 my_set_polarity(pvt, 1);
02965 }
02966
02967 static void my_hangup_polarityswitch(void *pvt)
02968 {
02969 struct dahdi_pvt *p = pvt;
02970
02971 if (!p->hanguponpolarityswitch) {
02972 return;
02973 }
02974
02975 if (p->answeronpolarityswitch) {
02976 my_set_polarity(pvt, 0);
02977 } else {
02978 my_set_polarity(pvt, 1);
02979 }
02980 }
02981
02982 static int my_start(void *pvt)
02983 {
02984 struct dahdi_pvt *p = pvt;
02985 int x = DAHDI_START;
02986
02987 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02988 }
02989
02990 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02991 {
02992 int index = analogsub_to_dahdisub(sub);
02993 int res;
02994 struct dahdi_pvt *p = pvt;
02995 struct dahdi_dialoperation ddop;
02996
02997 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02998 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02999 return -1;
03000 }
03001
03002 if (sub != ANALOG_SUB_REAL) {
03003 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03004 dop->dialstr, p->channel, sub);
03005 return -1;
03006 }
03007
03008 ddop.op = DAHDI_DIAL_OP_REPLACE;
03009 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03010
03011 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03012
03013 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03014 if (res == -1) {
03015 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03016 }
03017
03018 return res;
03019 }
03020
03021 static void dahdi_train_ec(struct dahdi_pvt *p);
03022
03023 static int my_train_echocanceller(void *pvt)
03024 {
03025 struct dahdi_pvt *p = pvt;
03026
03027 dahdi_train_ec(p);
03028
03029 return 0;
03030 }
03031
03032 static int my_is_dialing(void *pvt, enum analog_sub sub)
03033 {
03034 struct dahdi_pvt *p = pvt;
03035 int index;
03036 int x;
03037
03038 index = analogsub_to_dahdisub(sub);
03039
03040 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03041 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03042 return -1;
03043 }
03044
03045 return x;
03046 }
03047
03048 static int my_on_hook(void *pvt)
03049 {
03050 struct dahdi_pvt *p = pvt;
03051 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03052 }
03053
03054 #if defined(HAVE_PRI)
03055 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03056 {
03057 struct dahdi_pvt *old_chan = chan_old;
03058 struct dahdi_pvt *new_chan = chan_new;
03059
03060 new_chan->owner = old_chan->owner;
03061 old_chan->owner = NULL;
03062 if (new_chan->owner) {
03063 new_chan->owner->tech_pvt = new_chan;
03064 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03065 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03066 old_chan->subs[SUB_REAL].owner = NULL;
03067 }
03068
03069 new_chan->dsp = old_chan->dsp;
03070 new_chan->dsp_features = old_chan->dsp_features;
03071 old_chan->dsp = NULL;
03072 old_chan->dsp_features = 0;
03073
03074
03075 new_chan->dialing = old_chan->dialing;
03076 new_chan->digital = old_chan->digital;
03077 new_chan->outgoing = old_chan->outgoing;
03078 old_chan->dialing = 0;
03079 old_chan->digital = 0;
03080 old_chan->outgoing = 0;
03081
03082
03083 new_chan->law = old_chan->law;
03084 strcpy(new_chan->dialstring, old_chan->dialstring);
03085 }
03086 #endif
03087
03088 #if defined(HAVE_PRI)
03089 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03090 {
03091 switch (tone) {
03092 case SIG_PRI_TONE_RINGTONE:
03093 return DAHDI_TONE_RINGTONE;
03094 case SIG_PRI_TONE_STUTTER:
03095 return DAHDI_TONE_STUTTER;
03096 case SIG_PRI_TONE_CONGESTION:
03097 return DAHDI_TONE_CONGESTION;
03098 case SIG_PRI_TONE_DIALTONE:
03099 return DAHDI_TONE_DIALTONE;
03100 case SIG_PRI_TONE_DIALRECALL:
03101 return DAHDI_TONE_DIALRECALL;
03102 case SIG_PRI_TONE_INFO:
03103 return DAHDI_TONE_INFO;
03104 case SIG_PRI_TONE_BUSY:
03105 return DAHDI_TONE_BUSY;
03106 default:
03107 return -1;
03108 }
03109 }
03110 #endif
03111
03112 #if defined(HAVE_PRI)
03113 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03114 {
03115 int x;
03116
03117 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03118 switch (x) {
03119 case DAHDI_EVENT_NONE:
03120 break;
03121 case DAHDI_EVENT_ALARM:
03122 case DAHDI_EVENT_NOALARM:
03123 if (sig_pri_is_alarm_ignored(pri)) {
03124 break;
03125 }
03126
03127 default:
03128 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03129 event2str(x), x, pri->span);
03130 break;
03131 }
03132
03133 switch (x) {
03134 case DAHDI_EVENT_ALARM:
03135 pri_event_alarm(pri, index, 0);
03136 break;
03137 case DAHDI_EVENT_NOALARM:
03138 pri_event_noalarm(pri, index, 0);
03139 break;
03140 default:
03141 break;
03142 }
03143 }
03144 #endif
03145
03146 #if defined(HAVE_PRI)
03147 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03148 {
03149 struct dahdi_pvt *p = pvt;
03150
03151 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03152 }
03153 #endif
03154
03155 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03167 {
03168 struct dahdi_pvt *p = pvt;
03169
03170 ast_copy_string(p->cid_num,
03171 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03172 sizeof(p->cid_num));
03173 ast_copy_string(p->cid_name,
03174 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03175 sizeof(p->cid_name));
03176 ast_copy_string(p->cid_subaddr,
03177 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03178 sizeof(p->cid_subaddr));
03179 p->cid_ton = caller->id.number.plan;
03180 p->callingpres = ast_party_id_presentation(&caller->id);
03181 if (caller->id.tag) {
03182 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03183 }
03184 ast_copy_string(p->cid_ani,
03185 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03186 sizeof(p->cid_ani));
03187 p->cid_ani2 = caller->ani2;
03188 }
03189 #endif
03190
03191 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202 static void my_set_dnid(void *pvt, const char *dnid)
03203 {
03204 struct dahdi_pvt *p = pvt;
03205
03206 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03207 }
03208 #endif
03209
03210 #if defined(HAVE_PRI)
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221 static void my_set_rdnis(void *pvt, const char *rdnis)
03222 {
03223 struct dahdi_pvt *p = pvt;
03224
03225 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03226 }
03227 #endif
03228
03229 #if defined(HAVE_PRI)
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03255 {
03256 char *dial;
03257 struct dahdi_pvt *pvt;
03258 AST_DECLARE_APP_ARGS(args,
03259 AST_APP_ARG(tech);
03260 AST_APP_ARG(group);
03261
03262
03263
03264 );
03265
03266 pvt = priv;
03267 dial = ast_strdupa(pvt->dialstring);
03268 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03269 if (!args.tech) {
03270 ast_copy_string(buf, pvt->dialstring, buf_size);
03271 return;
03272 }
03273 if (!args.group) {
03274
03275 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03276 return;
03277 }
03278 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03279
03280
03281 ast_copy_string(buf, pvt->dialstring, buf_size);
03282 return;
03283 }
03284
03285 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03286 }
03287 #endif
03288
03289 #if defined(HAVE_PRI)
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03302 {
03303 unsigned idx;
03304 unsigned num_b_chans;
03305 unsigned in_use;
03306 unsigned in_alarm;
03307 enum ast_device_state new_state;
03308
03309
03310 num_b_chans = 0;
03311 in_use = 0;
03312 in_alarm = 1;
03313 for (idx = pri->numchans; idx--;) {
03314 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03315
03316 ++num_b_chans;
03317 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03318 ++in_use;
03319 }
03320 if (!pri->pvts[idx]->inalarm) {
03321
03322 in_alarm = 0;
03323 }
03324 }
03325 }
03326
03327
03328 if (in_alarm) {
03329 new_state = AST_DEVICE_UNAVAILABLE;
03330 } else {
03331 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03332 }
03333 if (pri->congestion_devstate != new_state) {
03334 pri->congestion_devstate = new_state;
03335 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03336 }
03337 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03338
03339 if (in_alarm) {
03340 new_state = AST_DEVICE_UNAVAILABLE;
03341 } else if (!in_use) {
03342 new_state = AST_DEVICE_NOT_INUSE;
03343 } else if (!pri->user_busy_threshold) {
03344 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03345 } else {
03346 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03347 : AST_DEVICE_BUSY;
03348 }
03349 if (pri->threshold_devstate != new_state) {
03350 pri->threshold_devstate = new_state;
03351 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03352 }
03353 #endif
03354 }
03355 #endif
03356
03357 #if defined(HAVE_PRI)
03358
03359
03360
03361
03362
03363
03364
03365 static void my_module_ref(void)
03366 {
03367 ast_module_ref(ast_module_info->self);
03368 }
03369 #endif
03370
03371 #if defined(HAVE_PRI)
03372
03373
03374
03375
03376
03377
03378
03379 static void my_module_unref(void)
03380 {
03381 ast_module_unref(ast_module_info->self);
03382 }
03383 #endif
03384
03385 #if defined(HAVE_PRI)
03386 #if defined(HAVE_PRI_CALL_WAITING)
03387 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03388 #endif
03389 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03390
03391 static struct sig_pri_callback dahdi_pri_callbacks =
03392 {
03393 .handle_dchan_exception = my_handle_dchan_exception,
03394 .play_tone = my_pri_play_tone,
03395 .set_echocanceller = my_set_echocanceller,
03396 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03397 .lock_private = my_lock_private,
03398 .unlock_private = my_unlock_private,
03399 .new_ast_channel = my_new_pri_ast_channel,
03400 .fixup_chans = my_pri_fixup_chans,
03401 .set_alarm = my_set_alarm,
03402 .set_dialing = my_set_dialing,
03403 .set_outgoing = my_set_outgoing,
03404 .set_digital = my_set_digital,
03405 .set_callerid = my_set_callerid,
03406 .set_dnid = my_set_dnid,
03407 .set_rdnis = my_set_rdnis,
03408 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03409 #if defined(HAVE_PRI_CALL_WAITING)
03410 .init_config = my_pri_init_config,
03411 #endif
03412 .get_orig_dialstring = my_get_orig_dialstring,
03413 .make_cc_dialstring = my_pri_make_cc_dialstring,
03414 .update_span_devstate = dahdi_pri_update_span_devstate,
03415 .module_ref = my_module_ref,
03416 .module_unref = my_module_unref,
03417 .dial_digits = my_pri_dial_digits,
03418 .open_media = my_pri_ss7_open_media,
03419 .ami_channel_event = my_ami_channel_event,
03420 };
03421 #endif
03422
03423 #if defined(HAVE_SS7)
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03435 {
03436 int event;
03437
03438 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03439 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03440 linkset->span, which);
03441 return;
03442 }
03443 switch (event) {
03444 case DAHDI_EVENT_NONE:
03445 break;
03446 case DAHDI_EVENT_ALARM:
03447 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03448 event2str(event), event, linkset->span, which);
03449 sig_ss7_link_alarm(linkset, which);
03450 break;
03451 case DAHDI_EVENT_NOALARM:
03452 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03453 event2str(event), event, linkset->span, which);
03454 sig_ss7_link_noalarm(linkset, which);
03455 break;
03456 default:
03457 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03458 event2str(event), event, linkset->span, which);
03459 break;
03460 }
03461 }
03462 #endif
03463
03464 #if defined(HAVE_SS7)
03465 static void my_ss7_set_loopback(void *pvt, int enable)
03466 {
03467 struct dahdi_pvt *p = pvt;
03468
03469 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03470 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03471 strerror(errno));
03472 }
03473 }
03474 #endif
03475
03476 #if defined(HAVE_SS7)
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491 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)
03492 {
03493 struct dahdi_pvt *p = pvt;
03494 int audio;
03495 int newlaw;
03496
03497
03498 audio = 1;
03499 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03500 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03501 p->channel, audio, strerror(errno));
03502
03503 if (law != SIG_SS7_DEFLAW) {
03504 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03505 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03506 }
03507
03508 ast_copy_string(p->exten, exten, sizeof(p->exten));
03509
03510 newlaw = -1;
03511 switch (law) {
03512 case SIG_SS7_DEFLAW:
03513 newlaw = 0;
03514 break;
03515 case SIG_SS7_ALAW:
03516 newlaw = DAHDI_LAW_ALAW;
03517 break;
03518 case SIG_SS7_ULAW:
03519 newlaw = DAHDI_LAW_MULAW;
03520 break;
03521 }
03522 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03523 }
03524 #endif
03525
03526 #if defined(HAVE_SS7)
03527 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03528 {
03529 switch (tone) {
03530 case SIG_SS7_TONE_RINGTONE:
03531 return DAHDI_TONE_RINGTONE;
03532 case SIG_SS7_TONE_STUTTER:
03533 return DAHDI_TONE_STUTTER;
03534 case SIG_SS7_TONE_CONGESTION:
03535 return DAHDI_TONE_CONGESTION;
03536 case SIG_SS7_TONE_DIALTONE:
03537 return DAHDI_TONE_DIALTONE;
03538 case SIG_SS7_TONE_DIALRECALL:
03539 return DAHDI_TONE_DIALRECALL;
03540 case SIG_SS7_TONE_INFO:
03541 return DAHDI_TONE_INFO;
03542 case SIG_SS7_TONE_BUSY:
03543 return DAHDI_TONE_BUSY;
03544 default:
03545 return -1;
03546 }
03547 }
03548 #endif
03549
03550 #if defined(HAVE_SS7)
03551 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03552 {
03553 struct dahdi_pvt *p = pvt;
03554
03555 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03556 }
03557 #endif
03558
03559 #if defined(HAVE_SS7)
03560 static struct sig_ss7_callback dahdi_ss7_callbacks =
03561 {
03562 .lock_private = my_lock_private,
03563 .unlock_private = my_unlock_private,
03564
03565 .set_echocanceller = my_set_echocanceller,
03566 .set_loopback = my_ss7_set_loopback,
03567
03568 .new_ast_channel = my_new_ss7_ast_channel,
03569 .play_tone = my_ss7_play_tone,
03570
03571 .handle_link_exception = my_handle_link_exception,
03572 .set_alarm = my_set_alarm,
03573 .set_dialing = my_set_dialing,
03574 .set_outgoing = my_set_outgoing,
03575 .set_digital = my_set_digital,
03576 .set_inservice = my_set_inservice,
03577 .set_locallyblocked = my_set_locallyblocked,
03578 .set_remotelyblocked = my_set_remotelyblocked,
03579 .set_callerid = my_set_callerid,
03580 .set_dnid = my_set_dnid,
03581 .open_media = my_pri_ss7_open_media,
03582 };
03583 #endif
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603 static void notify_message(char *mailbox_full, int thereornot)
03604 {
03605 char s[sizeof(mwimonitornotify) + 80];
03606 struct ast_event *event;
03607 char *mailbox, *context;
03608
03609
03610 context = mailbox = ast_strdupa(mailbox_full);
03611 strsep(&context, "@");
03612 if (ast_strlen_zero(context))
03613 context = "default";
03614
03615 if (!(event = ast_event_new(AST_EVENT_MWI,
03616 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03617 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03618 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03619 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03620 AST_EVENT_IE_END))) {
03621 return;
03622 }
03623
03624 ast_event_queue_and_cache(event);
03625
03626 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03627 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03628 ast_safe_system(s);
03629 }
03630 }
03631
03632 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03633 {
03634 struct dahdi_pvt *p = pvt;
03635
03636 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03637 return;
03638
03639 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03640 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03641 notify_message(p->mailbox, 1);
03642 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03643 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03644 notify_message(p->mailbox, 0);
03645 }
03646
03647
03648 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03649 ast_hangup(chan);
03650 return;
03651 }
03652 }
03653
03654 static int my_have_progressdetect(void *pvt)
03655 {
03656 struct dahdi_pvt *p = pvt;
03657
03658 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03659 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03660 return 1;
03661 } else {
03662
03663 return 0;
03664 }
03665 }
03666
03667 static struct analog_callback dahdi_analog_callbacks =
03668 {
03669 .play_tone = my_play_tone,
03670 .get_event = my_get_event,
03671 .wait_event = my_wait_event,
03672 .is_off_hook = my_is_off_hook,
03673 .set_echocanceller = my_set_echocanceller,
03674 .ring = my_ring,
03675 .flash = my_flash,
03676 .off_hook = my_off_hook,
03677 .dial_digits = my_dial_digits,
03678 .train_echocanceller = my_train_echocanceller,
03679 .on_hook = my_on_hook,
03680 .is_dialing = my_is_dialing,
03681 .allocate_sub = my_allocate_sub,
03682 .unallocate_sub = my_unallocate_sub,
03683 .swap_subs = my_swap_subchannels,
03684 .has_voicemail = my_has_voicemail,
03685 .check_for_conference = my_check_for_conference,
03686 .conf_add = my_conf_add,
03687 .conf_del = my_conf_del,
03688 .complete_conference_update = my_complete_conference_update,
03689 .start = my_start,
03690 .all_subchannels_hungup = my_all_subchannels_hungup,
03691 .lock_private = my_lock_private,
03692 .unlock_private = my_unlock_private,
03693 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03694 .handle_dtmf = my_handle_dtmf,
03695 .wink = my_wink,
03696 .new_ast_channel = my_new_analog_ast_channel,
03697 .dsp_set_digitmode = my_dsp_set_digitmode,
03698 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03699 .send_callerid = my_send_callerid,
03700 .callwait = my_callwait,
03701 .stop_callwait = my_stop_callwait,
03702 .get_callerid = my_get_callerid,
03703 .start_cid_detect = my_start_cid_detect,
03704 .stop_cid_detect = my_stop_cid_detect,
03705 .handle_notify_message = my_handle_notify_message,
03706 .increase_ss_count = my_increase_ss_count,
03707 .decrease_ss_count = my_decrease_ss_count,
03708 .distinctive_ring = my_distinctive_ring,
03709 .set_linear_mode = my_set_linear_mode,
03710 .set_inthreeway = my_set_inthreeway,
03711 .get_and_handle_alarms = my_get_and_handle_alarms,
03712 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03713 .get_sub_fd = my_get_sub_fd,
03714 .set_cadence = my_set_cadence,
03715 .set_alarm = my_set_alarm,
03716 .set_dialing = my_set_dialing,
03717 .set_outgoing = my_set_outgoing,
03718 .set_ringtimeout = my_set_ringtimeout,
03719 .set_waitingfordt = my_set_waitingfordt,
03720 .check_waitingfordt = my_check_waitingfordt,
03721 .set_confirmanswer = my_set_confirmanswer,
03722 .check_confirmanswer = my_check_confirmanswer,
03723 .set_callwaiting = my_set_callwaiting,
03724 .cancel_cidspill = my_cancel_cidspill,
03725 .confmute = my_confmute,
03726 .set_pulsedial = my_set_pulsedial,
03727 .set_new_owner = my_set_new_owner,
03728 .get_orig_dialstring = my_get_orig_dialstring,
03729 .set_needringing = my_set_needringing,
03730 .set_polarity = my_set_polarity,
03731 .start_polarityswitch = my_start_polarityswitch,
03732 .answer_polarityswitch = my_answer_polarityswitch,
03733 .hangup_polarityswitch = my_hangup_polarityswitch,
03734 .have_progressdetect = my_have_progressdetect,
03735 };
03736
03737
03738 static struct dahdi_pvt *round_robin[32];
03739
03740 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03741 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03742 {
03743 int res;
03744 if (p->subs[SUB_REAL].owner == ast)
03745 res = 0;
03746 else if (p->subs[SUB_CALLWAIT].owner == ast)
03747 res = 1;
03748 else if (p->subs[SUB_THREEWAY].owner == ast)
03749 res = 2;
03750 else {
03751 res = -1;
03752 if (!nullok)
03753 ast_log(LOG_WARNING,
03754 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03755 ast ? ast->name : "", p->channel, fname, line);
03756 }
03757 return res;
03758 }
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03776 {
03777 for (;;) {
03778 if (!pvt->subs[sub_idx].owner) {
03779
03780 break;
03781 }
03782 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03783
03784 break;
03785 }
03786
03787 DEADLOCK_AVOIDANCE(&pvt->lock);
03788 }
03789 }
03790
03791 static void wakeup_sub(struct dahdi_pvt *p, int a)
03792 {
03793 dahdi_lock_sub_owner(p, a);
03794 if (p->subs[a].owner) {
03795 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03796 ast_channel_unlock(p->subs[a].owner);
03797 }
03798 }
03799
03800 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03801 {
03802 for (;;) {
03803 if (p->owner) {
03804 if (ast_channel_trylock(p->owner)) {
03805 DEADLOCK_AVOIDANCE(&p->lock);
03806 } else {
03807 ast_queue_frame(p->owner, f);
03808 ast_channel_unlock(p->owner);
03809 break;
03810 }
03811 } else
03812 break;
03813 }
03814 }
03815
03816 static void handle_clear_alarms(struct dahdi_pvt *p)
03817 {
03818 #if defined(HAVE_PRI)
03819 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03820 return;
03821 }
03822 #endif
03823
03824 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03825 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03826 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03827 }
03828 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03829 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03830 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03831 }
03832 }
03833
03834 #ifdef HAVE_OPENR2
03835
03836 static int dahdi_r2_answer(struct dahdi_pvt *p)
03837 {
03838 int res = 0;
03839
03840
03841
03842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03843 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03844 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03845 if (!double_answer) {
03846
03847
03848 res = openr2_chan_answer_call(p->r2chan);
03849 } else if (wants_double_answer) {
03850 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03851 } else {
03852 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03853 }
03854 #else
03855 res = openr2_chan_answer_call(p->r2chan);
03856 #endif
03857 return res;
03858 }
03859
03860
03861
03862
03863 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03864 {
03865 openr2_calling_party_category_t cat;
03866 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03867 struct dahdi_pvt *p = c->tech_pvt;
03868 if (ast_strlen_zero(catstr)) {
03869 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03870 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03871 return p->mfcr2_category;
03872 }
03873 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03874 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03875 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03876 return p->mfcr2_category;
03877 }
03878 ast_debug(1, "Using category %s\n", catstr);
03879 return cat;
03880 }
03881
03882 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03883 {
03884 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03885 ast_mutex_lock(&p->lock);
03886 if (p->mfcr2call) {
03887 ast_mutex_unlock(&p->lock);
03888
03889
03890
03891
03892
03893 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03894 return;
03895 }
03896 p->mfcr2call = 1;
03897
03898 p->cid_name[0] = '\0';
03899 p->cid_num[0] = '\0';
03900 p->cid_subaddr[0] = '\0';
03901 p->rdnis[0] = '\0';
03902 p->exten[0] = '\0';
03903 p->mfcr2_ani_index = '\0';
03904 p->mfcr2_dnis_index = '\0';
03905 p->mfcr2_dnis_matched = 0;
03906 p->mfcr2_answer_pending = 0;
03907 p->mfcr2_call_accepted = 0;
03908 ast_mutex_unlock(&p->lock);
03909 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03910 }
03911
03912 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03913 {
03914 int res;
03915 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03916 ast_mutex_lock(&p->lock);
03917 p->inalarm = alarm ? 1 : 0;
03918 if (p->inalarm) {
03919 res = get_alarms(p);
03920 handle_alarms(p, res);
03921 } else {
03922 handle_clear_alarms(p);
03923 }
03924 ast_mutex_unlock(&p->lock);
03925 }
03926
03927 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03928 {
03929 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03930 }
03931
03932 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03933 {
03934 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03935 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03936 if (p->owner) {
03937 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03938 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03939 }
03940 ast_mutex_lock(&p->lock);
03941 p->mfcr2call = 0;
03942 ast_mutex_unlock(&p->lock);
03943 }
03944
03945 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03946 {
03947 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03948 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03949 p->channel, openr2_proto_get_disconnect_string(cause));
03950
03951 openr2_chan_set_idle(p->r2chan);
03952 ast_mutex_lock(&p->lock);
03953 p->mfcr2call = 0;
03954 ast_mutex_unlock(&p->lock);
03955 }
03956 }
03957
03958 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03959 {
03960 struct dahdi_pvt *p;
03961 struct ast_channel *c;
03962 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03963 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03964 openr2_proto_get_category_string(category));
03965 p = openr2_chan_get_client_data(r2chan);
03966
03967 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03968 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03969 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03970 return;
03971 }
03972 ast_mutex_lock(&p->lock);
03973 p->mfcr2_recvd_category = category;
03974
03975 if (!p->use_callerid) {
03976 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03977 p->cid_num[0] = 0;
03978 p->cid_name[0] = 0;
03979 }
03980
03981 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03982 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03983 p->exten[0] = 's';
03984 p->exten[1] = 0;
03985 }
03986 ast_mutex_unlock(&p->lock);
03987 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03988 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03989 p->channel, p->exten, p->context);
03990 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03991 return;
03992 }
03993 if (!p->mfcr2_accept_on_offer) {
03994
03995 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03996 if (c) {
03997
03998
03999
04000 return;
04001 }
04002 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04003 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04004 } else if (p->mfcr2_charge_calls) {
04005 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04006 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04007 } else {
04008 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04009 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04010 }
04011 }
04012
04013 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04014 {
04015 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04016 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04017 ast_mutex_lock(&p->lock);
04018 p->mfcr2call = 0;
04019 ast_mutex_unlock(&p->lock);
04020 }
04021
04022 static void dahdi_enable_ec(struct dahdi_pvt *p);
04023 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04024 {
04025 struct dahdi_pvt *p = NULL;
04026 struct ast_channel *c = NULL;
04027 p = openr2_chan_get_client_data(r2chan);
04028 dahdi_enable_ec(p);
04029 p->mfcr2_call_accepted = 1;
04030
04031 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04032 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04033
04034
04035
04036
04037 if (!p->mfcr2_accept_on_offer) {
04038 openr2_chan_disable_read(r2chan);
04039 if (p->mfcr2_answer_pending) {
04040 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04041 dahdi_r2_answer(p);
04042 }
04043 return;
04044 }
04045 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04046 if (c) {
04047
04048
04049 openr2_chan_disable_read(r2chan);
04050 return;
04051 }
04052 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04053
04054 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04055 return;
04056 }
04057
04058 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04059 p->subs[SUB_REAL].needringing = 1;
04060 p->dialing = 0;
04061
04062 openr2_chan_disable_read(r2chan);
04063 }
04064
04065 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04066 {
04067 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04068 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04069 p->subs[SUB_REAL].needanswer = 1;
04070 }
04071
04072 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04073 {
04074
04075 }
04076
04077 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04078 {
04079 switch (cause) {
04080 case OR2_CAUSE_BUSY_NUMBER:
04081 return AST_CAUSE_BUSY;
04082 case OR2_CAUSE_NETWORK_CONGESTION:
04083 return AST_CAUSE_CONGESTION;
04084 case OR2_CAUSE_OUT_OF_ORDER:
04085 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04086 case OR2_CAUSE_UNALLOCATED_NUMBER:
04087 return AST_CAUSE_UNREGISTERED;
04088 case OR2_CAUSE_NO_ANSWER:
04089 return AST_CAUSE_NO_ANSWER;
04090 case OR2_CAUSE_NORMAL_CLEARING:
04091 return AST_CAUSE_NORMAL_CLEARING;
04092 case OR2_CAUSE_UNSPECIFIED:
04093 default:
04094 return AST_CAUSE_NOTDEFINED;
04095 }
04096 }
04097
04098 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04099 {
04100 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04101 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04102 ast_mutex_lock(&p->lock);
04103 if (!p->owner) {
04104 ast_mutex_unlock(&p->lock);
04105
04106 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04107 return;
04108 }
04109
04110
04111 if (p->owner->_state == AST_STATE_UP) {
04112 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04113 ast_mutex_unlock(&p->lock);
04114 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04115
04116 switch (cause) {
04117 case OR2_CAUSE_BUSY_NUMBER:
04118 p->subs[SUB_REAL].needbusy = 1;
04119 break;
04120 case OR2_CAUSE_NETWORK_CONGESTION:
04121 case OR2_CAUSE_OUT_OF_ORDER:
04122 case OR2_CAUSE_UNALLOCATED_NUMBER:
04123 case OR2_CAUSE_NO_ANSWER:
04124 case OR2_CAUSE_UNSPECIFIED:
04125 case OR2_CAUSE_NORMAL_CLEARING:
04126 p->subs[SUB_REAL].needcongestion = 1;
04127 break;
04128 default:
04129 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04130 }
04131 ast_mutex_unlock(&p->lock);
04132 } else {
04133 ast_mutex_unlock(&p->lock);
04134
04135
04136 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04137 }
04138 }
04139
04140 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04141 {
04142 switch (level) {
04143 case OR2_LOG_NOTICE:
04144 ast_verbose("%s", logmessage);
04145 break;
04146 case OR2_LOG_WARNING:
04147 ast_log(LOG_WARNING, "%s", logmessage);
04148 break;
04149 case OR2_LOG_ERROR:
04150 ast_log(LOG_ERROR, "%s", logmessage);
04151 break;
04152 case OR2_LOG_STACK_TRACE:
04153 case OR2_LOG_MF_TRACE:
04154 case OR2_LOG_CAS_TRACE:
04155 case OR2_LOG_DEBUG:
04156 case OR2_LOG_EX_DEBUG:
04157 ast_log(LOG_DEBUG, "%s", logmessage);
04158 break;
04159 default:
04160 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04161 ast_log(LOG_DEBUG, "%s", logmessage);
04162 break;
04163 }
04164 }
04165
04166 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04167 {
04168 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04169 ast_mutex_lock(&p->lock);
04170 p->remotelyblocked = 1;
04171 ast_mutex_unlock(&p->lock);
04172 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04173 }
04174
04175 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04176 {
04177 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04178 ast_mutex_lock(&p->lock);
04179 p->remotelyblocked = 0;
04180 ast_mutex_unlock(&p->lock);
04181 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04182 }
04183
04184 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04185 __attribute__((format (printf, 3, 0)));
04186 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04187 {
04188 #define CONTEXT_TAG "Context - "
04189 char logmsg[256];
04190 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04191 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04192 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04193 dahdi_r2_write_log(level, completemsg);
04194 #undef CONTEXT_TAG
04195 }
04196
04197 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04198 __attribute__((format (printf, 3, 0)));
04199 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04200 {
04201 #define CHAN_TAG "Chan "
04202 char logmsg[256];
04203 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04204 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04205 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04206 dahdi_r2_write_log(level, completemsg);
04207 }
04208
04209 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04210 {
04211 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04212
04213 if (p->immediate) {
04214 return 0;
04215 }
04216 p->exten[p->mfcr2_dnis_index] = digit;
04217 p->rdnis[p->mfcr2_dnis_index] = digit;
04218 p->mfcr2_dnis_index++;
04219 p->exten[p->mfcr2_dnis_index] = 0;
04220 p->rdnis[p->mfcr2_dnis_index] = 0;
04221
04222 if ((p->mfcr2_dnis_matched ||
04223 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04224 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04225 return 0;
04226 }
04227
04228 return 1;
04229 }
04230
04231 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04232 {
04233 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04234 p->cid_num[p->mfcr2_ani_index] = digit;
04235 p->cid_name[p->mfcr2_ani_index] = digit;
04236 p->mfcr2_ani_index++;
04237 p->cid_num[p->mfcr2_ani_index] = 0;
04238 p->cid_name[p->mfcr2_ani_index] = 0;
04239 }
04240
04241 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04242 {
04243 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04244 }
04245
04246 static openr2_event_interface_t dahdi_r2_event_iface = {
04247 .on_call_init = dahdi_r2_on_call_init,
04248 .on_call_offered = dahdi_r2_on_call_offered,
04249 .on_call_accepted = dahdi_r2_on_call_accepted,
04250 .on_call_answered = dahdi_r2_on_call_answered,
04251 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04252 .on_call_end = dahdi_r2_on_call_end,
04253 .on_call_read = dahdi_r2_on_call_read,
04254 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04255 .on_os_error = dahdi_r2_on_os_error,
04256 .on_protocol_error = dahdi_r2_on_protocol_error,
04257 .on_line_blocked = dahdi_r2_on_line_blocked,
04258 .on_line_idle = dahdi_r2_on_line_idle,
04259
04260 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04261 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04262 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04263
04264 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04265 };
04266
04267 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04268 {
04269 return AST_ALAW(sample);
04270 }
04271
04272 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04273 {
04274 return AST_LIN2A(sample);
04275 }
04276
04277 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04278 dahdi_r2_alaw_to_linear,
04279 dahdi_r2_linear_to_alaw
04280 };
04281
04282 #endif
04283
04284 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04285 {
04286 int tchan;
04287 int tinthreeway;
04288 struct ast_channel *towner;
04289
04290 ast_debug(1, "Swapping %d and %d\n", a, b);
04291
04292 tchan = p->subs[a].chan;
04293 towner = p->subs[a].owner;
04294 tinthreeway = p->subs[a].inthreeway;
04295
04296 p->subs[a].chan = p->subs[b].chan;
04297 p->subs[a].owner = p->subs[b].owner;
04298 p->subs[a].inthreeway = p->subs[b].inthreeway;
04299
04300 p->subs[b].chan = tchan;
04301 p->subs[b].owner = towner;
04302 p->subs[b].inthreeway = tinthreeway;
04303
04304 if (p->subs[a].owner)
04305 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04306 if (p->subs[b].owner)
04307 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04308 wakeup_sub(p, a);
04309 wakeup_sub(p, b);
04310 }
04311
04312 static int dahdi_open(char *fn)
04313 {
04314 int fd;
04315 int isnum;
04316 int chan = 0;
04317 int bs;
04318 int x;
04319 isnum = 1;
04320 for (x = 0; x < strlen(fn); x++) {
04321 if (!isdigit(fn[x])) {
04322 isnum = 0;
04323 break;
04324 }
04325 }
04326 if (isnum) {
04327 chan = atoi(fn);
04328 if (chan < 1) {
04329 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04330 return -1;
04331 }
04332 fn = "/dev/dahdi/channel";
04333 }
04334 fd = open(fn, O_RDWR | O_NONBLOCK);
04335 if (fd < 0) {
04336 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04337 return -1;
04338 }
04339 if (chan) {
04340 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04341 x = errno;
04342 close(fd);
04343 errno = x;
04344 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04345 return -1;
04346 }
04347 }
04348 bs = READ_SIZE;
04349 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04350 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04351 x = errno;
04352 close(fd);
04353 errno = x;
04354 return -1;
04355 }
04356 return fd;
04357 }
04358
04359 static void dahdi_close(int fd)
04360 {
04361 if (fd > 0)
04362 close(fd);
04363 }
04364
04365 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04366 {
04367 dahdi_close(chan_pvt->subs[sub_num].dfd);
04368 chan_pvt->subs[sub_num].dfd = -1;
04369 }
04370
04371 #if defined(HAVE_PRI)
04372 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04373 {
04374 dahdi_close(pri->pri.fds[fd_num]);
04375 pri->pri.fds[fd_num] = -1;
04376 }
04377 #endif
04378
04379 #if defined(HAVE_SS7)
04380 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04381 {
04382 dahdi_close(ss7->ss7.fds[fd_num]);
04383 ss7->ss7.fds[fd_num] = -1;
04384 }
04385 #endif
04386
04387 static int dahdi_setlinear(int dfd, int linear)
04388 {
04389 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04390 }
04391
04392
04393 static int alloc_sub(struct dahdi_pvt *p, int x)
04394 {
04395 struct dahdi_bufferinfo bi;
04396 int res;
04397 if (p->subs[x].dfd >= 0) {
04398 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04399 return -1;
04400 }
04401
04402 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04403 if (p->subs[x].dfd <= -1) {
04404 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04405 return -1;
04406 }
04407
04408 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04409 if (!res) {
04410 bi.txbufpolicy = p->buf_policy;
04411 bi.rxbufpolicy = p->buf_policy;
04412 bi.numbufs = p->buf_no;
04413 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04414 if (res < 0) {
04415 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04416 }
04417 } else
04418 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04419
04420 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04421 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04422 dahdi_close_sub(p, x);
04423 p->subs[x].dfd = -1;
04424 return -1;
04425 }
04426 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04427 return 0;
04428 }
04429
04430 static int unalloc_sub(struct dahdi_pvt *p, int x)
04431 {
04432 if (!x) {
04433 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04434 return -1;
04435 }
04436 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04437 dahdi_close_sub(p, x);
04438 p->subs[x].linear = 0;
04439 p->subs[x].chan = 0;
04440 p->subs[x].owner = NULL;
04441 p->subs[x].inthreeway = 0;
04442 p->polarity = POLARITY_IDLE;
04443 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04444 return 0;
04445 }
04446
04447 static int digit_to_dtmfindex(char digit)
04448 {
04449 if (isdigit(digit))
04450 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04451 else if (digit >= 'A' && digit <= 'D')
04452 return DAHDI_TONE_DTMF_A + (digit - 'A');
04453 else if (digit >= 'a' && digit <= 'd')
04454 return DAHDI_TONE_DTMF_A + (digit - 'a');
04455 else if (digit == '*')
04456 return DAHDI_TONE_DTMF_s;
04457 else if (digit == '#')
04458 return DAHDI_TONE_DTMF_p;
04459 else
04460 return -1;
04461 }
04462
04463 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04464 {
04465 struct dahdi_pvt *pvt;
04466 int idx;
04467 int dtmf = -1;
04468 int res;
04469
04470 pvt = chan->tech_pvt;
04471
04472 ast_mutex_lock(&pvt->lock);
04473
04474 idx = dahdi_get_index(chan, pvt, 0);
04475
04476 if ((idx != SUB_REAL) || !pvt->owner)
04477 goto out;
04478
04479 #ifdef HAVE_PRI
04480 switch (pvt->sig) {
04481 case SIG_PRI_LIB_HANDLE_CASES:
04482 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04483 if (!res)
04484 goto out;
04485 break;
04486 default:
04487 break;
04488 }
04489 #endif
04490 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04491 goto out;
04492
04493 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04494 struct dahdi_dialoperation zo = {
04495 .op = DAHDI_DIAL_OP_APPEND,
04496 };
04497
04498 zo.dialstr[0] = 'T';
04499 zo.dialstr[1] = digit;
04500 zo.dialstr[2] = '\0';
04501 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04502 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04503 chan->name, digit, strerror(errno));
04504 else
04505 pvt->dialing = 1;
04506 } else {
04507 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04508 chan->name, digit);
04509 pvt->dialing = 1;
04510 pvt->begindigit = digit;
04511 }
04512
04513 out:
04514 ast_mutex_unlock(&pvt->lock);
04515
04516 return 0;
04517 }
04518
04519 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04520 {
04521 struct dahdi_pvt *pvt;
04522 int res = 0;
04523 int idx;
04524 int x;
04525
04526 pvt = chan->tech_pvt;
04527
04528 ast_mutex_lock(&pvt->lock);
04529
04530 idx = dahdi_get_index(chan, pvt, 0);
04531
04532 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04533 goto out;
04534
04535 #ifdef HAVE_PRI
04536
04537 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04538 goto out;
04539 }
04540 #endif
04541
04542 if (pvt->begindigit) {
04543 x = -1;
04544 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04545 chan->name, digit);
04546 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04547 pvt->dialing = 0;
04548 pvt->begindigit = 0;
04549 }
04550
04551 out:
04552 ast_mutex_unlock(&pvt->lock);
04553
04554 return res;
04555 }
04556
04557 static const char * const events[] = {
04558 "No event",
04559 "On hook",
04560 "Ring/Answered",
04561 "Wink/Flash",
04562 "Alarm",
04563 "No more alarm",
04564 "HDLC Abort",
04565 "HDLC Overrun",
04566 "HDLC Bad FCS",
04567 "Dial Complete",
04568 "Ringer On",
04569 "Ringer Off",
04570 "Hook Transition Complete",
04571 "Bits Changed",
04572 "Pulse Start",
04573 "Timer Expired",
04574 "Timer Ping",
04575 "Polarity Reversal",
04576 "Ring Begin",
04577 };
04578
04579 static struct {
04580 int alarm;
04581 char *name;
04582 } alarms[] = {
04583 { DAHDI_ALARM_RED, "Red Alarm" },
04584 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04585 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04586 { DAHDI_ALARM_RECOVER, "Recovering" },
04587 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04588 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04589 { DAHDI_ALARM_NONE, "None" },
04590 };
04591
04592 static char *alarm2str(int alm)
04593 {
04594 int x;
04595 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04596 if (alarms[x].alarm & alm)
04597 return alarms[x].name;
04598 }
04599 return alm ? "Unknown Alarm" : "No Alarm";
04600 }
04601
04602 static const char *event2str(int event)
04603 {
04604 static char buf[256];
04605 if ((event < (ARRAY_LEN(events))) && (event > -1))
04606 return events[event];
04607 sprintf(buf, "Event %d", event);
04608 return buf;
04609 }
04610
04611 static char *dahdi_sig2str(int sig)
04612 {
04613 static char buf[256];
04614 switch (sig) {
04615 case SIG_EM:
04616 return "E & M Immediate";
04617 case SIG_EMWINK:
04618 return "E & M Wink";
04619 case SIG_EM_E1:
04620 return "E & M E1";
04621 case SIG_FEATD:
04622 return "Feature Group D (DTMF)";
04623 case SIG_FEATDMF:
04624 return "Feature Group D (MF)";
04625 case SIG_FEATDMF_TA:
04626 return "Feature Groud D (MF) Tandem Access";
04627 case SIG_FEATB:
04628 return "Feature Group B (MF)";
04629 case SIG_E911:
04630 return "E911 (MF)";
04631 case SIG_FGC_CAMA:
04632 return "FGC/CAMA (Dialpulse)";
04633 case SIG_FGC_CAMAMF:
04634 return "FGC/CAMA (MF)";
04635 case SIG_FXSLS:
04636 return "FXS Loopstart";
04637 case SIG_FXSGS:
04638 return "FXS Groundstart";
04639 case SIG_FXSKS:
04640 return "FXS Kewlstart";
04641 case SIG_FXOLS:
04642 return "FXO Loopstart";
04643 case SIG_FXOGS:
04644 return "FXO Groundstart";
04645 case SIG_FXOKS:
04646 return "FXO Kewlstart";
04647 case SIG_PRI:
04648 return "ISDN PRI";
04649 case SIG_BRI:
04650 return "ISDN BRI Point to Point";
04651 case SIG_BRI_PTMP:
04652 return "ISDN BRI Point to MultiPoint";
04653 case SIG_SS7:
04654 return "SS7";
04655 case SIG_MFCR2:
04656 return "MFC/R2";
04657 case SIG_SF:
04658 return "SF (Tone) Immediate";
04659 case SIG_SFWINK:
04660 return "SF (Tone) Wink";
04661 case SIG_SF_FEATD:
04662 return "SF (Tone) with Feature Group D (DTMF)";
04663 case SIG_SF_FEATDMF:
04664 return "SF (Tone) with Feature Group D (MF)";
04665 case SIG_SF_FEATB:
04666 return "SF (Tone) with Feature Group B (MF)";
04667 case 0:
04668 return "Pseudo";
04669 default:
04670 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04671 return buf;
04672 }
04673 }
04674
04675 #define sig2str dahdi_sig2str
04676
04677 static int analog_lib_handles(int signalling, int radio, int oprmode)
04678 {
04679 switch (signalling) {
04680 case SIG_FXOLS:
04681 case SIG_FXOGS:
04682 case SIG_FXOKS:
04683 case SIG_FXSLS:
04684 case SIG_FXSGS:
04685 case SIG_FXSKS:
04686 case SIG_EMWINK:
04687 case SIG_EM:
04688 case SIG_EM_E1:
04689 case SIG_FEATD:
04690 case SIG_FEATDMF:
04691 case SIG_E911:
04692 case SIG_FGC_CAMA:
04693 case SIG_FGC_CAMAMF:
04694 case SIG_FEATB:
04695 case SIG_SFWINK:
04696 case SIG_SF:
04697 case SIG_SF_FEATD:
04698 case SIG_SF_FEATDMF:
04699 case SIG_FEATDMF_TA:
04700 case SIG_SF_FEATB:
04701 break;
04702 default:
04703
04704 return 0;
04705 }
04706
04707 if (radio)
04708 return 0;
04709
04710 if (oprmode)
04711 return 0;
04712
04713 return 1;
04714 }
04715
04716 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04717 {
04718
04719
04720 struct dahdi_confinfo zi;
04721
04722 memset(&zi, 0, sizeof(zi));
04723 zi.chan = 0;
04724
04725 if (slavechannel > 0) {
04726
04727 zi.confmode = DAHDI_CONF_DIGITALMON;
04728 zi.confno = slavechannel;
04729 } else {
04730 if (!idx) {
04731
04732 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04733 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04734 } else
04735 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04736 zi.confno = p->confno;
04737 }
04738 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04739 return 0;
04740 if (c->dfd < 0)
04741 return 0;
04742 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04743 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04744 return -1;
04745 }
04746 if (slavechannel < 1) {
04747 p->confno = zi.confno;
04748 }
04749 c->curconf = zi;
04750 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04751 return 0;
04752 }
04753
04754 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04755 {
04756
04757 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04758 return 1;
04759
04760 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04761 return 1;
04762 return 0;
04763 }
04764
04765 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04766 {
04767 struct dahdi_confinfo zi;
04768 if (
04769 (c->dfd < 0) ||
04770
04771 !isourconf(p, c)
04772
04773 ) return 0;
04774 memset(&zi, 0, sizeof(zi));
04775 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04776 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04777 return -1;
04778 }
04779 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04780 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04781 return 0;
04782 }
04783
04784 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04785 {
04786 int x;
04787 int useslavenative;
04788 struct dahdi_pvt *slave = NULL;
04789
04790 useslavenative = 1;
04791
04792 for (x = 0; x < 3; x++) {
04793
04794
04795 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04796 useslavenative = 0;
04797 }
04798
04799
04800 if (useslavenative) {
04801 for (x = 0; x < MAX_SLAVES; x++) {
04802 if (p->slaves[x]) {
04803 if (slave) {
04804
04805
04806 slave = NULL;
04807 useslavenative = 0;
04808 break;
04809 } else {
04810
04811 slave = p->slaves[x];
04812 }
04813 }
04814 }
04815 }
04816
04817 if (!slave)
04818 useslavenative = 0;
04819 else if (slave->law != p->law) {
04820 useslavenative = 0;
04821 slave = NULL;
04822 }
04823 if (out)
04824 *out = slave;
04825 return useslavenative;
04826 }
04827
04828 static int reset_conf(struct dahdi_pvt *p)
04829 {
04830 p->confno = -1;
04831 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04832 if (p->subs[SUB_REAL].dfd > -1) {
04833 struct dahdi_confinfo zi;
04834
04835 memset(&zi, 0, sizeof(zi));
04836 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04837 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04838 }
04839 return 0;
04840 }
04841
04842 static int update_conf(struct dahdi_pvt *p)
04843 {
04844 int needconf = 0;
04845 int x;
04846 int useslavenative;
04847 struct dahdi_pvt *slave = NULL;
04848
04849 useslavenative = isslavenative(p, &slave);
04850
04851 for (x = 0; x < 3; x++) {
04852
04853 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04854 conf_add(p, &p->subs[x], x, 0);
04855 needconf++;
04856 } else {
04857 conf_del(p, &p->subs[x], x);
04858 }
04859 }
04860
04861
04862 for (x = 0; x < MAX_SLAVES; x++) {
04863 if (p->slaves[x]) {
04864 if (useslavenative)
04865 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04866 else {
04867 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04868 needconf++;
04869 }
04870 }
04871 }
04872
04873 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04874 if (useslavenative)
04875 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04876 else {
04877 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04878 needconf++;
04879 }
04880 }
04881
04882 if (p->master) {
04883 if (isslavenative(p->master, NULL)) {
04884 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04885 } else {
04886 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04887 }
04888 }
04889 if (!needconf) {
04890
04891
04892 p->confno = -1;
04893 }
04894 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04895 return 0;
04896 }
04897
04898 static void dahdi_enable_ec(struct dahdi_pvt *p)
04899 {
04900 int res;
04901 if (!p)
04902 return;
04903 if (p->echocanon) {
04904 ast_debug(1, "Echo cancellation already on\n");
04905 return;
04906 }
04907 if (p->digital) {
04908 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04909 return;
04910 }
04911 if (p->echocancel.head.tap_length) {
04912 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04913 switch (p->sig) {
04914 #if defined(HAVE_PRI)
04915 case SIG_PRI_LIB_HANDLE_CASES:
04916 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04917
04918
04919
04920
04921 return;
04922 }
04923
04924 #endif
04925 #if defined(HAVE_SS7)
04926 case SIG_SS7:
04927 #endif
04928 {
04929 int x = 1;
04930
04931 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04932 if (res)
04933 ast_log(LOG_WARNING,
04934 "Unable to enable audio mode on channel %d (%s)\n",
04935 p->channel, strerror(errno));
04936 }
04937 break;
04938 default:
04939 break;
04940 }
04941 #endif
04942 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04943 if (res) {
04944 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04945 } else {
04946 p->echocanon = 1;
04947 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04948 }
04949 } else
04950 ast_debug(1, "No echo cancellation requested\n");
04951 }
04952
04953 static void dahdi_train_ec(struct dahdi_pvt *p)
04954 {
04955 int x;
04956 int res;
04957
04958 if (p && p->echocanon && p->echotraining) {
04959 x = p->echotraining;
04960 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04961 if (res)
04962 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04963 else
04964 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04965 } else {
04966 ast_debug(1, "No echo training requested\n");
04967 }
04968 }
04969
04970 static void dahdi_disable_ec(struct dahdi_pvt *p)
04971 {
04972 int res;
04973
04974 if (p->echocanon) {
04975 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04976
04977 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04978
04979 if (res)
04980 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04981 else
04982 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04983 }
04984
04985 p->echocanon = 0;
04986 }
04987
04988
04989 static int drc_sample(int sample, float drc)
04990 {
04991 float neg;
04992 float shallow, steep;
04993 float max = SHRT_MAX;
04994
04995 neg = (sample < 0 ? -1 : 1);
04996 steep = drc*sample;
04997 shallow = neg*(max-max/drc)+(float)sample/drc;
04998 if (abs(steep) < abs(shallow)) {
04999 sample = steep;
05000 }
05001 else {
05002 sample = shallow;
05003 }
05004
05005 return sample;
05006 }
05007
05008
05009 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05010 {
05011 int j;
05012 int k;
05013
05014 float linear_gain = pow(10.0, gain / 20.0);
05015
05016 switch (law) {
05017 case DAHDI_LAW_ALAW:
05018 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05019 if (gain || drc) {
05020 k = AST_ALAW(j);
05021 if (drc) {
05022 k = drc_sample(k, drc);
05023 }
05024 k = (float)k*linear_gain;
05025 if (k > 32767) k = 32767;
05026 if (k < -32767) k = -32767;
05027 g->txgain[j] = AST_LIN2A(k);
05028 } else {
05029 g->txgain[j] = j;
05030 }
05031 }
05032 break;
05033 case DAHDI_LAW_MULAW:
05034 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05035 if (gain || drc) {
05036 k = AST_MULAW(j);
05037 if (drc) {
05038 k = drc_sample(k, drc);
05039 }
05040 k = (float)k*linear_gain;
05041 if (k > 32767) k = 32767;
05042 if (k < -32767) k = -32767;
05043 g->txgain[j] = AST_LIN2MU(k);
05044
05045 } else {
05046 g->txgain[j] = j;
05047 }
05048 }
05049 break;
05050 }
05051 }
05052
05053 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05054 {
05055 int j;
05056 int k;
05057 float linear_gain = pow(10.0, gain / 20.0);
05058
05059 switch (law) {
05060 case DAHDI_LAW_ALAW:
05061 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05062 if (gain || drc) {
05063 k = AST_ALAW(j);
05064 if (drc) {
05065 k = drc_sample(k, drc);
05066 }
05067 k = (float)k*linear_gain;
05068 if (k > 32767) k = 32767;
05069 if (k < -32767) k = -32767;
05070 g->rxgain[j] = AST_LIN2A(k);
05071 } else {
05072 g->rxgain[j] = j;
05073 }
05074 }
05075 break;
05076 case DAHDI_LAW_MULAW:
05077 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05078 if (gain || drc) {
05079 k = AST_MULAW(j);
05080 if (drc) {
05081 k = drc_sample(k, drc);
05082 }
05083 k = (float)k*linear_gain;
05084 if (k > 32767) k = 32767;
05085 if (k < -32767) k = -32767;
05086 g->rxgain[j] = AST_LIN2MU(k);
05087 } else {
05088 g->rxgain[j] = j;
05089 }
05090 }
05091 break;
05092 }
05093 }
05094
05095 static int set_actual_txgain(int fd, float gain, float drc, int law)
05096 {
05097 struct dahdi_gains g;
05098 int res;
05099
05100 memset(&g, 0, sizeof(g));
05101 res = ioctl(fd, DAHDI_GETGAINS, &g);
05102 if (res) {
05103 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05104 return res;
05105 }
05106
05107 fill_txgain(&g, gain, drc, law);
05108
05109 return ioctl(fd, DAHDI_SETGAINS, &g);
05110 }
05111
05112 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05113 {
05114 struct dahdi_gains g;
05115 int res;
05116
05117 memset(&g, 0, sizeof(g));
05118 res = ioctl(fd, DAHDI_GETGAINS, &g);
05119 if (res) {
05120 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05121 return res;
05122 }
05123
05124 fill_rxgain(&g, gain, drc, law);
05125
05126 return ioctl(fd, DAHDI_SETGAINS, &g);
05127 }
05128
05129 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05130 {
05131 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05132 }
05133
05134 static int bump_gains(struct dahdi_pvt *p)
05135 {
05136 int res;
05137
05138
05139 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05140 if (res) {
05141 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05142 return -1;
05143 }
05144
05145 return 0;
05146 }
05147
05148 static int restore_gains(struct dahdi_pvt *p)
05149 {
05150 int res;
05151
05152 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05153 if (res) {
05154 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05155 return -1;
05156 }
05157
05158 return 0;
05159 }
05160
05161 static inline int dahdi_set_hook(int fd, int hs)
05162 {
05163 int x, res;
05164
05165 x = hs;
05166 res = ioctl(fd, DAHDI_HOOK, &x);
05167
05168 if (res < 0) {
05169 if (errno == EINPROGRESS)
05170 return 0;
05171 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05172
05173 }
05174
05175 return res;
05176 }
05177
05178 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05179 {
05180 int x, res;
05181
05182 x = muted;
05183 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05184 switch (p->sig) {
05185 #if defined(HAVE_PRI)
05186 case SIG_PRI_LIB_HANDLE_CASES:
05187 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05188
05189 break;
05190 }
05191
05192 #endif
05193 #if defined(HAVE_SS7)
05194 case SIG_SS7:
05195 #endif
05196 {
05197 int y = 1;
05198
05199 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05200 if (res)
05201 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05202 p->channel, strerror(errno));
05203 }
05204 break;
05205 default:
05206 break;
05207 }
05208 #endif
05209 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05210 if (res < 0)
05211 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05212 return res;
05213 }
05214
05215 static int save_conference(struct dahdi_pvt *p)
05216 {
05217 struct dahdi_confinfo c;
05218 int res;
05219 if (p->saveconf.confmode) {
05220 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05221 return -1;
05222 }
05223 p->saveconf.chan = 0;
05224 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05225 if (res) {
05226 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05227 p->saveconf.confmode = 0;
05228 return -1;
05229 }
05230 memset(&c, 0, sizeof(c));
05231 c.confmode = DAHDI_CONF_NORMAL;
05232 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05233 if (res) {
05234 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05235 return -1;
05236 }
05237 ast_debug(1, "Disabled conferencing\n");
05238 return 0;
05239 }
05240
05241 static int restore_conference(struct dahdi_pvt *p)
05242 {
05243 int res;
05244 if (p->saveconf.confmode) {
05245 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05246 p->saveconf.confmode = 0;
05247 if (res) {
05248 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05249 return -1;
05250 }
05251 ast_debug(1, "Restored conferencing\n");
05252 }
05253 return 0;
05254 }
05255
05256 static int send_cwcidspill(struct dahdi_pvt *p)
05257 {
05258 p->callwaitcas = 0;
05259 p->cidcwexpire = 0;
05260 p->cid_suppress_expire = 0;
05261 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05262 return -1;
05263 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05264
05265 p->cidlen += READ_SIZE * 4;
05266 p->cidpos = 0;
05267 send_callerid(p);
05268 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05269 return 0;
05270 }
05271
05272 static int has_voicemail(struct dahdi_pvt *p)
05273 {
05274 int new_msgs;
05275 struct ast_event *event;
05276 char *mailbox, *context;
05277
05278 mailbox = context = ast_strdupa(p->mailbox);
05279 strsep(&context, "@");
05280 if (ast_strlen_zero(context))
05281 context = "default";
05282
05283 event = ast_event_get_cached(AST_EVENT_MWI,
05284 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05285 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05286 AST_EVENT_IE_END);
05287
05288 if (event) {
05289 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05290 ast_event_destroy(event);
05291 } else
05292 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05293
05294 return new_msgs;
05295 }
05296
05297
05298
05299 static int send_callerid(struct dahdi_pvt *p)
05300 {
05301
05302 int res;
05303
05304 if (p->subs[SUB_REAL].linear) {
05305 p->subs[SUB_REAL].linear = 0;
05306 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05307 }
05308 while (p->cidpos < p->cidlen) {
05309 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05310 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05311 if (res < 0) {
05312 if (errno == EAGAIN)
05313 return 0;
05314 else {
05315 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05316 return -1;
05317 }
05318 }
05319 if (!res)
05320 return 0;
05321 p->cidpos += res;
05322 }
05323 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05324 ast_free(p->cidspill);
05325 p->cidspill = NULL;
05326 if (p->callwaitcas) {
05327
05328 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05329 p->cid_suppress_expire = p->cidcwexpire;
05330 } else
05331 restore_conference(p);
05332 return 0;
05333 }
05334
05335 static int dahdi_callwait(struct ast_channel *ast)
05336 {
05337 struct dahdi_pvt *p = ast->tech_pvt;
05338 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05339 if (p->cidspill) {
05340 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05341 ast_free(p->cidspill);
05342 }
05343
05344
05345
05346
05347
05348 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05349 return -1;
05350 save_conference(p);
05351
05352 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05353 if (!p->callwaitrings && p->callwaitingcallerid) {
05354 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05355 p->callwaitcas = 1;
05356 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05357 } else {
05358 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05359 p->callwaitcas = 0;
05360 p->cidlen = 2400 + READ_SIZE * 4;
05361 }
05362 p->cidpos = 0;
05363 send_callerid(p);
05364
05365 return 0;
05366 }
05367
05368 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05369 {
05370 struct dahdi_pvt *p = ast->tech_pvt;
05371 int x, res, mysig;
05372 char dest[256];
05373
05374 ast_mutex_lock(&p->lock);
05375 ast_copy_string(dest, rdest, sizeof(dest));
05376 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05377 if ((ast->_state == AST_STATE_BUSY)) {
05378 p->subs[SUB_REAL].needbusy = 1;
05379 ast_mutex_unlock(&p->lock);
05380 return 0;
05381 }
05382 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05383 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05384 ast_mutex_unlock(&p->lock);
05385 return -1;
05386 }
05387 p->waitingfordt.tv_sec = 0;
05388 p->dialednone = 0;
05389 if ((p->radio || (p->oprmode < 0)))
05390 {
05391
05392 ast_setstate(ast, AST_STATE_UP);
05393 ast_mutex_unlock(&p->lock);
05394 return 0;
05395 }
05396 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05397 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05398 if (res)
05399 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05400 p->outgoing = 1;
05401
05402 if (IS_DIGITAL(ast->transfercapability)){
05403 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05404 } else {
05405 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05406 }
05407
05408 #ifdef HAVE_PRI
05409 if (dahdi_sig_pri_lib_handles(p->sig)) {
05410 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05411 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05412 ast_mutex_unlock(&p->lock);
05413 return res;
05414 }
05415 #endif
05416
05417 #if defined(HAVE_SS7)
05418 if (p->sig == SIG_SS7) {
05419 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05420 ast_mutex_unlock(&p->lock);
05421 return res;
05422 }
05423 #endif
05424
05425
05426 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05427 p->callwaitrings = 0;
05428 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05429 ast_mutex_unlock(&p->lock);
05430 return res;
05431 }
05432
05433 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05434 switch (mysig) {
05435 case 0:
05436
05437 ast_setstate(ast, AST_STATE_UP);
05438 break;
05439 case SIG_MFCR2:
05440 break;
05441 default:
05442 ast_debug(1, "not yet implemented\n");
05443 ast_mutex_unlock(&p->lock);
05444 return -1;
05445 }
05446
05447 #ifdef HAVE_OPENR2
05448 if (p->mfcr2) {
05449 openr2_calling_party_category_t chancat;
05450 int callres = 0;
05451 char *c, *l;
05452
05453
05454 p->dialdest[0] = '\0';
05455
05456 c = strchr(dest, '/');
05457 if (c) {
05458 c++;
05459 } else {
05460 c = "";
05461 }
05462 if (!p->hidecallerid) {
05463 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05464 } else {
05465 l = NULL;
05466 }
05467 if (strlen(c) < p->stripmsd) {
05468 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05469 ast_mutex_unlock(&p->lock);
05470 return -1;
05471 }
05472 p->dialing = 1;
05473 chancat = dahdi_r2_get_channel_category(ast);
05474 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05475 if (-1 == callres) {
05476 ast_mutex_unlock(&p->lock);
05477 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05478 return -1;
05479 }
05480 p->mfcr2_call_accepted = 0;
05481 p->mfcr2_progress = 0;
05482 ast_setstate(ast, AST_STATE_DIALING);
05483 }
05484 #endif
05485 ast_mutex_unlock(&p->lock);
05486 return 0;
05487 }
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05505 {
05506 struct dahdi_pvt *cur;
05507
05508 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05509
05510
05511 for (cur = iflist; cur; cur = cur->next) {
05512 if (pvt->channel < cur->channel) {
05513
05514 pvt->prev = cur->prev;
05515 pvt->next = cur;
05516 if (cur->prev) {
05517
05518 cur->prev->next = pvt;
05519 } else {
05520
05521 iflist = pvt;
05522 }
05523 cur->prev = pvt;
05524 return;
05525 }
05526 }
05527
05528
05529 pvt->prev = ifend;
05530 pvt->next = NULL;
05531 if (ifend) {
05532 ifend->next = pvt;
05533 }
05534 ifend = pvt;
05535 if (!iflist) {
05536
05537 iflist = pvt;
05538 }
05539 }
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05555 {
05556
05557 if (pvt->prev) {
05558 pvt->prev->next = pvt->next;
05559 } else if (iflist == pvt) {
05560
05561 iflist = pvt->next;
05562 }
05563
05564
05565 if (pvt->next) {
05566 pvt->next->prev = pvt->prev;
05567 } else if (ifend == pvt) {
05568
05569 ifend = pvt->prev;
05570 }
05571
05572
05573 pvt->which_iflist = DAHDI_IFLIST_NONE;
05574 pvt->prev = NULL;
05575 pvt->next = NULL;
05576 }
05577
05578 #if defined(HAVE_PRI)
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05596 {
05597 struct dahdi_pvt *cur;
05598
05599 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05600
05601
05602 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05603 if (pvt->channel < cur->channel) {
05604
05605 pvt->prev = cur->prev;
05606 pvt->next = cur;
05607 if (cur->prev) {
05608
05609 cur->prev->next = pvt;
05610 } else {
05611
05612 pri->no_b_chan_iflist = pvt;
05613 }
05614 cur->prev = pvt;
05615 return;
05616 }
05617 }
05618
05619
05620 pvt->prev = pri->no_b_chan_end;
05621 pvt->next = NULL;
05622 if (pri->no_b_chan_end) {
05623 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05624 }
05625 pri->no_b_chan_end = pvt;
05626 if (!pri->no_b_chan_iflist) {
05627
05628 pri->no_b_chan_iflist = pvt;
05629 }
05630 }
05631 #endif
05632
05633 #if defined(HAVE_PRI)
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05649 {
05650
05651 if (pvt->prev) {
05652 pvt->prev->next = pvt->next;
05653 } else if (pri->no_b_chan_iflist == pvt) {
05654
05655 pri->no_b_chan_iflist = pvt->next;
05656 }
05657
05658
05659 if (pvt->next) {
05660 pvt->next->prev = pvt->prev;
05661 } else if (pri->no_b_chan_end == pvt) {
05662
05663 pri->no_b_chan_end = pvt->prev;
05664 }
05665
05666
05667 pvt->which_iflist = DAHDI_IFLIST_NONE;
05668 pvt->prev = NULL;
05669 pvt->next = NULL;
05670 }
05671 #endif
05672
05673 #if defined(HAVE_PRI)
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05684 {
05685 unsigned idx;
05686 struct sig_pri_span *pri;
05687
05688 pri = pvt->pri;
05689 if (!pri) {
05690
05691 return;
05692 }
05693 ast_mutex_lock(&pri->lock);
05694 for (idx = 0; idx < pri->numchans; ++idx) {
05695 if (pri->pvts[idx] == pvt->sig_pvt) {
05696 pri->pvts[idx] = NULL;
05697 ast_mutex_unlock(&pri->lock);
05698 return;
05699 }
05700 }
05701 ast_mutex_unlock(&pri->lock);
05702 }
05703 #endif
05704
05705 #if defined(HAVE_SS7)
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05716 {
05717 unsigned idx;
05718 struct sig_ss7_linkset *ss7;
05719
05720 ss7 = pvt->ss7;
05721 if (!ss7) {
05722
05723 return;
05724 }
05725 ast_mutex_lock(&ss7->lock);
05726 for (idx = 0; idx < ss7->numchans; ++idx) {
05727 if (ss7->pvts[idx] == pvt->sig_pvt) {
05728 ss7->pvts[idx] = NULL;
05729 ast_mutex_unlock(&ss7->lock);
05730 return;
05731 }
05732 }
05733 ast_mutex_unlock(&ss7->lock);
05734 }
05735 #endif
05736
05737 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05738 {
05739 if (cur->next && cur->next->span == cur->span) {
05740 return cur->next;
05741 } else if (cur->prev && cur->prev->span == cur->span) {
05742 return cur->prev;
05743 }
05744
05745 return NULL;
05746 }
05747
05748 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05749 {
05750 struct dahdi_pvt *p = pvt;
05751
05752 if (p->manages_span_alarms) {
05753 struct dahdi_pvt *next = find_next_iface_in_span(p);
05754 if (next) {
05755 next->manages_span_alarms = 1;
05756 }
05757 }
05758
05759
05760 #if defined(HAVE_PRI)
05761 dahdi_unlink_pri_pvt(p);
05762 #endif
05763 #if defined(HAVE_SS7)
05764 dahdi_unlink_ss7_pvt(p);
05765 #endif
05766 switch (pvt->which_iflist) {
05767 case DAHDI_IFLIST_NONE:
05768 break;
05769 case DAHDI_IFLIST_MAIN:
05770 dahdi_iflist_extract(p);
05771 break;
05772 #if defined(HAVE_PRI)
05773 case DAHDI_IFLIST_NO_B_CHAN:
05774 if (p->pri) {
05775 dahdi_nobch_extract(p->pri, p);
05776 }
05777 break;
05778 #endif
05779 }
05780
05781 if (p->sig_pvt) {
05782 if (analog_lib_handles(p->sig, 0, 0)) {
05783 analog_delete(p->sig_pvt);
05784 }
05785 switch (p->sig) {
05786 #if defined(HAVE_PRI)
05787 case SIG_PRI_LIB_HANDLE_CASES:
05788 sig_pri_chan_delete(p->sig_pvt);
05789 break;
05790 #endif
05791 #if defined(HAVE_SS7)
05792 case SIG_SS7:
05793 sig_ss7_chan_delete(p->sig_pvt);
05794 break;
05795 #endif
05796 default:
05797 break;
05798 }
05799 }
05800 ast_free(p->cidspill);
05801 if (p->use_smdi)
05802 ast_smdi_interface_unref(p->smdi_iface);
05803 if (p->mwi_event_sub)
05804 ast_event_unsubscribe(p->mwi_event_sub);
05805 if (p->vars) {
05806 ast_variables_destroy(p->vars);
05807 }
05808 if (p->cc_params) {
05809 ast_cc_config_params_destroy(p->cc_params);
05810 }
05811 ast_mutex_destroy(&p->lock);
05812 dahdi_close_sub(p, SUB_REAL);
05813 if (p->owner)
05814 p->owner->tech_pvt = NULL;
05815 ast_free(p);
05816 }
05817
05818 static void destroy_channel(struct dahdi_pvt *cur, int now)
05819 {
05820 int i;
05821
05822 if (!now) {
05823
05824 if (cur->owner) {
05825 return;
05826 }
05827 for (i = 0; i < 3; i++) {
05828 if (cur->subs[i].owner) {
05829 return;
05830 }
05831 }
05832 }
05833 destroy_dahdi_pvt(cur);
05834 }
05835
05836 static void destroy_all_channels(void)
05837 {
05838 int chan;
05839 #if defined(HAVE_PRI)
05840 unsigned span;
05841 struct sig_pri_span *pri;
05842 #endif
05843 struct dahdi_pvt *p;
05844
05845 while (num_restart_pending) {
05846 usleep(1);
05847 }
05848
05849 ast_mutex_lock(&iflock);
05850
05851 while (iflist) {
05852 p = iflist;
05853
05854 chan = p->channel;
05855 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05856 {
05857 char db_chan_name[20];
05858 char db_answer[5];
05859 char state;
05860 int why = -1;
05861
05862 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05863 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05864 sscanf(db_answer, "%1c:%30d", &state, &why);
05865 }
05866 if (!why) {
05867
05868 ast_db_del(db_chan_name, SRVST_DBKEY);
05869 }
05870 }
05871 #endif
05872
05873 destroy_dahdi_pvt(p);
05874 ast_verb(3, "Unregistered channel %d\n", chan);
05875 }
05876 ifcount = 0;
05877 ast_mutex_unlock(&iflock);
05878
05879 #if defined(HAVE_PRI)
05880
05881 for (span = 0; span < NUM_SPANS; ++span) {
05882 if (!pris[span].dchannels[0]) {
05883 break;
05884 }
05885 pri = &pris[span].pri;
05886 ast_mutex_lock(&pri->lock);
05887 while (pri->no_b_chan_iflist) {
05888 p = pri->no_b_chan_iflist;
05889
05890
05891 destroy_dahdi_pvt(p);
05892 }
05893 ast_mutex_unlock(&pri->lock);
05894 }
05895 #endif
05896 }
05897
05898 #if defined(HAVE_PRI)
05899 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05900
05901 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05902 {
05903
05904 struct dahdi_pvt *p;
05905
05906 if (ast_strlen_zero(digits)) {
05907 ast_debug(1, "No digit string sent to application!\n");
05908 return -1;
05909 }
05910
05911 p = (struct dahdi_pvt *)chan->tech_pvt;
05912
05913 if (!p) {
05914 ast_debug(1, "Unable to find technology private\n");
05915 return -1;
05916 }
05917
05918 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05919
05920 return 0;
05921 }
05922 #endif
05923
05924 #if defined(HAVE_PRI)
05925 #if defined(HAVE_PRI_PROG_W_CAUSE)
05926 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05927
05928 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05929 {
05930
05931 struct dahdi_pvt *pvt;
05932 char *parse;
05933 int res;
05934 AST_DECLARE_APP_ARGS(args,
05935 AST_APP_ARG(destination);
05936 AST_APP_ARG(original);
05937 AST_APP_ARG(reason);
05938 );
05939
05940 if (ast_strlen_zero(data)) {
05941 ast_log(LOG_DEBUG, "No data sent to application!\n");
05942 return -1;
05943 }
05944 if (chan->tech != &dahdi_tech) {
05945 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05946 return -1;
05947 }
05948 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05949 if (!pvt) {
05950 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05951 return -1;
05952 }
05953 switch (pvt->sig) {
05954 case SIG_PRI_LIB_HANDLE_CASES:
05955 break;
05956 default:
05957 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05958 chan->name);
05959 return -1;
05960 }
05961
05962 parse = ast_strdupa(data);
05963 AST_STANDARD_APP_ARGS(args, parse);
05964
05965 if (ast_strlen_zero(args.destination)) {
05966 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05967 return -1;
05968 }
05969
05970 if (ast_strlen_zero(args.original)) {
05971 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05972 args.original = NULL;
05973 }
05974
05975 if (ast_strlen_zero(args.reason)) {
05976 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05977 args.reason = NULL;
05978 }
05979
05980 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05981 args.destination, args.original, args.reason);
05982 if (!res) {
05983
05984
05985
05986
05987 ast_safe_sleep(chan, 5000);
05988 }
05989
05990 return -1;
05991 }
05992 #endif
05993 #endif
05994
05995 #if defined(HAVE_OPENR2)
05996 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05997
05998 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05999 {
06000
06001 openr2_call_mode_t accept_mode;
06002 int res, timeout, maxloops;
06003 struct ast_frame *f;
06004 struct dahdi_pvt *p;
06005 char *parse;
06006 AST_DECLARE_APP_ARGS(args,
06007 AST_APP_ARG(charge);
06008 );
06009
06010 if (ast_strlen_zero(data)) {
06011 ast_log(LOG_DEBUG, "No data sent to application!\n");
06012 return -1;
06013 }
06014
06015 if (chan->tech != &dahdi_tech) {
06016 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06017 return -1;
06018 }
06019
06020 p = (struct dahdi_pvt *)chan->tech_pvt;
06021 if (!p) {
06022 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06023 return -1;
06024 }
06025
06026 parse = ast_strdupa(data);
06027 AST_STANDARD_APP_ARGS(args, parse);
06028
06029 if (ast_strlen_zero(args.charge)) {
06030 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06031 return -1;
06032 }
06033
06034 ast_mutex_lock(&p->lock);
06035 if (!p->mfcr2 || !p->mfcr2call) {
06036 ast_mutex_unlock(&p->lock);
06037 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06038 return -1;
06039 }
06040
06041 if (p->mfcr2_call_accepted) {
06042 ast_mutex_unlock(&p->lock);
06043 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06044 return 0;
06045 }
06046 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06047 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06048 ast_mutex_unlock(&p->lock);
06049 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06050 return -1;
06051 }
06052 ast_mutex_unlock(&p->lock);
06053
06054 res = 0;
06055 timeout = 100;
06056 maxloops = 50;
06057
06058 while (maxloops > 0) {
06059 maxloops--;
06060 if (ast_check_hangup(chan)) {
06061 break;
06062 }
06063 res = ast_waitfor(chan, timeout);
06064 if (res < 0) {
06065 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06066 res = -1;
06067 break;
06068 }
06069 if (res == 0) {
06070 continue;
06071 }
06072 f = ast_read(chan);
06073 if (!f) {
06074 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06075 res = -1;
06076 break;
06077 }
06078 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06079 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06080 ast_frfree(f);
06081 res = -1;
06082 break;
06083 }
06084 ast_frfree(f);
06085 ast_mutex_lock(&p->lock);
06086 if (p->mfcr2_call_accepted) {
06087 ast_mutex_unlock(&p->lock);
06088 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06089 break;
06090 }
06091 ast_mutex_unlock(&p->lock);
06092 }
06093 if (res == -1) {
06094 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06095 }
06096 return res;
06097 }
06098
06099 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06100 {
06101 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06102 switch (cause) {
06103 case AST_CAUSE_USER_BUSY:
06104 case AST_CAUSE_CALL_REJECTED:
06105 case AST_CAUSE_INTERWORKING:
06106 r2cause = OR2_CAUSE_BUSY_NUMBER;
06107 break;
06108
06109 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06110 case AST_CAUSE_SWITCH_CONGESTION:
06111 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06112 break;
06113
06114 case AST_CAUSE_UNALLOCATED:
06115 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06116 break;
06117
06118 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06119 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06120 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06121 break;
06122
06123 case AST_CAUSE_NO_ANSWER:
06124 case AST_CAUSE_NO_USER_RESPONSE:
06125 r2cause = OR2_CAUSE_NO_ANSWER;
06126 break;
06127
06128 default:
06129 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06130 break;
06131 }
06132 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06133 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06134 return r2cause;
06135 }
06136 #endif
06137
06138 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06139 {
06140 if (p->bufferoverrideinuse) {
06141
06142 struct dahdi_bufferinfo bi = {
06143 .txbufpolicy = p->buf_policy,
06144 .rxbufpolicy = p->buf_policy,
06145 .bufsize = p->bufsize,
06146 .numbufs = p->buf_no
06147 };
06148 int bpres;
06149
06150 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06151 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06152 }
06153 p->bufferoverrideinuse = 0;
06154 return bpres;
06155 }
06156
06157 return -1;
06158 }
06159
06160 static int dahdi_hangup(struct ast_channel *ast)
06161 {
06162 int res = 0;
06163 int idx,x;
06164 int law;
06165
06166 struct dahdi_pvt *p = ast->tech_pvt;
06167 struct dahdi_params par;
06168
06169 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06170 if (!ast->tech_pvt) {
06171 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06172 return 0;
06173 }
06174
06175 ast_mutex_lock(&p->lock);
06176 p->exten[0] = '\0';
06177 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06178 dahdi_confmute(p, 0);
06179 restore_gains(p);
06180 p->ignoredtmf = 0;
06181 p->waitingfordt.tv_sec = 0;
06182
06183 res = analog_hangup(p->sig_pvt, ast);
06184 revert_fax_buffers(p, ast);
06185
06186 goto hangup_out;
06187 } else {
06188 p->cid_num[0] = '\0';
06189 p->cid_name[0] = '\0';
06190 p->cid_subaddr[0] = '\0';
06191 }
06192
06193 #if defined(HAVE_PRI)
06194 if (dahdi_sig_pri_lib_handles(p->sig)) {
06195 x = 1;
06196 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06197
06198 dahdi_confmute(p, 0);
06199 p->muting = 0;
06200 restore_gains(p);
06201 if (p->dsp) {
06202 ast_dsp_free(p->dsp);
06203 p->dsp = NULL;
06204 }
06205 p->ignoredtmf = 0;
06206
06207
06208 p->subs[SUB_REAL].owner = NULL;
06209 p->subs[SUB_REAL].needbusy = 0;
06210 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06211
06212 p->owner = NULL;
06213 p->cid_tag[0] = '\0';
06214 p->ringt = 0;
06215 p->distinctivering = 0;
06216 p->confirmanswer = 0;
06217 p->outgoing = 0;
06218 p->digital = 0;
06219 p->faxhandled = 0;
06220 p->pulsedial = 0;
06221
06222 revert_fax_buffers(p, ast);
06223
06224 p->law = p->law_default;
06225 law = p->law_default;
06226 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06227 if (res < 0) {
06228 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06229 p->channel, strerror(errno));
06230 }
06231
06232 sig_pri_hangup(p->sig_pvt, ast);
06233
06234 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06235 dahdi_disable_ec(p);
06236
06237 x = 0;
06238 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06239 p->didtdd = 0;
06240
06241 p->rdnis[0] = '\0';
06242 update_conf(p);
06243 reset_conf(p);
06244
06245
06246 x = 0;
06247 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06248
06249 if (num_restart_pending == 0) {
06250 restart_monitor();
06251 }
06252 goto hangup_out;
06253 }
06254 #endif
06255
06256 #if defined(HAVE_SS7)
06257 if (p->sig == SIG_SS7) {
06258 x = 1;
06259 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06260
06261 dahdi_confmute(p, 0);
06262 p->muting = 0;
06263 restore_gains(p);
06264 if (p->dsp) {
06265 ast_dsp_free(p->dsp);
06266 p->dsp = NULL;
06267 }
06268 p->ignoredtmf = 0;
06269
06270
06271 p->subs[SUB_REAL].owner = NULL;
06272 p->subs[SUB_REAL].needbusy = 0;
06273 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06274
06275 p->owner = NULL;
06276 p->ringt = 0;
06277 p->distinctivering = 0;
06278 p->confirmanswer = 0;
06279 p->outgoing = 0;
06280 p->digital = 0;
06281 p->faxhandled = 0;
06282 p->pulsedial = 0;
06283
06284 revert_fax_buffers(p, ast);
06285
06286 p->law = p->law_default;
06287 law = p->law_default;
06288 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06289 if (res < 0) {
06290 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06291 p->channel, strerror(errno));
06292 }
06293
06294 sig_ss7_hangup(p->sig_pvt, ast);
06295
06296 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06297 dahdi_disable_ec(p);
06298
06299 x = 0;
06300 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06301 p->didtdd = 0;
06302
06303 update_conf(p);
06304 reset_conf(p);
06305
06306
06307 x = 0;
06308 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06309
06310 if (num_restart_pending == 0) {
06311 restart_monitor();
06312 }
06313 goto hangup_out;
06314 }
06315 #endif
06316
06317 idx = dahdi_get_index(ast, p, 1);
06318
06319 dahdi_confmute(p, 0);
06320 p->muting = 0;
06321 restore_gains(p);
06322 if (p->origcid_num) {
06323 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06324 ast_free(p->origcid_num);
06325 p->origcid_num = NULL;
06326 }
06327 if (p->origcid_name) {
06328 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06329 ast_free(p->origcid_name);
06330 p->origcid_name = NULL;
06331 }
06332 if (p->dsp)
06333 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06334
06335 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06336 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06337 p->ignoredtmf = 0;
06338
06339 if (idx > -1) {
06340
06341 p->subs[idx].owner = NULL;
06342 p->subs[idx].needanswer = 0;
06343 p->subs[idx].needflash = 0;
06344 p->subs[idx].needringing = 0;
06345 p->subs[idx].needbusy = 0;
06346 p->subs[idx].needcongestion = 0;
06347 p->subs[idx].linear = 0;
06348 p->polarity = POLARITY_IDLE;
06349 dahdi_setlinear(p->subs[idx].dfd, 0);
06350 if (idx == SUB_REAL) {
06351 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06352 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06353 if (p->subs[SUB_CALLWAIT].inthreeway) {
06354
06355 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06356
06357 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06358 unalloc_sub(p, SUB_CALLWAIT);
06359 p->owner = NULL;
06360 } else {
06361
06362 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06363 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06364 unalloc_sub(p, SUB_THREEWAY);
06365 if (p->subs[SUB_REAL].inthreeway) {
06366
06367
06368 ast_debug(1, "Call was complete, setting owner to former third call\n");
06369 p->owner = p->subs[SUB_REAL].owner;
06370 } else {
06371
06372 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06373 p->owner = NULL;
06374 }
06375 p->subs[SUB_REAL].inthreeway = 0;
06376 }
06377 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06378
06379 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06380 unalloc_sub(p, SUB_CALLWAIT);
06381 p->owner = p->subs[SUB_REAL].owner;
06382 if (p->owner->_state != AST_STATE_UP)
06383 p->subs[SUB_REAL].needanswer = 1;
06384 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06385 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06386 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06387 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06388 unalloc_sub(p, SUB_THREEWAY);
06389 if (p->subs[SUB_REAL].inthreeway) {
06390
06391
06392 ast_debug(1, "Call was complete, setting owner to former third call\n");
06393 p->owner = p->subs[SUB_REAL].owner;
06394 } else {
06395
06396 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06397 p->owner = NULL;
06398 }
06399 p->subs[SUB_REAL].inthreeway = 0;
06400 }
06401 } else if (idx == SUB_CALLWAIT) {
06402
06403 if (p->subs[SUB_CALLWAIT].inthreeway) {
06404
06405
06406 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06407 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06408 S_OR(p->mohsuggest, NULL),
06409 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06410 }
06411 p->subs[SUB_THREEWAY].inthreeway = 0;
06412
06413 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06414 unalloc_sub(p, SUB_THREEWAY);
06415 } else
06416 unalloc_sub(p, SUB_CALLWAIT);
06417 } else if (idx == SUB_THREEWAY) {
06418 if (p->subs[SUB_CALLWAIT].inthreeway) {
06419
06420
06421 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06422 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06423 S_OR(p->mohsuggest, NULL),
06424 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06425 }
06426 p->subs[SUB_CALLWAIT].inthreeway = 0;
06427 }
06428 p->subs[SUB_REAL].inthreeway = 0;
06429
06430
06431 unalloc_sub(p, SUB_THREEWAY);
06432 } else {
06433
06434 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06435 }
06436 }
06437
06438 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06439 p->owner = NULL;
06440 p->ringt = 0;
06441 p->distinctivering = 0;
06442 p->confirmanswer = 0;
06443 p->outgoing = 0;
06444 p->digital = 0;
06445 p->faxhandled = 0;
06446 p->pulsedial = 0;
06447 if (p->dsp) {
06448 ast_dsp_free(p->dsp);
06449 p->dsp = NULL;
06450 }
06451
06452 revert_fax_buffers(p, ast);
06453
06454 p->law = p->law_default;
06455 law = p->law_default;
06456 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06457 if (res < 0)
06458 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06459
06460 #ifdef HAVE_OPENR2
06461 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06462 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06463
06464 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06465 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06466 } else {
06467 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06468 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06469 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06470 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06471 dahdi_r2_disconnect_call(p, r2cause);
06472 }
06473 } else if (p->mfcr2call) {
06474 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06475
06476
06477
06478
06479 p->mfcr2call = 0;
06480 }
06481 #endif
06482 switch (p->sig) {
06483 case SIG_SS7:
06484 case SIG_MFCR2:
06485 case SIG_PRI_LIB_HANDLE_CASES:
06486 case 0:
06487 break;
06488 default:
06489 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06490 break;
06491 }
06492 if (res < 0) {
06493 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06494 }
06495 switch (p->sig) {
06496 case SIG_FXOGS:
06497 case SIG_FXOLS:
06498 case SIG_FXOKS:
06499 memset(&par, 0, sizeof(par));
06500 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06501 if (!res) {
06502 struct analog_pvt *analog_p = p->sig_pvt;
06503 #if 0
06504 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06505 #endif
06506
06507 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06508 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06509 else
06510 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06511 analog_p->fxsoffhookstate = par.rxisoffhook;
06512 }
06513 break;
06514 case SIG_FXSGS:
06515 case SIG_FXSLS:
06516 case SIG_FXSKS:
06517
06518
06519 if (ast->_state != AST_STATE_RESERVED) {
06520 time(&p->guardtime);
06521 p->guardtime += 2;
06522 }
06523 break;
06524 default:
06525 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06526 break;
06527 }
06528 if (p->sig)
06529 dahdi_disable_ec(p);
06530 x = 0;
06531 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06532 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06533 p->didtdd = 0;
06534 p->callwaitcas = 0;
06535 p->callwaiting = p->permcallwaiting;
06536 p->hidecallerid = p->permhidecallerid;
06537 p->waitingfordt.tv_sec = 0;
06538 p->dialing = 0;
06539 p->rdnis[0] = '\0';
06540 update_conf(p);
06541 reset_conf(p);
06542
06543 switch (p->sig) {
06544 case SIG_PRI_LIB_HANDLE_CASES:
06545 case SIG_SS7:
06546 x = 0;
06547 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06548 break;
06549 default:
06550 break;
06551 }
06552 if (num_restart_pending == 0)
06553 restart_monitor();
06554 }
06555
06556 p->callwaitingrepeat = 0;
06557 p->cidcwexpire = 0;
06558 p->cid_suppress_expire = 0;
06559 p->oprmode = 0;
06560 hangup_out:
06561 ast->tech_pvt = NULL;
06562 ast_free(p->cidspill);
06563 p->cidspill = NULL;
06564
06565 ast_mutex_unlock(&p->lock);
06566 ast_verb(3, "Hungup '%s'\n", ast->name);
06567
06568 ast_mutex_lock(&iflock);
06569 if (p->restartpending) {
06570 num_restart_pending--;
06571 }
06572
06573 if (p->destroy) {
06574 destroy_channel(p, 0);
06575 }
06576 ast_mutex_unlock(&iflock);
06577
06578 ast_module_unref(ast_module_info->self);
06579 return 0;
06580 }
06581
06582 static int dahdi_answer(struct ast_channel *ast)
06583 {
06584 struct dahdi_pvt *p = ast->tech_pvt;
06585 int res = 0;
06586 int idx;
06587 ast_setstate(ast, AST_STATE_UP);
06588 ast_mutex_lock(&p->lock);
06589 idx = dahdi_get_index(ast, p, 0);
06590 if (idx < 0)
06591 idx = SUB_REAL;
06592
06593 if ((p->radio || (p->oprmode < 0))) {
06594 ast_mutex_unlock(&p->lock);
06595 return 0;
06596 }
06597
06598 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06599 res = analog_answer(p->sig_pvt, ast);
06600 ast_mutex_unlock(&p->lock);
06601 return res;
06602 }
06603
06604 switch (p->sig) {
06605 #if defined(HAVE_PRI)
06606 case SIG_PRI_LIB_HANDLE_CASES:
06607 res = sig_pri_answer(p->sig_pvt, ast);
06608 break;
06609 #endif
06610 #if defined(HAVE_SS7)
06611 case SIG_SS7:
06612 res = sig_ss7_answer(p->sig_pvt, ast);
06613 break;
06614 #endif
06615 #ifdef HAVE_OPENR2
06616 case SIG_MFCR2:
06617 if (!p->mfcr2_call_accepted) {
06618
06619
06620 p->mfcr2_answer_pending = 1;
06621 if (p->mfcr2_charge_calls) {
06622 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06623 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06624 } else {
06625 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06626 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06627 }
06628 } else {
06629 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06630 dahdi_r2_answer(p);
06631 }
06632 break;
06633 #endif
06634 case 0:
06635 ast_mutex_unlock(&p->lock);
06636 return 0;
06637 default:
06638 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06639 res = -1;
06640 break;
06641 }
06642 ast_mutex_unlock(&p->lock);
06643 return res;
06644 }
06645
06646 static void disable_dtmf_detect(struct dahdi_pvt *p)
06647 {
06648 int val = 0;
06649
06650 p->ignoredtmf = 1;
06651
06652 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06653
06654 if (!p->hardwaredtmf && p->dsp) {
06655 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06656 ast_dsp_set_features(p->dsp, p->dsp_features);
06657 }
06658 }
06659
06660 static void enable_dtmf_detect(struct dahdi_pvt *p)
06661 {
06662 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06663
06664 if (p->channel == CHAN_PSEUDO)
06665 return;
06666
06667 p->ignoredtmf = 0;
06668
06669 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06670
06671 if (!p->hardwaredtmf && p->dsp) {
06672 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06673 ast_dsp_set_features(p->dsp, p->dsp_features);
06674 }
06675 }
06676
06677 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06678 {
06679 char *cp;
06680 struct dahdi_pvt *p = chan->tech_pvt;
06681
06682
06683 if (!p || !data || (*datalen < 1)) {
06684 errno = EINVAL;
06685 return -1;
06686 }
06687
06688 switch (option) {
06689 case AST_OPTION_DIGIT_DETECT:
06690 cp = (char *) data;
06691 *cp = p->ignoredtmf ? 0 : 1;
06692 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06693 break;
06694 case AST_OPTION_FAX_DETECT:
06695 cp = (char *) data;
06696 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06697 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06698 break;
06699 case AST_OPTION_CC_AGENT_TYPE:
06700 #if defined(HAVE_PRI)
06701 #if defined(HAVE_PRI_CCSS)
06702 if (dahdi_sig_pri_lib_handles(p->sig)) {
06703 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06704 break;
06705 }
06706 #endif
06707 #endif
06708 return -1;
06709 default:
06710 return -1;
06711 }
06712
06713 errno = 0;
06714
06715 return 0;
06716 }
06717
06718 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06719 {
06720 char *cp;
06721 signed char *scp;
06722 int x;
06723 int idx;
06724 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06725 struct oprmode *oprmode;
06726
06727
06728
06729 if (!p || !data || (datalen < 1)) {
06730 errno = EINVAL;
06731 return -1;
06732 }
06733
06734 switch (option) {
06735 case AST_OPTION_TXGAIN:
06736 scp = (signed char *) data;
06737 idx = dahdi_get_index(chan, p, 0);
06738 if (idx < 0) {
06739 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06740 return -1;
06741 }
06742 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06743 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06744 case AST_OPTION_RXGAIN:
06745 scp = (signed char *) data;
06746 idx = dahdi_get_index(chan, p, 0);
06747 if (idx < 0) {
06748 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06749 return -1;
06750 }
06751 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06752 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06753 case AST_OPTION_TONE_VERIFY:
06754 if (!p->dsp)
06755 break;
06756 cp = (char *) data;
06757 switch (*cp) {
06758 case 1:
06759 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06760 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06761 break;
06762 case 2:
06763 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06764 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06765 break;
06766 default:
06767 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06768 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06769 break;
06770 }
06771 break;
06772 case AST_OPTION_TDD:
06773
06774 cp = (char *) data;
06775 p->mate = 0;
06776 if (!*cp) {
06777 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06778 if (p->tdd)
06779 tdd_free(p->tdd);
06780 p->tdd = 0;
06781 break;
06782 }
06783 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06784 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06785 dahdi_disable_ec(p);
06786
06787 if (!p->didtdd) {
06788 unsigned char mybuf[41000];
06789 unsigned char *buf;
06790 int size, res, fd, len;
06791 struct pollfd fds[1];
06792
06793 buf = mybuf;
06794 memset(buf, 0x7f, sizeof(mybuf));
06795 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06796 len = 40000;
06797 idx = dahdi_get_index(chan, p, 0);
06798 if (idx < 0) {
06799 ast_log(LOG_WARNING, "No index in TDD?\n");
06800 return -1;
06801 }
06802 fd = p->subs[idx].dfd;
06803 while (len) {
06804 if (ast_check_hangup(chan))
06805 return -1;
06806 size = len;
06807 if (size > READ_SIZE)
06808 size = READ_SIZE;
06809 fds[0].fd = fd;
06810 fds[0].events = POLLPRI | POLLOUT;
06811 fds[0].revents = 0;
06812 res = poll(fds, 1, -1);
06813 if (!res) {
06814 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06815 continue;
06816 }
06817
06818 if (fds[0].revents & POLLPRI)
06819 return -1;
06820 if (!(fds[0].revents & POLLOUT)) {
06821 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06822 continue;
06823 }
06824 res = write(fd, buf, size);
06825 if (res != size) {
06826 if (res == -1) return -1;
06827 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06828 break;
06829 }
06830 len -= size;
06831 buf += size;
06832 }
06833 p->didtdd = 1;
06834 }
06835 if (*cp == 2) {
06836 if (p->tdd)
06837 tdd_free(p->tdd);
06838 p->tdd = 0;
06839 p->mate = 1;
06840 break;
06841 }
06842 if (!p->tdd) {
06843 p->tdd = tdd_new();
06844 }
06845 break;
06846 case AST_OPTION_RELAXDTMF:
06847 if (!p->dsp)
06848 break;
06849 cp = (char *) data;
06850 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06851 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06852 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06853 break;
06854 case AST_OPTION_AUDIO_MODE:
06855 #if defined(HAVE_PRI)
06856 if (dahdi_sig_pri_lib_handles(p->sig)
06857 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06858
06859 break;
06860 }
06861 #endif
06862
06863 cp = (char *) data;
06864 if (!*cp) {
06865 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06866 x = 0;
06867 dahdi_disable_ec(p);
06868 } else {
06869 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06870 x = 1;
06871 }
06872 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06873 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06874 break;
06875 case AST_OPTION_OPRMODE:
06876 oprmode = (struct oprmode *) data;
06877
06878 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06879 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06880 chan->tech->type, oprmode->peer->tech->type);
06881 errno = EINVAL;
06882 return -1;
06883 }
06884 pp = oprmode->peer->tech_pvt;
06885 p->oprmode = pp->oprmode = 0;
06886
06887 p->oprpeer = pp;
06888 pp->oprpeer = p;
06889
06890 if (oprmode->mode)
06891 {
06892 pp->oprmode = oprmode->mode;
06893 p->oprmode = -oprmode->mode;
06894 }
06895 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06896 oprmode->mode, chan->name,oprmode->peer->name);
06897 break;
06898 case AST_OPTION_ECHOCAN:
06899 cp = (char *) data;
06900 if (*cp) {
06901 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06902 dahdi_enable_ec(p);
06903 } else {
06904 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06905 dahdi_disable_ec(p);
06906 }
06907 break;
06908 case AST_OPTION_DIGIT_DETECT:
06909 cp = (char *) data;
06910 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06911 if (*cp) {
06912 enable_dtmf_detect(p);
06913 } else {
06914 disable_dtmf_detect(p);
06915 }
06916 break;
06917 case AST_OPTION_FAX_DETECT:
06918 cp = (char *) data;
06919 if (p->dsp) {
06920 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06921 if (*cp) {
06922 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06923 } else {
06924 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06925 }
06926 ast_dsp_set_features(p->dsp, p->dsp_features);
06927 }
06928 break;
06929 default:
06930 return -1;
06931 }
06932 errno = 0;
06933
06934 return 0;
06935 }
06936
06937 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06938 {
06939 struct dahdi_pvt *p = chan->tech_pvt;
06940 int res = 0;
06941
06942 if (!p) {
06943
06944 *buf = '\0';
06945 return -1;
06946 }
06947
06948 if (!strcasecmp(data, "rxgain")) {
06949 ast_mutex_lock(&p->lock);
06950 snprintf(buf, len, "%f", p->rxgain);
06951 ast_mutex_unlock(&p->lock);
06952 } else if (!strcasecmp(data, "txgain")) {
06953 ast_mutex_lock(&p->lock);
06954 snprintf(buf, len, "%f", p->txgain);
06955 ast_mutex_unlock(&p->lock);
06956 } else if (!strcasecmp(data, "dahdi_channel")) {
06957 ast_mutex_lock(&p->lock);
06958 snprintf(buf, len, "%d", p->channel);
06959 ast_mutex_unlock(&p->lock);
06960 } else if (!strcasecmp(data, "dahdi_span")) {
06961 ast_mutex_lock(&p->lock);
06962 snprintf(buf, len, "%d", p->span);
06963 ast_mutex_unlock(&p->lock);
06964 } else if (!strcasecmp(data, "dahdi_type")) {
06965 ast_mutex_lock(&p->lock);
06966 switch (p->sig) {
06967 #if defined(HAVE_OPENR2)
06968 case SIG_MFCR2:
06969 ast_copy_string(buf, "mfc/r2", len);
06970 break;
06971 #endif
06972 #if defined(HAVE_PRI)
06973 case SIG_PRI_LIB_HANDLE_CASES:
06974 ast_copy_string(buf, "pri", len);
06975 break;
06976 #endif
06977 case 0:
06978 ast_copy_string(buf, "pseudo", len);
06979 break;
06980 #if defined(HAVE_SS7)
06981 case SIG_SS7:
06982 ast_copy_string(buf, "ss7", len);
06983 break;
06984 #endif
06985 default:
06986
06987 ast_copy_string(buf, "analog", len);
06988 break;
06989 }
06990 ast_mutex_unlock(&p->lock);
06991 #if defined(HAVE_PRI)
06992 #if defined(HAVE_PRI_REVERSE_CHARGE)
06993 } else if (!strcasecmp(data, "reversecharge")) {
06994 ast_mutex_lock(&p->lock);
06995 switch (p->sig) {
06996 case SIG_PRI_LIB_HANDLE_CASES:
06997 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06998 break;
06999 default:
07000 *buf = '\0';
07001 res = -1;
07002 break;
07003 }
07004 ast_mutex_unlock(&p->lock);
07005 #endif
07006 #if defined(HAVE_PRI_SETUP_KEYPAD)
07007 } else if (!strcasecmp(data, "keypad_digits")) {
07008 ast_mutex_lock(&p->lock);
07009 switch (p->sig) {
07010 case SIG_PRI_LIB_HANDLE_CASES:
07011 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07012 len);
07013 break;
07014 default:
07015 *buf = '\0';
07016 res = -1;
07017 break;
07018 }
07019 ast_mutex_unlock(&p->lock);
07020 #endif
07021 } else if (!strcasecmp(data, "no_media_path")) {
07022 ast_mutex_lock(&p->lock);
07023 switch (p->sig) {
07024 case SIG_PRI_LIB_HANDLE_CASES:
07025
07026
07027
07028
07029 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07030 break;
07031 default:
07032 *buf = '\0';
07033 res = -1;
07034 break;
07035 }
07036 ast_mutex_unlock(&p->lock);
07037 #endif
07038 } else {
07039 *buf = '\0';
07040 res = -1;
07041 }
07042
07043 return res;
07044 }
07045
07046
07047 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07048 {
07049 int res;
07050 char policy_str[21] = "";
07051
07052 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07053 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07054 return 1;
07055 }
07056 if (*num_buffers < 0) {
07057 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07058 return -1;
07059 }
07060 if (!strcasecmp(policy_str, "full")) {
07061 *policy = DAHDI_POLICY_WHEN_FULL;
07062 } else if (!strcasecmp(policy_str, "immediate")) {
07063 *policy = DAHDI_POLICY_IMMEDIATE;
07064 #if defined(HAVE_DAHDI_HALF_FULL)
07065 } else if (!strcasecmp(policy_str, "half")) {
07066 *policy = DAHDI_POLICY_HALF_FULL;
07067 #endif
07068 } else {
07069 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07070 return -1;
07071 }
07072
07073 return 0;
07074 }
07075
07076 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07077 {
07078 struct dahdi_pvt *p = chan->tech_pvt;
07079 int res = 0;
07080
07081 if (!p) {
07082
07083 return -1;
07084 }
07085
07086 if (!strcasecmp(data, "buffers")) {
07087 int num_bufs, policy;
07088
07089 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07090 struct dahdi_bufferinfo bi = {
07091 .txbufpolicy = policy,
07092 .rxbufpolicy = policy,
07093 .bufsize = p->bufsize,
07094 .numbufs = num_bufs,
07095 };
07096 int bpres;
07097
07098 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07099 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07100 } else {
07101 p->bufferoverrideinuse = 1;
07102 }
07103 } else {
07104 res = -1;
07105 }
07106 } else if (!strcasecmp(data, "echocan_mode")) {
07107 if (!strcasecmp(value, "on")) {
07108 ast_mutex_lock(&p->lock);
07109 dahdi_enable_ec(p);
07110 ast_mutex_unlock(&p->lock);
07111 } else if (!strcasecmp(value, "off")) {
07112 ast_mutex_lock(&p->lock);
07113 dahdi_disable_ec(p);
07114 ast_mutex_unlock(&p->lock);
07115 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07116 } else if (!strcasecmp(value, "fax")) {
07117 int blah = 1;
07118
07119 ast_mutex_lock(&p->lock);
07120 if (!p->echocanon) {
07121 dahdi_enable_ec(p);
07122 }
07123 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07124 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07125 }
07126 ast_mutex_unlock(&p->lock);
07127 } else if (!strcasecmp(value, "voice")) {
07128 int blah = 0;
07129
07130 ast_mutex_lock(&p->lock);
07131 if (!p->echocanon) {
07132 dahdi_enable_ec(p);
07133 }
07134 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07135 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07136 }
07137 ast_mutex_unlock(&p->lock);
07138 #endif
07139 } else {
07140 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07141 res = -1;
07142 }
07143 } else {
07144 res = -1;
07145 }
07146
07147 return res;
07148 }
07149
07150 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07151 {
07152
07153 int x;
07154 int hasslaves;
07155 if (!master)
07156 return;
07157 if (needlock) {
07158 ast_mutex_lock(&master->lock);
07159 if (slave) {
07160 while (ast_mutex_trylock(&slave->lock)) {
07161 DEADLOCK_AVOIDANCE(&master->lock);
07162 }
07163 }
07164 }
07165 hasslaves = 0;
07166 for (x = 0; x < MAX_SLAVES; x++) {
07167 if (master->slaves[x]) {
07168 if (!slave || (master->slaves[x] == slave)) {
07169
07170 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07171 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07172 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07173 master->slaves[x]->master = NULL;
07174 master->slaves[x] = NULL;
07175 } else
07176 hasslaves = 1;
07177 }
07178 if (!hasslaves)
07179 master->inconference = 0;
07180 }
07181 if (!slave) {
07182 if (master->master) {
07183
07184 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07185 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07186 hasslaves = 0;
07187 for (x = 0; x < MAX_SLAVES; x++) {
07188 if (master->master->slaves[x] == master)
07189 master->master->slaves[x] = NULL;
07190 else if (master->master->slaves[x])
07191 hasslaves = 1;
07192 }
07193 if (!hasslaves)
07194 master->master->inconference = 0;
07195 }
07196 master->master = NULL;
07197 }
07198 update_conf(master);
07199 if (needlock) {
07200 if (slave)
07201 ast_mutex_unlock(&slave->lock);
07202 ast_mutex_unlock(&master->lock);
07203 }
07204 }
07205
07206 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07207 int x;
07208 if (!slave || !master) {
07209 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07210 return;
07211 }
07212 for (x = 0; x < MAX_SLAVES; x++) {
07213 if (!master->slaves[x]) {
07214 master->slaves[x] = slave;
07215 break;
07216 }
07217 }
07218 if (x >= MAX_SLAVES) {
07219 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07220 master->slaves[MAX_SLAVES - 1] = slave;
07221 }
07222 if (slave->master)
07223 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07224 slave->master = master;
07225
07226 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07227 }
07228
07229 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)
07230 {
07231 struct ast_channel *who;
07232 struct dahdi_pvt *p0, *p1, *op0, *op1;
07233 struct dahdi_pvt *master = NULL, *slave = NULL;
07234 struct ast_frame *f;
07235 int inconf = 0;
07236 int nothingok = 1;
07237 int ofd0, ofd1;
07238 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07239 int os0 = -1, os1 = -1;
07240 int priority = 0;
07241 struct ast_channel *oc0, *oc1;
07242 enum ast_bridge_result res;
07243 #ifdef PRI_2BCT
07244 int triedtopribridge = 0;
07245 q931_call *q931c0;
07246 q931_call *q931c1;
07247 #endif
07248
07249
07250
07251
07252
07253
07254 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07255 return AST_BRIDGE_FAILED_NOWARN;
07256
07257 ast_channel_lock(c0);
07258 while (ast_channel_trylock(c1)) {
07259 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07260 }
07261
07262 p0 = c0->tech_pvt;
07263 p1 = c1->tech_pvt;
07264
07265 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07266 ast_channel_unlock(c0);
07267 ast_channel_unlock(c1);
07268 return AST_BRIDGE_FAILED_NOWARN;
07269 }
07270
07271 oi0 = dahdi_get_index(c0, p0, 0);
07272 oi1 = dahdi_get_index(c1, p1, 0);
07273 if ((oi0 < 0) || (oi1 < 0)) {
07274 ast_channel_unlock(c0);
07275 ast_channel_unlock(c1);
07276 return AST_BRIDGE_FAILED;
07277 }
07278
07279 op0 = p0 = c0->tech_pvt;
07280 op1 = p1 = c1->tech_pvt;
07281 ofd0 = c0->fds[0];
07282 ofd1 = c1->fds[0];
07283 oc0 = p0->owner;
07284 oc1 = p1->owner;
07285
07286 if (ast_mutex_trylock(&p0->lock)) {
07287
07288 ast_channel_unlock(c0);
07289 ast_channel_unlock(c1);
07290 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07291 return AST_BRIDGE_RETRY;
07292 }
07293 if (ast_mutex_trylock(&p1->lock)) {
07294
07295 ast_mutex_unlock(&p0->lock);
07296 ast_channel_unlock(c0);
07297 ast_channel_unlock(c1);
07298 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07299 return AST_BRIDGE_RETRY;
07300 }
07301
07302 if ((p0->callwaiting && p0->callwaitingcallerid)
07303 || (p1->callwaiting && p1->callwaitingcallerid)) {
07304
07305
07306
07307
07308
07309
07310
07311
07312
07313 ast_mutex_unlock(&p0->lock);
07314 ast_mutex_unlock(&p1->lock);
07315 ast_channel_unlock(c0);
07316 ast_channel_unlock(c1);
07317 return AST_BRIDGE_FAILED_NOWARN;
07318 }
07319
07320 #if defined(HAVE_PRI)
07321 if ((dahdi_sig_pri_lib_handles(p0->sig)
07322 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07323 || (dahdi_sig_pri_lib_handles(p1->sig)
07324 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07325
07326
07327
07328
07329 ast_mutex_unlock(&p0->lock);
07330 ast_mutex_unlock(&p1->lock);
07331 ast_channel_unlock(c0);
07332 ast_channel_unlock(c1);
07333 return AST_BRIDGE_FAILED_NOWARN;
07334 }
07335 #endif
07336
07337 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07338 if (p0->owner && p1->owner) {
07339
07340 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07341 master = p0;
07342 slave = p1;
07343 inconf = 1;
07344 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07345 master = p1;
07346 slave = p0;
07347 inconf = 1;
07348 } else {
07349 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07350 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07351 p0->channel,
07352 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07353 p0->subs[SUB_REAL].inthreeway, p0->channel,
07354 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07355 p1->subs[SUB_REAL].inthreeway);
07356 }
07357 nothingok = 0;
07358 }
07359 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07360 if (p1->subs[SUB_THREEWAY].inthreeway) {
07361 master = p1;
07362 slave = p0;
07363 nothingok = 0;
07364 }
07365 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07366 if (p0->subs[SUB_THREEWAY].inthreeway) {
07367 master = p0;
07368 slave = p1;
07369 nothingok = 0;
07370 }
07371 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07372
07373
07374 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07375 master = p1;
07376 slave = p0;
07377 nothingok = 0;
07378 }
07379 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07380
07381 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07382 master = p0;
07383 slave = p1;
07384 nothingok = 0;
07385 }
07386 }
07387 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07388 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07389 if (master && slave) {
07390
07391
07392
07393 if ((oi1 == SUB_THREEWAY) &&
07394 p1->subs[SUB_THREEWAY].inthreeway &&
07395 p1->subs[SUB_REAL].owner &&
07396 p1->subs[SUB_REAL].inthreeway &&
07397 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07398 ast_debug(1,
07399 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07400 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07401 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07402 os1 = p1->subs[SUB_REAL].owner->_state;
07403 } else {
07404 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07405 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07406 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07407 }
07408 if ((oi0 == SUB_THREEWAY) &&
07409 p0->subs[SUB_THREEWAY].inthreeway &&
07410 p0->subs[SUB_REAL].owner &&
07411 p0->subs[SUB_REAL].inthreeway &&
07412 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07413 ast_debug(1,
07414 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07415 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07416 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07417 os0 = p0->subs[SUB_REAL].owner->_state;
07418 } else {
07419 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07420 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07421 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07422 }
07423 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07424 if (!p0->echocanbridged || !p1->echocanbridged) {
07425
07426 dahdi_disable_ec(p0);
07427 dahdi_disable_ec(p1);
07428 }
07429 }
07430 dahdi_link(slave, master);
07431 master->inconference = inconf;
07432 } else if (!nothingok)
07433 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07434
07435 update_conf(p0);
07436 update_conf(p1);
07437 t0 = p0->subs[SUB_REAL].inthreeway;
07438 t1 = p1->subs[SUB_REAL].inthreeway;
07439
07440 ast_mutex_unlock(&p0->lock);
07441 ast_mutex_unlock(&p1->lock);
07442
07443 ast_channel_unlock(c0);
07444 ast_channel_unlock(c1);
07445
07446
07447 if ((!master || !slave) && !nothingok) {
07448 dahdi_enable_ec(p0);
07449 dahdi_enable_ec(p1);
07450 return AST_BRIDGE_FAILED;
07451 }
07452
07453 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07454
07455 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07456 disable_dtmf_detect(op0);
07457
07458 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07459 disable_dtmf_detect(op1);
07460
07461 for (;;) {
07462 struct ast_channel *c0_priority[2] = {c0, c1};
07463 struct ast_channel *c1_priority[2] = {c1, c0};
07464
07465
07466
07467
07468 ast_channel_lock(c0);
07469 while (ast_channel_trylock(c1)) {
07470 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07471 }
07472
07473 p0 = c0->tech_pvt;
07474 p1 = c1->tech_pvt;
07475
07476 if (op0 == p0)
07477 i0 = dahdi_get_index(c0, p0, 1);
07478 if (op1 == p1)
07479 i1 = dahdi_get_index(c1, p1, 1);
07480
07481 ast_channel_unlock(c0);
07482 ast_channel_unlock(c1);
07483
07484 if (!timeoutms ||
07485 (op0 != p0) ||
07486 (op1 != p1) ||
07487 (ofd0 != c0->fds[0]) ||
07488 (ofd1 != c1->fds[0]) ||
07489 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07490 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07491 (oc0 != p0->owner) ||
07492 (oc1 != p1->owner) ||
07493 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07494 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07495 (oi0 != i0) ||
07496 (oi1 != i1)) {
07497 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07498 op0->channel, oi0, op1->channel, oi1);
07499 res = AST_BRIDGE_RETRY;
07500 goto return_from_bridge;
07501 }
07502
07503 #ifdef PRI_2BCT
07504 if (!triedtopribridge) {
07505 triedtopribridge = 1;
07506 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07507 ast_mutex_lock(&p0->pri->lock);
07508 switch (p0->sig) {
07509 case SIG_PRI_LIB_HANDLE_CASES:
07510 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07511 break;
07512 default:
07513 q931c0 = NULL;
07514 break;
07515 }
07516 switch (p1->sig) {
07517 case SIG_PRI_LIB_HANDLE_CASES:
07518 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07519 break;
07520 default:
07521 q931c1 = NULL;
07522 break;
07523 }
07524 if (q931c0 && q931c1) {
07525 pri_channel_bridge(q931c0, q931c1);
07526 }
07527 ast_mutex_unlock(&p0->pri->lock);
07528 }
07529 }
07530 #endif
07531
07532 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07533 if (!who) {
07534 ast_debug(1, "Ooh, empty read...\n");
07535 continue;
07536 }
07537 f = ast_read(who);
07538 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07539 *fo = f;
07540 *rc = who;
07541 res = AST_BRIDGE_COMPLETE;
07542 goto return_from_bridge;
07543 }
07544 if (f->frametype == AST_FRAME_DTMF) {
07545 if ((who == c0) && p0->pulsedial) {
07546 ast_write(c1, f);
07547 } else if ((who == c1) && p1->pulsedial) {
07548 ast_write(c0, f);
07549 } else {
07550 *fo = f;
07551 *rc = who;
07552 res = AST_BRIDGE_COMPLETE;
07553 goto return_from_bridge;
07554 }
07555 }
07556 ast_frfree(f);
07557
07558
07559 priority = !priority;
07560 }
07561
07562 return_from_bridge:
07563 if (op0 == p0)
07564 dahdi_enable_ec(p0);
07565
07566 if (op1 == p1)
07567 dahdi_enable_ec(p1);
07568
07569 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07570 enable_dtmf_detect(op0);
07571
07572 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07573 enable_dtmf_detect(op1);
07574
07575 dahdi_unlink(slave, master, 1);
07576
07577 return res;
07578 }
07579
07580 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07581 {
07582 struct dahdi_pvt *p = newchan->tech_pvt;
07583 int x;
07584
07585 ast_mutex_lock(&p->lock);
07586
07587 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07588 if (p->owner == oldchan) {
07589 p->owner = newchan;
07590 }
07591 for (x = 0; x < 3; x++) {
07592 if (p->subs[x].owner == oldchan) {
07593 if (!x) {
07594 dahdi_unlink(NULL, p, 0);
07595 }
07596 p->subs[x].owner = newchan;
07597 }
07598 }
07599 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07600 analog_fixup(oldchan, newchan, p->sig_pvt);
07601 #if defined(HAVE_PRI)
07602 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07603 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07604 #endif
07605 #if defined(HAVE_SS7)
07606 } else if (p->sig == SIG_SS7) {
07607 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07608 #endif
07609 }
07610 update_conf(p);
07611
07612 ast_mutex_unlock(&p->lock);
07613
07614 if (newchan->_state == AST_STATE_RINGING) {
07615 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07616 }
07617 return 0;
07618 }
07619
07620 static int dahdi_ring_phone(struct dahdi_pvt *p)
07621 {
07622 int x;
07623 int res;
07624
07625 x = 0;
07626 x = DAHDI_ONHOOK;
07627 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07628 do {
07629 x = DAHDI_RING;
07630 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07631 if (res) {
07632 switch (errno) {
07633 case EBUSY:
07634 case EINTR:
07635
07636 usleep(10000);
07637 continue;
07638 case EINPROGRESS:
07639 res = 0;
07640 break;
07641 default:
07642 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07643 res = 0;
07644 }
07645 }
07646 } while (res);
07647 return res;
07648 }
07649
07650 static void *analog_ss_thread(void *data);
07651
07652 static int attempt_transfer(struct dahdi_pvt *p)
07653 {
07654
07655
07656
07657 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07658
07659
07660 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07661 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07662 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07663 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07664 }
07665 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07666 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07667 }
07668 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07669 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07670 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07671 return -1;
07672 }
07673
07674 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07675 unalloc_sub(p, SUB_THREEWAY);
07676 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07677 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07678 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07679 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07680 }
07681 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07682 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07683 }
07684 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07685 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07686 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07687 return -1;
07688 }
07689
07690 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07691 ast_channel_unlock(p->subs[SUB_REAL].owner);
07692 unalloc_sub(p, SUB_THREEWAY);
07693
07694 return 1;
07695 } else {
07696 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07697 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07698 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07699 return -1;
07700 }
07701 return 0;
07702 }
07703
07704 static int check_for_conference(struct dahdi_pvt *p)
07705 {
07706 struct dahdi_confinfo ci;
07707
07708 if (p->master || (p->confno > -1))
07709 return 0;
07710 memset(&ci, 0, sizeof(ci));
07711 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07712 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07713 return 0;
07714 }
07715
07716
07717
07718 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07719 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07720 return 1;
07721 }
07722 return 0;
07723 }
07724
07725
07726
07727
07728
07729
07730 static int get_alarms(struct dahdi_pvt *p)
07731 {
07732 int res;
07733 struct dahdi_spaninfo zi;
07734 struct dahdi_params params;
07735
07736 memset(&zi, 0, sizeof(zi));
07737 zi.spanno = p->span;
07738
07739 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07740 if (zi.alarms != DAHDI_ALARM_NONE)
07741 return zi.alarms;
07742 } else {
07743 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07744 return 0;
07745 }
07746
07747
07748 memset(¶ms, 0, sizeof(params));
07749 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07750 return params.chan_alarms;
07751
07752 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07753
07754 return DAHDI_ALARM_NONE;
07755 }
07756
07757 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07758 {
07759 struct dahdi_pvt *p = ast->tech_pvt;
07760 struct ast_frame *f = *dest;
07761
07762 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07763 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07764 f->subclass.integer, f->subclass.integer, ast->name);
07765
07766 if (p->confirmanswer) {
07767 if (f->frametype == AST_FRAME_DTMF_END) {
07768 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07769
07770
07771 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07772 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07773
07774 p->confirmanswer = 0;
07775 } else {
07776 p->subs[idx].f.frametype = AST_FRAME_NULL;
07777 p->subs[idx].f.subclass.integer = 0;
07778 }
07779 *dest = &p->subs[idx].f;
07780 } else if (p->callwaitcas) {
07781 if (f->frametype == AST_FRAME_DTMF_END) {
07782 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07783 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07784 ast_free(p->cidspill);
07785 p->cidspill = NULL;
07786 send_cwcidspill(p);
07787 }
07788 p->callwaitcas = 0;
07789 }
07790 p->subs[idx].f.frametype = AST_FRAME_NULL;
07791 p->subs[idx].f.subclass.integer = 0;
07792 *dest = &p->subs[idx].f;
07793 } else if (f->subclass.integer == 'f') {
07794 if (f->frametype == AST_FRAME_DTMF_END) {
07795
07796 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07797
07798 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07799 struct dahdi_bufferinfo bi = {
07800 .txbufpolicy = p->faxbuf_policy,
07801 .bufsize = p->bufsize,
07802 .numbufs = p->faxbuf_no
07803 };
07804 int res;
07805
07806 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07807 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07808 } else {
07809 p->bufferoverrideinuse = 1;
07810 }
07811 }
07812 p->faxhandled = 1;
07813 if (p->dsp) {
07814 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07815 ast_dsp_set_features(p->dsp, p->dsp_features);
07816 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07817 }
07818 if (strcmp(ast->exten, "fax")) {
07819 const char *target_context = S_OR(ast->macrocontext, ast->context);
07820
07821
07822
07823
07824
07825 ast_mutex_unlock(&p->lock);
07826 ast_channel_unlock(ast);
07827 if (ast_exists_extension(ast, target_context, "fax", 1,
07828 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07829 ast_channel_lock(ast);
07830 ast_mutex_lock(&p->lock);
07831 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07832
07833 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07834 if (ast_async_goto(ast, target_context, "fax", 1))
07835 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07836 } else {
07837 ast_channel_lock(ast);
07838 ast_mutex_lock(&p->lock);
07839 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07840 }
07841 } else {
07842 ast_debug(1, "Already in a fax extension, not redirecting\n");
07843 }
07844 } else {
07845 ast_debug(1, "Fax already handled\n");
07846 }
07847 dahdi_confmute(p, 0);
07848 }
07849 p->subs[idx].f.frametype = AST_FRAME_NULL;
07850 p->subs[idx].f.subclass.integer = 0;
07851 *dest = &p->subs[idx].f;
07852 }
07853 }
07854
07855 static void handle_alarms(struct dahdi_pvt *p, int alms)
07856 {
07857 const char *alarm_str;
07858
07859 #if defined(HAVE_PRI)
07860 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07861 return;
07862 }
07863 #endif
07864
07865 alarm_str = alarm2str(alms);
07866 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07867 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07868 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07869 "Alarm: %s\r\n"
07870 "Channel: %d\r\n",
07871 alarm_str, p->channel);
07872 }
07873
07874 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07875 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07876 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07877 "Alarm: %s\r\n"
07878 "Span: %d\r\n",
07879 alarm_str, p->span);
07880 }
07881 }
07882
07883 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07884 {
07885 int res, x;
07886 int idx, mysig;
07887 char *c;
07888 struct dahdi_pvt *p = ast->tech_pvt;
07889 pthread_t threadid;
07890 struct ast_channel *chan;
07891 struct ast_frame *f;
07892
07893 idx = dahdi_get_index(ast, p, 0);
07894 if (idx < 0) {
07895 return &ast_null_frame;
07896 }
07897 mysig = p->sig;
07898 if (p->outsigmod > -1)
07899 mysig = p->outsigmod;
07900 p->subs[idx].f.frametype = AST_FRAME_NULL;
07901 p->subs[idx].f.subclass.integer = 0;
07902 p->subs[idx].f.datalen = 0;
07903 p->subs[idx].f.samples = 0;
07904 p->subs[idx].f.mallocd = 0;
07905 p->subs[idx].f.offset = 0;
07906 p->subs[idx].f.src = "dahdi_handle_event";
07907 p->subs[idx].f.data.ptr = NULL;
07908 f = &p->subs[idx].f;
07909
07910 if (p->fake_event) {
07911 res = p->fake_event;
07912 p->fake_event = 0;
07913 } else
07914 res = dahdi_get_event(p->subs[idx].dfd);
07915
07916 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07917
07918 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07919 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07920 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07921 #if defined(HAVE_PRI)
07922 if (dahdi_sig_pri_lib_handles(p->sig)
07923 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07924 && p->pri
07925 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07926
07927 } else
07928 #endif
07929 {
07930
07931 dahdi_confmute(p, 0);
07932 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07933 p->subs[idx].f.subclass.integer = res & 0xff;
07934 dahdi_handle_dtmf(ast, idx, &f);
07935 }
07936 return f;
07937 }
07938
07939 if (res & DAHDI_EVENT_DTMFDOWN) {
07940 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07941 #if defined(HAVE_PRI)
07942 if (dahdi_sig_pri_lib_handles(p->sig)
07943 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07944 && p->pri
07945 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07946
07947 } else
07948 #endif
07949 {
07950
07951 dahdi_confmute(p, 1);
07952 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07953 p->subs[idx].f.subclass.integer = res & 0xff;
07954 dahdi_handle_dtmf(ast, idx, &f);
07955 }
07956 return &p->subs[idx].f;
07957 }
07958
07959 switch (res) {
07960 case DAHDI_EVENT_EC_DISABLED:
07961 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07962 p->echocanon = 0;
07963 break;
07964 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07965 case DAHDI_EVENT_TX_CED_DETECTED:
07966 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07967 break;
07968 case DAHDI_EVENT_RX_CED_DETECTED:
07969 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07970 break;
07971 case DAHDI_EVENT_EC_NLP_DISABLED:
07972 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07973 break;
07974 case DAHDI_EVENT_EC_NLP_ENABLED:
07975 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07976 break;
07977 #endif
07978 case DAHDI_EVENT_BITSCHANGED:
07979 #ifdef HAVE_OPENR2
07980 if (p->sig != SIG_MFCR2) {
07981 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07982 } else {
07983 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07984 openr2_chan_handle_cas(p->r2chan);
07985 }
07986 #else
07987 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07988 #endif
07989 break;
07990 case DAHDI_EVENT_PULSE_START:
07991
07992 if (!ast->pbx)
07993 tone_zone_play_tone(p->subs[idx].dfd, -1);
07994 break;
07995 case DAHDI_EVENT_DIALCOMPLETE:
07996
07997 #if defined(HAVE_PRI)
07998 if (dahdi_sig_pri_lib_handles(p->sig)) {
07999 if (p->inalarm) {
08000 break;
08001 }
08002 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08003 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08004 strerror(errno));
08005 return NULL;
08006 }
08007 if (x) {
08008
08009 break;
08010 }
08011
08012
08013
08014
08015 sig_pri_dial_complete(p->sig_pvt, ast);
08016 break;
08017 }
08018 #endif
08019 #ifdef HAVE_OPENR2
08020 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08021
08022
08023 break;
08024 }
08025 #endif
08026 if (p->inalarm) break;
08027 if ((p->radio || (p->oprmode < 0))) break;
08028 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08029 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08030 return NULL;
08031 }
08032 if (!x) {
08033 dahdi_enable_ec(p);
08034 if (p->echobreak) {
08035 dahdi_train_ec(p);
08036 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08037 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08039 p->echobreak = 0;
08040 } else {
08041 p->dialing = 0;
08042 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08043
08044 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08045 ast_setstate(ast, AST_STATE_UP);
08046 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08047 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08048 break;
08049 } else {
08050
08051 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08052 }
08053 }
08054 if (ast->_state == AST_STATE_DIALING) {
08055 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08056 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08057 } else if (p->confirmanswer || (!p->dialednone
08058 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08059 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08060 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08061 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08062 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08063 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08064 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08065 || (mysig == SIG_SF_FEATB)))) {
08066 ast_setstate(ast, AST_STATE_RINGING);
08067 } else if (!p->answeronpolarityswitch) {
08068 ast_setstate(ast, AST_STATE_UP);
08069 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08070 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08071
08072 p->polarity = POLARITY_REV;
08073 } else {
08074
08075 p->polarity = POLARITY_IDLE;
08076 }
08077 }
08078 }
08079 }
08080 break;
08081 case DAHDI_EVENT_ALARM:
08082 switch (p->sig) {
08083 #if defined(HAVE_PRI)
08084 case SIG_PRI_LIB_HANDLE_CASES:
08085 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08086 break;
08087 #endif
08088 #if defined(HAVE_SS7)
08089 case SIG_SS7:
08090 sig_ss7_set_alarm(p->sig_pvt, 1);
08091 break;
08092 #endif
08093 default:
08094 p->inalarm = 1;
08095 break;
08096 }
08097 res = get_alarms(p);
08098 handle_alarms(p, res);
08099 #ifdef HAVE_PRI
08100 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08101
08102 } else {
08103 break;
08104 }
08105 #endif
08106 #if defined(HAVE_SS7)
08107 if (p->sig == SIG_SS7)
08108 break;
08109 #endif
08110 #ifdef HAVE_OPENR2
08111 if (p->sig == SIG_MFCR2)
08112 break;
08113 #endif
08114 case DAHDI_EVENT_ONHOOK:
08115 if (p->radio) {
08116 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08117 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08118 break;
08119 }
08120 if (p->oprmode < 0)
08121 {
08122 if (p->oprmode != -1) break;
08123 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08124 {
08125
08126 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08127 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08128 save_conference(p->oprpeer);
08129 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08130 }
08131 break;
08132 }
08133 switch (p->sig) {
08134 case SIG_FXOLS:
08135 case SIG_FXOGS:
08136 case SIG_FXOKS:
08137
08138 if (idx == SUB_REAL) {
08139
08140 if (p->subs[SUB_CALLWAIT].owner) {
08141
08142 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08143 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08144 unalloc_sub(p, SUB_CALLWAIT);
08145 #if 0
08146 p->subs[idx].needanswer = 0;
08147 p->subs[idx].needringing = 0;
08148 #endif
08149 p->callwaitingrepeat = 0;
08150 p->cidcwexpire = 0;
08151 p->cid_suppress_expire = 0;
08152 p->owner = NULL;
08153
08154 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08155 p->dialing = 1;
08156 dahdi_ring_phone(p);
08157 } else if (p->subs[SUB_THREEWAY].owner) {
08158 unsigned int mssinceflash;
08159
08160
08161 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08162
08163 DLA_UNLOCK(&p->lock);
08164 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08165
08166
08167
08168 DLA_LOCK(&p->lock);
08169 if (p->owner != ast) {
08170 ast_log(LOG_WARNING, "This isn't good...\n");
08171 return NULL;
08172 }
08173 }
08174 if (!p->subs[SUB_THREEWAY].owner) {
08175 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08176 return NULL;
08177 }
08178 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08179 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08180 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08181
08182
08183 if (p->subs[SUB_THREEWAY].owner)
08184 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08185 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08186 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08187 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08188 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08189 if (p->transfer) {
08190
08191 p->subs[SUB_REAL].inthreeway = 0;
08192 p->subs[SUB_THREEWAY].inthreeway = 0;
08193
08194 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08195 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08196
08197 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08198 p->owner = NULL;
08199
08200 dahdi_ring_phone(p);
08201 } else {
08202 if ((res = attempt_transfer(p)) < 0) {
08203 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08204 if (p->subs[SUB_THREEWAY].owner)
08205 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08206 } else if (res) {
08207
08208 if (p->subs[SUB_THREEWAY].owner)
08209 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08210 break;
08211 }
08212 }
08213 } else {
08214 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08215 if (p->subs[SUB_THREEWAY].owner)
08216 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08217 }
08218 } else {
08219 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08220
08221 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08222 p->owner = NULL;
08223
08224 dahdi_ring_phone(p);
08225 }
08226 }
08227 } else {
08228 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08229 }
08230
08231 default:
08232 dahdi_disable_ec(p);
08233 return NULL;
08234 }
08235 break;
08236 case DAHDI_EVENT_RINGOFFHOOK:
08237 if (p->inalarm) break;
08238 if (p->oprmode < 0)
08239 {
08240 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08241 {
08242
08243 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08244 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08245 restore_conference(p->oprpeer);
08246 }
08247 break;
08248 }
08249 if (p->radio)
08250 {
08251 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08252 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08253 break;
08254 }
08255
08256
08257 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08258 c = strchr(p->dialdest, '/');
08259 if (c)
08260 c++;
08261 else
08262 c = p->dialdest;
08263 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08264 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08265 if (strlen(p->dop.dialstr) > 4) {
08266 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08267 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08268 p->echorest[sizeof(p->echorest) - 1] = '\0';
08269 p->echobreak = 1;
08270 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08271 } else
08272 p->echobreak = 0;
08273 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08274 int saveerr = errno;
08275
08276 x = DAHDI_ONHOOK;
08277 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08278 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08279 return NULL;
08280 }
08281 p->dialing = 1;
08282 return &p->subs[idx].f;
08283 }
08284 switch (p->sig) {
08285 case SIG_FXOLS:
08286 case SIG_FXOGS:
08287 case SIG_FXOKS:
08288 switch (ast->_state) {
08289 case AST_STATE_RINGING:
08290 dahdi_enable_ec(p);
08291 dahdi_train_ec(p);
08292 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08293 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08294
08295 p->subs[SUB_REAL].needringing = 0;
08296 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08297 ast_debug(1, "channel %d answered\n", p->channel);
08298
08299
08300 ast_free(p->cidspill);
08301 p->cidspill = NULL;
08302 restore_conference(p);
08303
08304 p->dialing = 0;
08305 p->callwaitcas = 0;
08306 if (p->confirmanswer) {
08307
08308 p->subs[idx].f.frametype = AST_FRAME_NULL;
08309 p->subs[idx].f.subclass.integer = 0;
08310 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08311
08312 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08313 if (res < 0) {
08314 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08315 p->dop.dialstr[0] = '\0';
08316 return NULL;
08317 } else {
08318 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08319 p->subs[idx].f.frametype = AST_FRAME_NULL;
08320 p->subs[idx].f.subclass.integer = 0;
08321 p->dialing = 1;
08322 }
08323 p->dop.dialstr[0] = '\0';
08324 ast_setstate(ast, AST_STATE_DIALING);
08325 } else
08326 ast_setstate(ast, AST_STATE_UP);
08327 return &p->subs[idx].f;
08328 case AST_STATE_DOWN:
08329 ast_setstate(ast, AST_STATE_RING);
08330 ast->rings = 1;
08331 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08332 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08333 ast_debug(1, "channel %d picked up\n", p->channel);
08334 return &p->subs[idx].f;
08335 case AST_STATE_UP:
08336
08337 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08338
08339 if (ast_bridged_channel(p->owner))
08340 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08341 p->subs[idx].needunhold = 1;
08342 break;
08343 case AST_STATE_RESERVED:
08344
08345 if (has_voicemail(p))
08346 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08347 else
08348 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08349 break;
08350 default:
08351 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08352 }
08353 break;
08354 case SIG_FXSLS:
08355 case SIG_FXSGS:
08356 case SIG_FXSKS:
08357 if (ast->_state == AST_STATE_RING) {
08358 p->ringt = p->ringt_base;
08359 }
08360
08361
08362
08363 ast_debug(1, "Setting IDLE polarity due "
08364 "to ring. Old polarity was %d\n",
08365 p->polarity);
08366 p->polarity = POLARITY_IDLE;
08367
08368
08369 case SIG_EM:
08370 case SIG_EM_E1:
08371 case SIG_EMWINK:
08372 case SIG_FEATD:
08373 case SIG_FEATDMF:
08374 case SIG_FEATDMF_TA:
08375 case SIG_E911:
08376 case SIG_FGC_CAMA:
08377 case SIG_FGC_CAMAMF:
08378 case SIG_FEATB:
08379 case SIG_SF:
08380 case SIG_SFWINK:
08381 case SIG_SF_FEATD:
08382 case SIG_SF_FEATDMF:
08383 case SIG_SF_FEATB:
08384 if (ast->_state == AST_STATE_PRERING)
08385 ast_setstate(ast, AST_STATE_RING);
08386 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08387 ast_debug(1, "Ring detected\n");
08388 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08389 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08390 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08391 ast_debug(1, "Line answered\n");
08392 if (p->confirmanswer) {
08393 p->subs[idx].f.frametype = AST_FRAME_NULL;
08394 p->subs[idx].f.subclass.integer = 0;
08395 } else {
08396 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08397 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08398 ast_setstate(ast, AST_STATE_UP);
08399 }
08400 } else if (ast->_state != AST_STATE_RING)
08401 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08402 break;
08403 default:
08404 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08405 }
08406 break;
08407 case DAHDI_EVENT_RINGBEGIN:
08408 switch (p->sig) {
08409 case SIG_FXSLS:
08410 case SIG_FXSGS:
08411 case SIG_FXSKS:
08412 if (ast->_state == AST_STATE_RING) {
08413 p->ringt = p->ringt_base;
08414 }
08415 break;
08416 }
08417 break;
08418 case DAHDI_EVENT_RINGERON:
08419 break;
08420 case DAHDI_EVENT_NOALARM:
08421 switch (p->sig) {
08422 #if defined(HAVE_PRI)
08423 case SIG_PRI_LIB_HANDLE_CASES:
08424 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08425 break;
08426 #endif
08427 #if defined(HAVE_SS7)
08428 case SIG_SS7:
08429 sig_ss7_set_alarm(p->sig_pvt, 0);
08430 break;
08431 #endif
08432 default:
08433 p->inalarm = 0;
08434 break;
08435 }
08436 handle_clear_alarms(p);
08437 break;
08438 case DAHDI_EVENT_WINKFLASH:
08439 if (p->inalarm) break;
08440 if (p->radio) break;
08441 if (p->oprmode < 0) break;
08442 if (p->oprmode > 1)
08443 {
08444 struct dahdi_params par;
08445
08446 memset(&par, 0, sizeof(par));
08447 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08448 {
08449 if (!par.rxisoffhook)
08450 {
08451
08452 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08453 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08454 save_conference(p);
08455 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08456 }
08457 }
08458 break;
08459 }
08460
08461 p->flashtime = ast_tvnow();
08462 switch (mysig) {
08463 case SIG_FXOLS:
08464 case SIG_FXOGS:
08465 case SIG_FXOKS:
08466 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08467 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08468
08469
08470 ast_free(p->cidspill);
08471 p->cidspill = NULL;
08472 restore_conference(p);
08473 p->callwaitcas = 0;
08474
08475 if (idx != SUB_REAL) {
08476 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08477 goto winkflashdone;
08478 }
08479
08480 if (p->subs[SUB_CALLWAIT].owner) {
08481
08482 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08483 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08484 p->owner = p->subs[SUB_REAL].owner;
08485 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08486 if (p->owner->_state == AST_STATE_RINGING) {
08487 ast_setstate(p->owner, AST_STATE_UP);
08488 p->subs[SUB_REAL].needanswer = 1;
08489 }
08490 p->callwaitingrepeat = 0;
08491 p->cidcwexpire = 0;
08492 p->cid_suppress_expire = 0;
08493
08494 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08495 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08496 S_OR(p->mohsuggest, NULL),
08497 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08498 }
08499 p->subs[SUB_CALLWAIT].needhold = 1;
08500 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08501 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08502 S_OR(p->mohsuggest, NULL),
08503 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08504 }
08505 p->subs[SUB_REAL].needunhold = 1;
08506 } else if (!p->subs[SUB_THREEWAY].owner) {
08507 if (!p->threewaycalling) {
08508
08509 p->subs[SUB_REAL].needflash = 1;
08510 goto winkflashdone;
08511 } else if (!check_for_conference(p)) {
08512 char cid_num[256];
08513 char cid_name[256];
08514
08515 cid_num[0] = 0;
08516 cid_name[0] = 0;
08517 if (p->dahditrcallerid && p->owner) {
08518 if (p->owner->caller.id.number.valid
08519 && p->owner->caller.id.number.str) {
08520 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08521 sizeof(cid_num));
08522 }
08523 if (p->owner->caller.id.name.valid
08524 && p->owner->caller.id.name.str) {
08525 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08526 sizeof(cid_name));
08527 }
08528 }
08529
08530
08531 if (!((ast->pbx) ||
08532 (ast->_state == AST_STATE_UP) ||
08533 (ast->_state == AST_STATE_RING))) {
08534 ast_debug(1, "Flash when call not up or ringing\n");
08535 goto winkflashdone;
08536 }
08537 if (alloc_sub(p, SUB_THREEWAY)) {
08538 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08539 goto winkflashdone;
08540 }
08541
08542
08543
08544
08545
08546
08547
08548 ast_mutex_unlock(&p->lock);
08549 ast_channel_unlock(ast);
08550 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08551 ast_channel_lock(ast);
08552 ast_mutex_lock(&p->lock);
08553 if (p->dahditrcallerid) {
08554 if (!p->origcid_num)
08555 p->origcid_num = ast_strdup(p->cid_num);
08556 if (!p->origcid_name)
08557 p->origcid_name = ast_strdup(p->cid_name);
08558 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08559 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08560 }
08561
08562 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08563
08564 dahdi_disable_ec(p);
08565 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08566 if (res)
08567 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08568 p->owner = chan;
08569 if (!chan) {
08570 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08571 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08572 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08573 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08574 dahdi_enable_ec(p);
08575 ast_hangup(chan);
08576 } else {
08577 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08578
08579
08580 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08581 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08582 S_OR(p->mohsuggest, NULL),
08583 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08584 }
08585 p->subs[SUB_THREEWAY].needhold = 1;
08586 }
08587 }
08588 } else {
08589
08590 if (p->subs[SUB_THREEWAY].inthreeway) {
08591
08592 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08593
08594 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08595
08596 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08597 p->owner = p->subs[SUB_REAL].owner;
08598 }
08599
08600 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08601 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08602 p->subs[SUB_REAL].inthreeway = 0;
08603 p->subs[SUB_THREEWAY].inthreeway = 0;
08604 } else {
08605
08606 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08607 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08608 int otherindex = SUB_THREEWAY;
08609
08610 ast_verb(3, "Building conference call with %s and %s\n",
08611 p->subs[SUB_THREEWAY].owner->name,
08612 p->subs[SUB_REAL].owner->name);
08613
08614 p->subs[SUB_THREEWAY].inthreeway = 1;
08615 p->subs[SUB_REAL].inthreeway = 1;
08616 if (ast->_state == AST_STATE_UP) {
08617 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08618 otherindex = SUB_REAL;
08619 }
08620 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08621 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08622 p->subs[otherindex].needunhold = 1;
08623 p->owner = p->subs[SUB_REAL].owner;
08624 } else {
08625 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08626 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08627 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08628 p->owner = p->subs[SUB_REAL].owner;
08629 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08630 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08631 p->subs[SUB_REAL].needunhold = 1;
08632 dahdi_enable_ec(p);
08633 }
08634 }
08635 }
08636 winkflashdone:
08637 update_conf(p);
08638 break;
08639 case SIG_EM:
08640 case SIG_EM_E1:
08641 case SIG_FEATD:
08642 case SIG_SF:
08643 case SIG_SFWINK:
08644 case SIG_SF_FEATD:
08645 case SIG_FXSLS:
08646 case SIG_FXSGS:
08647 if (p->dialing)
08648 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08649 else
08650 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08651 break;
08652 case SIG_FEATDMF_TA:
08653 switch (p->whichwink) {
08654 case 0:
08655 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08656 S_COR(p->owner->caller.ani.number.valid,
08657 p->owner->caller.ani.number.str, ""));
08658 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08659 p->owner->caller.ani2,
08660 S_COR(p->owner->caller.ani.number.valid,
08661 p->owner->caller.ani.number.str, ""));
08662 break;
08663 case 1:
08664 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08665 break;
08666 case 2:
08667 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08668 return NULL;
08669 }
08670 p->whichwink++;
08671
08672 case SIG_FEATDMF:
08673 case SIG_E911:
08674 case SIG_FGC_CAMAMF:
08675 case SIG_FGC_CAMA:
08676 case SIG_FEATB:
08677 case SIG_SF_FEATDMF:
08678 case SIG_SF_FEATB:
08679 case SIG_EMWINK:
08680
08681 if (!ast_strlen_zero(p->dop.dialstr)) {
08682 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08683 if (res < 0) {
08684 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08685 p->dop.dialstr[0] = '\0';
08686 return NULL;
08687 } else
08688 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08689 }
08690 p->dop.dialstr[0] = '\0';
08691 break;
08692 default:
08693 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08694 }
08695 break;
08696 case DAHDI_EVENT_HOOKCOMPLETE:
08697 if (p->inalarm) break;
08698 if ((p->radio || (p->oprmode < 0))) break;
08699 if (p->waitingfordt.tv_sec) break;
08700 switch (mysig) {
08701 case SIG_FXSLS:
08702 case SIG_FXSGS:
08703 case SIG_FXSKS:
08704 case SIG_EM:
08705 case SIG_EM_E1:
08706 case SIG_EMWINK:
08707 case SIG_FEATD:
08708 case SIG_SF:
08709 case SIG_SFWINK:
08710 case SIG_SF_FEATD:
08711 if (!ast_strlen_zero(p->dop.dialstr)) {
08712 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08713 if (res < 0) {
08714 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08715 p->dop.dialstr[0] = '\0';
08716 return NULL;
08717 } else
08718 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08719 }
08720 p->dop.dialstr[0] = '\0';
08721 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08722 break;
08723 case SIG_FEATDMF:
08724 case SIG_FEATDMF_TA:
08725 case SIG_E911:
08726 case SIG_FGC_CAMA:
08727 case SIG_FGC_CAMAMF:
08728 case SIG_FEATB:
08729 case SIG_SF_FEATDMF:
08730 case SIG_SF_FEATB:
08731 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08732 break;
08733 default:
08734 break;
08735 }
08736 break;
08737 case DAHDI_EVENT_POLARITY:
08738
08739
08740
08741
08742
08743
08744 if (p->polarity == POLARITY_IDLE) {
08745 p->polarity = POLARITY_REV;
08746 if (p->answeronpolarityswitch &&
08747 ((ast->_state == AST_STATE_DIALING) ||
08748 (ast->_state == AST_STATE_RINGING))) {
08749 ast_debug(1, "Answering on polarity switch!\n");
08750 ast_setstate(p->owner, AST_STATE_UP);
08751 if (p->hanguponpolarityswitch) {
08752 p->polaritydelaytv = ast_tvnow();
08753 }
08754 } else
08755 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08756 }
08757
08758
08759 if (p->hanguponpolarityswitch &&
08760 (p->polarityonanswerdelay > 0) &&
08761 (p->polarity == POLARITY_REV) &&
08762 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08763
08764 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) );
08765
08766 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08767 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08768 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08769 p->polarity = POLARITY_IDLE;
08770 } else
08771 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);
08772
08773 } else {
08774 p->polarity = POLARITY_IDLE;
08775 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08776 }
08777
08778 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) );
08779 break;
08780 default:
08781 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08782 }
08783 return &p->subs[idx].f;
08784 }
08785
08786 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08787 {
08788 int res;
08789 int idx;
08790 struct ast_frame *f;
08791 int usedindex = -1;
08792 struct dahdi_pvt *p = ast->tech_pvt;
08793
08794 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08795 idx = SUB_REAL;
08796 }
08797
08798 p->subs[idx].f.frametype = AST_FRAME_NULL;
08799 p->subs[idx].f.datalen = 0;
08800 p->subs[idx].f.samples = 0;
08801 p->subs[idx].f.mallocd = 0;
08802 p->subs[idx].f.offset = 0;
08803 p->subs[idx].f.subclass.integer = 0;
08804 p->subs[idx].f.delivery = ast_tv(0,0);
08805 p->subs[idx].f.src = "dahdi_exception";
08806 p->subs[idx].f.data.ptr = NULL;
08807
08808
08809 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08810
08811
08812
08813
08814
08815 if (p->fake_event) {
08816 res = p->fake_event;
08817 p->fake_event = 0;
08818 } else
08819 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08820
08821 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08822 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08823 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08824 p->owner = p->subs[SUB_REAL].owner;
08825 if (p->owner && ast_bridged_channel(p->owner))
08826 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08827 p->subs[SUB_REAL].needunhold = 1;
08828 }
08829 switch (res) {
08830 case DAHDI_EVENT_ONHOOK:
08831 dahdi_disable_ec(p);
08832 if (p->owner) {
08833 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08834 dahdi_ring_phone(p);
08835 p->callwaitingrepeat = 0;
08836 p->cidcwexpire = 0;
08837 p->cid_suppress_expire = 0;
08838 } else
08839 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08840 update_conf(p);
08841 break;
08842 case DAHDI_EVENT_RINGOFFHOOK:
08843 dahdi_enable_ec(p);
08844 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08845 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08846 p->subs[SUB_REAL].needanswer = 1;
08847 p->dialing = 0;
08848 }
08849 break;
08850 case DAHDI_EVENT_HOOKCOMPLETE:
08851 case DAHDI_EVENT_RINGERON:
08852 case DAHDI_EVENT_RINGEROFF:
08853
08854 break;
08855 case DAHDI_EVENT_WINKFLASH:
08856 p->flashtime = ast_tvnow();
08857 if (p->owner) {
08858 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08859 if (p->owner->_state != AST_STATE_UP) {
08860
08861 usedindex = dahdi_get_index(p->owner, p, 0);
08862 if (usedindex > -1) {
08863 p->subs[usedindex].needanswer = 1;
08864 }
08865 ast_setstate(p->owner, AST_STATE_UP);
08866 }
08867 p->callwaitingrepeat = 0;
08868 p->cidcwexpire = 0;
08869 p->cid_suppress_expire = 0;
08870 if (ast_bridged_channel(p->owner))
08871 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08872 p->subs[SUB_REAL].needunhold = 1;
08873 } else
08874 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08875 update_conf(p);
08876 break;
08877 default:
08878 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08879 }
08880 f = &p->subs[idx].f;
08881 return f;
08882 }
08883 if (!(p->radio || (p->oprmode < 0)))
08884 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08885
08886 if (ast != p->owner) {
08887 if (p->owner) {
08888 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08889 }
08890 f = &p->subs[idx].f;
08891 return f;
08892 }
08893
08894 f = dahdi_handle_event(ast);
08895 if (!f) {
08896 const char *name = ast_strdupa(ast->name);
08897
08898
08899 ast_mutex_unlock(&p->lock);
08900 ast_channel_unlock(ast);
08901 ast_set_hangupsource(ast, name, 0);
08902 ast_channel_lock(ast);
08903 ast_mutex_lock(&p->lock);
08904 }
08905 return f;
08906 }
08907
08908 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08909 {
08910 struct dahdi_pvt *p = ast->tech_pvt;
08911 struct ast_frame *f;
08912 ast_mutex_lock(&p->lock);
08913 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08914 struct analog_pvt *analog_p = p->sig_pvt;
08915 f = analog_exception(analog_p, ast);
08916 } else {
08917 f = __dahdi_exception(ast);
08918 }
08919 ast_mutex_unlock(&p->lock);
08920 return f;
08921 }
08922
08923 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08924 {
08925 struct dahdi_pvt *p;
08926 int res;
08927 int idx;
08928 void *readbuf;
08929 struct ast_frame *f;
08930
08931
08932
08933
08934
08935
08936 p = ast->tech_pvt;
08937 while (ast_mutex_trylock(&p->lock)) {
08938 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08939
08940
08941
08942
08943
08944
08945 p = ast->tech_pvt;
08946 }
08947
08948 idx = dahdi_get_index(ast, p, 0);
08949
08950
08951 if (idx < 0) {
08952 ast_log(LOG_WARNING, "We don't exist?\n");
08953 ast_mutex_unlock(&p->lock);
08954 return NULL;
08955 }
08956
08957 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08958 ast_mutex_unlock(&p->lock);
08959 return NULL;
08960 }
08961
08962 p->subs[idx].f.frametype = AST_FRAME_NULL;
08963 p->subs[idx].f.datalen = 0;
08964 p->subs[idx].f.samples = 0;
08965 p->subs[idx].f.mallocd = 0;
08966 p->subs[idx].f.offset = 0;
08967 p->subs[idx].f.subclass.integer = 0;
08968 p->subs[idx].f.delivery = ast_tv(0,0);
08969 p->subs[idx].f.src = "dahdi_read";
08970 p->subs[idx].f.data.ptr = NULL;
08971
08972
08973 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08974 {
08975 struct dahdi_params ps;
08976
08977 memset(&ps, 0, sizeof(ps));
08978 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08979 ast_mutex_unlock(&p->lock);
08980 return NULL;
08981 }
08982 p->firstradio = 1;
08983 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08984 if (ps.rxisoffhook)
08985 {
08986 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08987 }
08988 else
08989 {
08990 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08991 }
08992 ast_mutex_unlock(&p->lock);
08993 return &p->subs[idx].f;
08994 }
08995 if (p->ringt > 0) {
08996 if (!(--p->ringt)) {
08997 ast_mutex_unlock(&p->lock);
08998 return NULL;
08999 }
09000 }
09001
09002 #ifdef HAVE_OPENR2
09003 if (p->mfcr2) {
09004 openr2_chan_process_event(p->r2chan);
09005 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09006 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09007
09008
09009 if (p->mfcr2_call_accepted &&
09010 !p->mfcr2_progress &&
09011 ast->_state == AST_STATE_RINGING) {
09012 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09013 ast_queue_frame(p->owner, &f);
09014 p->mfcr2_progress = 1;
09015 }
09016 }
09017 }
09018 #endif
09019
09020 if (p->subs[idx].needringing) {
09021
09022 p->subs[idx].needringing = 0;
09023 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09024 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09025 ast_setstate(ast, AST_STATE_RINGING);
09026 ast_mutex_unlock(&p->lock);
09027 return &p->subs[idx].f;
09028 }
09029
09030 if (p->subs[idx].needbusy) {
09031
09032 p->subs[idx].needbusy = 0;
09033 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09034 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09035 ast_mutex_unlock(&p->lock);
09036 return &p->subs[idx].f;
09037 }
09038
09039 if (p->subs[idx].needcongestion) {
09040
09041 p->subs[idx].needcongestion = 0;
09042 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09043 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09044 ast_mutex_unlock(&p->lock);
09045 return &p->subs[idx].f;
09046 }
09047
09048 if (p->subs[idx].needanswer) {
09049
09050 p->subs[idx].needanswer = 0;
09051 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09052 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09053 ast_mutex_unlock(&p->lock);
09054 return &p->subs[idx].f;
09055 }
09056 #ifdef HAVE_OPENR2
09057 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09058
09059
09060
09061
09062 ast_mutex_unlock(&p->lock);
09063 return &ast_null_frame;
09064 }
09065 #endif
09066
09067 if (p->subs[idx].needflash) {
09068
09069 p->subs[idx].needflash = 0;
09070 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09071 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09072 ast_mutex_unlock(&p->lock);
09073 return &p->subs[idx].f;
09074 }
09075
09076 if (p->subs[idx].needhold) {
09077
09078 p->subs[idx].needhold = 0;
09079 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09080 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09081 ast_mutex_unlock(&p->lock);
09082 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09083 return &p->subs[idx].f;
09084 }
09085
09086 if (p->subs[idx].needunhold) {
09087
09088 p->subs[idx].needunhold = 0;
09089 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09090 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09091 ast_mutex_unlock(&p->lock);
09092 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09093 return &p->subs[idx].f;
09094 }
09095
09096
09097
09098
09099
09100 if (p->fake_event && p->owner == ast) {
09101 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09102 struct analog_pvt *analog_p = p->sig_pvt;
09103
09104 f = analog_exception(analog_p, ast);
09105 } else {
09106 f = __dahdi_exception(ast);
09107 }
09108 ast_mutex_unlock(&p->lock);
09109 return f;
09110 }
09111
09112 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09113 if (!p->subs[idx].linear) {
09114 p->subs[idx].linear = 1;
09115 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09116 if (res)
09117 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09118 }
09119 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09120 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09121 if (p->subs[idx].linear) {
09122 p->subs[idx].linear = 0;
09123 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09124 if (res)
09125 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09126 }
09127 } else {
09128 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09129 ast_mutex_unlock(&p->lock);
09130 return NULL;
09131 }
09132 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09133 CHECK_BLOCKING(ast);
09134 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09135 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09136
09137 if (res < 0) {
09138 f = NULL;
09139 if (res == -1) {
09140 if (errno == EAGAIN) {
09141
09142 ast_mutex_unlock(&p->lock);
09143 return &p->subs[idx].f;
09144 } else if (errno == ELAST) {
09145 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09146 struct analog_pvt *analog_p = p->sig_pvt;
09147 f = analog_exception(analog_p, ast);
09148 } else {
09149 f = __dahdi_exception(ast);
09150 }
09151 } else
09152 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09153 }
09154 ast_mutex_unlock(&p->lock);
09155 return f;
09156 }
09157 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09158 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09159 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09160 struct analog_pvt *analog_p = p->sig_pvt;
09161 f = analog_exception(analog_p, ast);
09162 } else {
09163 f = __dahdi_exception(ast);
09164 }
09165 ast_mutex_unlock(&p->lock);
09166 return f;
09167 }
09168 if (p->tdd) {
09169 int c;
09170
09171 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09172 if (c < 0) {
09173 ast_debug(1,"tdd_feed failed\n");
09174 ast_mutex_unlock(&p->lock);
09175 return NULL;
09176 }
09177 if (c) {
09178 p->subs[idx].f.subclass.integer = 0;
09179 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09180 p->subs[idx].f.mallocd = 0;
09181 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09182 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09183 p->subs[idx].f.datalen = 1;
09184 *((char *) p->subs[idx].f.data.ptr) = c;
09185 ast_mutex_unlock(&p->lock);
09186 return &p->subs[idx].f;
09187 }
09188 }
09189 if (idx == SUB_REAL) {
09190
09191 if (p->cidcwexpire) {
09192 if (!--p->cidcwexpire) {
09193
09194 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09195 restore_conference(p);
09196 }
09197 }
09198 if (p->cid_suppress_expire) {
09199 --p->cid_suppress_expire;
09200 }
09201 if (p->callwaitingrepeat) {
09202 if (!--p->callwaitingrepeat) {
09203
09204 ++p->callwaitrings;
09205 dahdi_callwait(ast);
09206 }
09207 }
09208 }
09209 if (p->subs[idx].linear) {
09210 p->subs[idx].f.datalen = READ_SIZE * 2;
09211 } else
09212 p->subs[idx].f.datalen = READ_SIZE;
09213
09214
09215 if ((p->owner == ast) && p->cidspill) {
09216 send_callerid(p);
09217 }
09218
09219 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09220 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09221 p->subs[idx].f.samples = READ_SIZE;
09222 p->subs[idx].f.mallocd = 0;
09223 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09224 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09225 #if 0
09226 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09227 #endif
09228 if (p->dialing || p->radio ||
09229 (idx && (ast->_state != AST_STATE_UP)) ||
09230 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09231 ) {
09232
09233
09234 p->subs[idx].f.frametype = AST_FRAME_NULL;
09235 p->subs[idx].f.subclass.integer = 0;
09236 p->subs[idx].f.samples = 0;
09237 p->subs[idx].f.mallocd = 0;
09238 p->subs[idx].f.offset = 0;
09239 p->subs[idx].f.data.ptr = NULL;
09240 p->subs[idx].f.datalen= 0;
09241 }
09242 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09243
09244 int mute;
09245
09246 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09247
09248
09249 mute = ast_dsp_was_muted(p->dsp);
09250 if (p->muting != mute) {
09251 p->muting = mute;
09252 dahdi_confmute(p, mute);
09253 }
09254
09255 if (f) {
09256 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09257 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09258
09259
09260 ast_frfree(f);
09261 f = NULL;
09262 }
09263 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09264 || f->frametype == AST_FRAME_DTMF_END) {
09265 #ifdef HAVE_PRI
09266 if (dahdi_sig_pri_lib_handles(p->sig)
09267 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09268 && p->pri
09269 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09270 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09271
09272 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09273 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09274 f->subclass.integer, f->subclass.integer, ast->name);
09275
09276 f->frametype = AST_FRAME_NULL;
09277 f->subclass.integer = 0;
09278 }
09279 #endif
09280
09281 p->pulsedial = 0;
09282 } else if (p->waitingfordt.tv_sec) {
09283 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09284 p->waitingfordt.tv_sec = 0;
09285 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09286 ast_frfree(f);
09287 f = NULL;
09288 } else if (f->frametype == AST_FRAME_VOICE) {
09289 f->frametype = AST_FRAME_NULL;
09290 f->subclass.integer = 0;
09291 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) {
09292 p->waitingfordt.tv_sec = 0;
09293 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09294 ast_dsp_set_features(p->dsp, p->dsp_features);
09295 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09296 if (!ast_strlen_zero(p->dop.dialstr)) {
09297 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09298 if (res < 0) {
09299 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09300 p->dop.dialstr[0] = '\0';
09301 ast_mutex_unlock(&p->lock);
09302 ast_frfree(f);
09303 return NULL;
09304 } else {
09305 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09306 p->dialing = 1;
09307 p->dop.dialstr[0] = '\0';
09308 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09309 ast_setstate(ast, AST_STATE_DIALING);
09310 }
09311 }
09312 }
09313 }
09314 }
09315 }
09316 } else
09317 f = &p->subs[idx].f;
09318
09319 if (f) {
09320 switch (f->frametype) {
09321 case AST_FRAME_DTMF_BEGIN:
09322 case AST_FRAME_DTMF_END:
09323 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09324 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09325 } else {
09326 dahdi_handle_dtmf(ast, idx, &f);
09327 }
09328 break;
09329 case AST_FRAME_VOICE:
09330 if (p->cidspill || p->cid_suppress_expire) {
09331
09332 p->subs[idx].f.frametype = AST_FRAME_NULL;
09333 p->subs[idx].f.subclass.integer = 0;
09334 p->subs[idx].f.samples = 0;
09335 p->subs[idx].f.mallocd = 0;
09336 p->subs[idx].f.offset = 0;
09337 p->subs[idx].f.data.ptr = NULL;
09338 p->subs[idx].f.datalen= 0;
09339 }
09340 break;
09341 default:
09342 break;
09343 }
09344 }
09345
09346 ast_mutex_unlock(&p->lock);
09347 return f;
09348 }
09349
09350 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09351 {
09352 int sent=0;
09353 int size;
09354 int res;
09355 int fd;
09356 fd = p->subs[idx].dfd;
09357 while (len) {
09358 size = len;
09359 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09360 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09361 res = write(fd, buf, size);
09362 if (res != size) {
09363 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09364 return sent;
09365 }
09366 len -= size;
09367 buf += size;
09368 }
09369 return sent;
09370 }
09371
09372 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09373 {
09374 struct dahdi_pvt *p = ast->tech_pvt;
09375 int res;
09376 int idx;
09377 idx = dahdi_get_index(ast, p, 0);
09378 if (idx < 0) {
09379 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09380 return -1;
09381 }
09382
09383
09384 if (frame->frametype != AST_FRAME_VOICE) {
09385 if (frame->frametype != AST_FRAME_IMAGE)
09386 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09387 return 0;
09388 }
09389 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09390 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09391 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09392 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09393 return -1;
09394 }
09395 if (p->dialing) {
09396 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09397 return 0;
09398 }
09399 if (!p->owner) {
09400 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09401 return 0;
09402 }
09403 if (p->cidspill) {
09404 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09405 ast->name);
09406 return 0;
09407 }
09408
09409 if (!frame->data.ptr || !frame->datalen)
09410 return 0;
09411
09412 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09413 if (!p->subs[idx].linear) {
09414 p->subs[idx].linear = 1;
09415 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09416 if (res)
09417 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09418 }
09419 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09420 } else {
09421
09422 if (p->subs[idx].linear) {
09423 p->subs[idx].linear = 0;
09424 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09425 if (res)
09426 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09427 }
09428 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09429 }
09430 if (res < 0) {
09431 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09432 return -1;
09433 }
09434 return 0;
09435 }
09436
09437 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09438 {
09439 struct dahdi_pvt *p = chan->tech_pvt;
09440 int res=-1;
09441 int idx;
09442 int func = DAHDI_FLASH;
09443
09444 ast_mutex_lock(&p->lock);
09445 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09446 switch (p->sig) {
09447 #if defined(HAVE_PRI)
09448 case SIG_PRI_LIB_HANDLE_CASES:
09449 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09450 ast_mutex_unlock(&p->lock);
09451 return res;
09452 #endif
09453 #if defined(HAVE_SS7)
09454 case SIG_SS7:
09455 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09456 ast_mutex_unlock(&p->lock);
09457 return res;
09458 #endif
09459 default:
09460 break;
09461 }
09462 #ifdef HAVE_OPENR2
09463 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09464 ast_mutex_unlock(&p->lock);
09465
09466
09467 return 0;
09468 }
09469 #endif
09470 idx = dahdi_get_index(chan, p, 0);
09471 if (idx == SUB_REAL) {
09472 switch (condition) {
09473 case AST_CONTROL_BUSY:
09474 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09475 break;
09476 case AST_CONTROL_RINGING:
09477 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09478
09479 if (chan->_state != AST_STATE_UP) {
09480 if ((chan->_state != AST_STATE_RING) ||
09481 ((p->sig != SIG_FXSKS) &&
09482 (p->sig != SIG_FXSLS) &&
09483 (p->sig != SIG_FXSGS)))
09484 ast_setstate(chan, AST_STATE_RINGING);
09485 }
09486 break;
09487 case AST_CONTROL_INCOMPLETE:
09488 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09489
09490 res = 0;
09491 break;
09492 case AST_CONTROL_PROCEEDING:
09493 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09494
09495 res = 0;
09496 break;
09497 case AST_CONTROL_PROGRESS:
09498 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09499
09500 res = 0;
09501 break;
09502 case AST_CONTROL_CONGESTION:
09503
09504 switch (chan->hangupcause) {
09505 case AST_CAUSE_USER_BUSY:
09506 case AST_CAUSE_NORMAL_CLEARING:
09507 case 0:
09508
09509 chan->hangupcause = AST_CAUSE_CONGESTION;
09510 break;
09511 default:
09512 break;
09513 }
09514 break;
09515 case AST_CONTROL_HOLD:
09516 ast_moh_start(chan, data, p->mohinterpret);
09517 break;
09518 case AST_CONTROL_UNHOLD:
09519 ast_moh_stop(chan);
09520 break;
09521 case AST_CONTROL_RADIO_KEY:
09522 if (p->radio)
09523 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09524 res = 0;
09525 break;
09526 case AST_CONTROL_RADIO_UNKEY:
09527 if (p->radio)
09528 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09529 res = 0;
09530 break;
09531 case AST_CONTROL_FLASH:
09532
09533 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09534
09535 p->dop.dialstr[0] = '\0';
09536 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09537 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09538 chan->name, strerror(errno));
09539 } else
09540 res = 0;
09541 } else
09542 res = 0;
09543 break;
09544 case AST_CONTROL_SRCUPDATE:
09545 res = 0;
09546 break;
09547 case -1:
09548 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09549 break;
09550 }
09551 } else {
09552 res = 0;
09553 }
09554 ast_mutex_unlock(&p->lock);
09555 return res;
09556 }
09557
09558 #if defined(HAVE_PRI)
09559 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09560 #else
09561 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09562 #endif
09563 {
09564 struct ast_str *chan_name;
09565 int x, y;
09566
09567
09568 if (!(chan_name = ast_str_create(32))) {
09569 return NULL;
09570 }
09571 if (i->channel == CHAN_PSEUDO) {
09572 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09573 #if defined(HAVE_PRI)
09574 } else if (i->pri) {
09575 ast_mutex_lock(&i->pri->lock);
09576 y = ++i->pri->new_chan_seq;
09577 if (is_outgoing) {
09578 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09579 address[0] = '\0';
09580 } else if (ast_strlen_zero(i->cid_subaddr)) {
09581
09582 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09583 } else {
09584
09585 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09586 i->cid_subaddr, y);
09587 }
09588 ast_mutex_unlock(&i->pri->lock);
09589 #endif
09590 } else {
09591 y = 1;
09592 do {
09593 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09594 for (x = 0; x < 3; ++x) {
09595 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09596 i->subs[x].owner->name + 6)) {
09597 break;
09598 }
09599 }
09600 ++y;
09601 } while (x < 3);
09602 }
09603 return chan_name;
09604 }
09605
09606 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09607 {
09608 struct ast_channel *tmp;
09609 format_t deflaw;
09610 int x;
09611 int features;
09612 struct ast_str *chan_name;
09613 struct ast_variable *v;
09614 char *dashptr;
09615 char device_name[AST_CHANNEL_NAME];
09616
09617 if (i->subs[idx].owner) {
09618 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09619 return NULL;
09620 }
09621
09622 #if defined(HAVE_PRI)
09623
09624
09625
09626
09627 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09628 #else
09629 chan_name = create_channel_name(i);
09630 #endif
09631 if (!chan_name) {
09632 return NULL;
09633 }
09634
09635 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));
09636 ast_free(chan_name);
09637 if (!tmp)
09638 return NULL;
09639 tmp->tech = &dahdi_tech;
09640 #if defined(HAVE_PRI)
09641 if (i->pri) {
09642 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09643 }
09644 #endif
09645 ast_channel_cc_params_init(tmp, i->cc_params);
09646 if (law) {
09647 i->law = law;
09648 if (law == DAHDI_LAW_ALAW) {
09649 deflaw = AST_FORMAT_ALAW;
09650 } else {
09651 deflaw = AST_FORMAT_ULAW;
09652 }
09653 } else {
09654 switch (i->sig) {
09655 case SIG_PRI_LIB_HANDLE_CASES:
09656
09657 i->law = (i->law_default == DAHDI_LAW_ALAW)
09658 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09659 break;
09660 default:
09661 i->law = i->law_default;
09662 break;
09663 }
09664 if (i->law_default == DAHDI_LAW_ALAW) {
09665 deflaw = AST_FORMAT_ALAW;
09666 } else {
09667 deflaw = AST_FORMAT_ULAW;
09668 }
09669 }
09670 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09671 tmp->nativeformats = deflaw;
09672
09673 tmp->rawreadformat = deflaw;
09674 tmp->readformat = deflaw;
09675 tmp->rawwriteformat = deflaw;
09676 tmp->writeformat = deflaw;
09677 i->subs[idx].linear = 0;
09678 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09679 features = 0;
09680 if (idx == SUB_REAL) {
09681 if (i->busydetect && CANBUSYDETECT(i))
09682 features |= DSP_FEATURE_BUSY_DETECT;
09683 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09684 features |= DSP_FEATURE_CALL_PROGRESS;
09685 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09686 features |= DSP_FEATURE_WAITDIALTONE;
09687 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09688 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09689 features |= DSP_FEATURE_FAX_DETECT;
09690 }
09691 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09692 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09693 i->hardwaredtmf = 0;
09694 features |= DSP_FEATURE_DIGIT_DETECT;
09695 } else if (NEED_MFDETECT(i)) {
09696 i->hardwaredtmf = 1;
09697 features |= DSP_FEATURE_DIGIT_DETECT;
09698 }
09699 }
09700 if (features) {
09701 if (i->dsp) {
09702 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09703 } else {
09704 if (i->channel != CHAN_PSEUDO)
09705 i->dsp = ast_dsp_new();
09706 else
09707 i->dsp = NULL;
09708 if (i->dsp) {
09709 i->dsp_features = features;
09710 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09711
09712 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09713
09714
09715 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09716 features = 0;
09717 }
09718 #endif
09719 ast_dsp_set_features(i->dsp, features);
09720 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09721 if (!ast_strlen_zero(progzone))
09722 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09723 if (i->busydetect && CANBUSYDETECT(i)) {
09724 if(i->silencethreshold > 0)
09725 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09726 ast_dsp_set_busy_count(i->dsp, i->busycount);
09727 if(i->busytonelength > 0)
09728 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09729 if((i->busytonelength == i->busyquietlength) && i->busycompare)
09730 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09731 }
09732 }
09733 }
09734 }
09735
09736 if (state == AST_STATE_RING)
09737 tmp->rings = 1;
09738 tmp->tech_pvt = i;
09739 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09740
09741 tmp->callgroup = i->callgroup;
09742 tmp->pickupgroup = i->pickupgroup;
09743 }
09744 if (!ast_strlen_zero(i->parkinglot))
09745 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09746 if (!ast_strlen_zero(i->language))
09747 ast_string_field_set(tmp, language, i->language);
09748 if (!i->owner)
09749 i->owner = tmp;
09750 if (!ast_strlen_zero(i->accountcode))
09751 ast_string_field_set(tmp, accountcode, i->accountcode);
09752 if (i->amaflags)
09753 tmp->amaflags = i->amaflags;
09754 i->subs[idx].owner = tmp;
09755 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09756 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09757 ast_string_field_set(tmp, call_forward, i->call_forward);
09758 }
09759
09760 if (!i->adsi)
09761 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09762 if (!ast_strlen_zero(i->exten))
09763 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09764 if (!ast_strlen_zero(i->rdnis)) {
09765 tmp->redirecting.from.number.valid = 1;
09766 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09767 }
09768 if (!ast_strlen_zero(i->dnid)) {
09769 tmp->dialed.number.str = ast_strdup(i->dnid);
09770 }
09771
09772
09773
09774 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09775 if (!ast_strlen_zero(i->cid_ani)) {
09776 tmp->caller.ani.number.valid = 1;
09777 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09778 } else if (!ast_strlen_zero(i->cid_num)) {
09779 tmp->caller.ani.number.valid = 1;
09780 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09781 }
09782 #else
09783 if (!ast_strlen_zero(i->cid_num)) {
09784 tmp->caller.ani.number.valid = 1;
09785 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09786 }
09787 #endif
09788 tmp->caller.id.name.presentation = i->callingpres;
09789 tmp->caller.id.number.presentation = i->callingpres;
09790 tmp->caller.id.number.plan = i->cid_ton;
09791 tmp->caller.ani2 = i->cid_ani2;
09792 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09793
09794 i->fake_event = 0;
09795
09796 dahdi_confmute(i, 0);
09797 i->muting = 0;
09798
09799 ast_jb_configure(tmp, &global_jbconf);
09800
09801
09802 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09803 dashptr = strrchr(device_name, '-');
09804 if (dashptr) {
09805 *dashptr = '\0';
09806 }
09807 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09808
09809 for (v = i->vars ; v ; v = v->next)
09810 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09811
09812 ast_module_ref(ast_module_info->self);
09813
09814 dahdi_ami_channel_event(i, tmp);
09815 if (startpbx) {
09816 #ifdef HAVE_OPENR2
09817 if (i->mfcr2call) {
09818 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09819 }
09820 #endif
09821 if (ast_pbx_start(tmp)) {
09822 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09823 ast_hangup(tmp);
09824 return NULL;
09825 }
09826 }
09827 return tmp;
09828 }
09829
09830
09831 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09832 {
09833 char c;
09834
09835 *str = 0;
09836 for (;;)
09837 {
09838
09839 c = ast_waitfordigit(chan, ms);
09840
09841 if (c < 1)
09842 return c;
09843 *str++ = c;
09844 *str = 0;
09845 if (strchr(term, c))
09846 return 1;
09847 }
09848 }
09849
09850 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09851 {
09852 int j;
09853 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09854 for (;;)
09855 {
09856
09857 j = DAHDI_IOMUX_SIGEVENT;
09858
09859 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09860
09861 if (j & DAHDI_IOMUX_SIGEVENT) break;
09862 }
09863
09864 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09865 return 0;
09866 }
09867
09868
09869
09870
09871
09872
09873
09874
09875
09876
09877 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09878 {
09879 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09880 return analog_dnd(dahdichan->sig_pvt, flag);
09881 }
09882
09883 if (flag == -1) {
09884 return dahdichan->dnd;
09885 }
09886
09887
09888 dahdichan->dnd = flag;
09889 ast_verb(3, "%s DND on channel %d\n",
09890 flag? "Enabled" : "Disabled",
09891 dahdichan->channel);
09892 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09893 "Channel: DAHDI/%d\r\n"
09894 "Status: %s\r\n", dahdichan->channel,
09895 flag? "enabled" : "disabled");
09896
09897 return 0;
09898 }
09899
09900 static int canmatch_featurecode(const char *exten)
09901 {
09902 int extlen = strlen(exten);
09903 const char *pickup_ext;
09904 if (!extlen) {
09905 return 1;
09906 }
09907 pickup_ext = ast_pickup_ext();
09908 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09909 return 1;
09910 }
09911
09912 if (exten[0] == '*' && extlen < 3) {
09913 if (extlen == 1) {
09914 return 1;
09915 }
09916
09917 switch (exten[1]) {
09918 case '6':
09919 case '7':
09920 case '8':
09921 return 1;
09922 }
09923 }
09924 return 0;
09925 }
09926
09927 static void *analog_ss_thread(void *data)
09928 {
09929 struct ast_channel *chan = data;
09930 struct dahdi_pvt *p = chan->tech_pvt;
09931 char exten[AST_MAX_EXTENSION] = "";
09932 char exten2[AST_MAX_EXTENSION] = "";
09933 unsigned char buf[256];
09934 char dtmfcid[300];
09935 char dtmfbuf[300];
09936 struct callerid_state *cs = NULL;
09937 char *name = NULL, *number = NULL;
09938 int distMatches;
09939 int curRingData[3];
09940 int receivedRingT;
09941 int counter1;
09942 int counter;
09943 int samples = 0;
09944 struct ast_smdi_md_message *smdi_msg = NULL;
09945 int flags = 0;
09946 int i;
09947 int timeout;
09948 int getforward = 0;
09949 char *s1, *s2;
09950 int len = 0;
09951 int res;
09952 int idx;
09953
09954 ast_mutex_lock(&ss_thread_lock);
09955 ss_thread_count++;
09956 ast_mutex_unlock(&ss_thread_lock);
09957
09958
09959
09960 if (!p) {
09961 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09962 ast_hangup(chan);
09963 goto quit;
09964 }
09965 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09966 idx = dahdi_get_index(chan, p, 1);
09967 if (idx < 0) {
09968 ast_log(LOG_WARNING, "Huh?\n");
09969 ast_hangup(chan);
09970 goto quit;
09971 }
09972 if (p->dsp)
09973 ast_dsp_digitreset(p->dsp);
09974 switch (p->sig) {
09975 case SIG_FEATD:
09976 case SIG_FEATDMF:
09977 case SIG_FEATDMF_TA:
09978 case SIG_E911:
09979 case SIG_FGC_CAMAMF:
09980 case SIG_FEATB:
09981 case SIG_EMWINK:
09982 case SIG_SF_FEATD:
09983 case SIG_SF_FEATDMF:
09984 case SIG_SF_FEATB:
09985 case SIG_SFWINK:
09986 if (dahdi_wink(p, idx))
09987 goto quit;
09988
09989 case SIG_EM:
09990 case SIG_EM_E1:
09991 case SIG_SF:
09992 case SIG_FGC_CAMA:
09993 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09994 if (p->dsp)
09995 ast_dsp_digitreset(p->dsp);
09996
09997 if (p->dsp) {
09998 if (NEED_MFDETECT(p))
09999 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10000 else
10001 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10002 }
10003 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10004
10005 if (!p->immediate)
10006
10007 res = ast_waitfordigit(chan, 5000);
10008 else
10009 res = 0;
10010 if (res > 0) {
10011
10012 dtmfbuf[0] = res;
10013 switch (p->sig) {
10014 case SIG_FEATD:
10015 case SIG_SF_FEATD:
10016 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10017 if (res > 0)
10018 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10019 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10020 break;
10021 case SIG_FEATDMF_TA:
10022 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10023 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10024 if (dahdi_wink(p, idx)) goto quit;
10025 dtmfbuf[0] = 0;
10026
10027 res = ast_waitfordigit(chan, 5000);
10028 if (res <= 0) break;
10029 dtmfbuf[0] = res;
10030
10031 case SIG_FEATDMF:
10032 case SIG_E911:
10033 case SIG_FGC_CAMAMF:
10034 case SIG_SF_FEATDMF:
10035 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10036
10037 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10038 {
10039 if (dahdi_wink(p, idx)) goto quit;
10040 dtmfbuf[0] = 0;
10041
10042 res = ast_waitfordigit(chan, 5000);
10043 if (res <= 0) break;
10044 dtmfbuf[0] = res;
10045 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10046 }
10047 if (res > 0) {
10048
10049 if (p->sig == SIG_E911)
10050 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10051 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10052 }
10053 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10054 break;
10055 case SIG_FEATB:
10056 case SIG_SF_FEATB:
10057 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10058 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10059 break;
10060 case SIG_EMWINK:
10061
10062
10063
10064
10065 if (res == '*') {
10066 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10067 if (res > 0)
10068 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10069 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10070 break;
10071 }
10072 default:
10073
10074 len = 1;
10075 dtmfbuf[len] = '\0';
10076 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10077 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10078 timeout = matchdigittimeout;
10079 } else {
10080 timeout = gendigittimeout;
10081 }
10082 res = ast_waitfordigit(chan, timeout);
10083 if (res < 0) {
10084 ast_debug(1, "waitfordigit returned < 0...\n");
10085 ast_hangup(chan);
10086 goto quit;
10087 } else if (res) {
10088 dtmfbuf[len++] = res;
10089 dtmfbuf[len] = '\0';
10090 } else {
10091 break;
10092 }
10093 }
10094 break;
10095 }
10096 }
10097 if (res == -1) {
10098 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10099 ast_hangup(chan);
10100 goto quit;
10101 } else if (res < 0) {
10102 ast_debug(1, "Got hung up before digits finished\n");
10103 ast_hangup(chan);
10104 goto quit;
10105 }
10106
10107 if (p->sig == SIG_FGC_CAMA) {
10108 char anibuf[100];
10109
10110 if (ast_safe_sleep(chan,1000) == -1) {
10111 ast_hangup(chan);
10112 goto quit;
10113 }
10114 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10115 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10116 res = my_getsigstr(chan, anibuf, "#", 10000);
10117 if ((res > 0) && (strlen(anibuf) > 2)) {
10118 if (anibuf[strlen(anibuf) - 1] == '#')
10119 anibuf[strlen(anibuf) - 1] = 0;
10120 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10121 }
10122 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10123 }
10124
10125 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10126 if (ast_strlen_zero(exten))
10127 ast_copy_string(exten, "s", sizeof(exten));
10128 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10129
10130 if (exten[0] == '*') {
10131 char *stringp=NULL;
10132 ast_copy_string(exten2, exten, sizeof(exten2));
10133
10134 stringp=exten2 +1;
10135 s1 = strsep(&stringp, "*");
10136 s2 = strsep(&stringp, "*");
10137 if (s2) {
10138 if (!ast_strlen_zero(p->cid_num))
10139 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10140 else
10141 ast_set_callerid(chan, s1, NULL, s1);
10142 ast_copy_string(exten, s2, sizeof(exten));
10143 } else
10144 ast_copy_string(exten, s1, sizeof(exten));
10145 } else if (p->sig == SIG_FEATD)
10146 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10147 }
10148 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10149 if (exten[0] == '*') {
10150 char *stringp=NULL;
10151 ast_copy_string(exten2, exten, sizeof(exten2));
10152
10153 stringp=exten2 +1;
10154 s1 = strsep(&stringp, "#");
10155 s2 = strsep(&stringp, "#");
10156 if (s2) {
10157 if (!ast_strlen_zero(p->cid_num))
10158 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10159 else
10160 if (*(s1 + 2))
10161 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10162 ast_copy_string(exten, s2 + 1, sizeof(exten));
10163 } else
10164 ast_copy_string(exten, s1 + 2, sizeof(exten));
10165 } else
10166 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10167 }
10168 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10169 if (exten[0] == '*') {
10170 char *stringp=NULL;
10171 ast_copy_string(exten2, exten, sizeof(exten2));
10172
10173 stringp=exten2 +1;
10174 s1 = strsep(&stringp, "#");
10175 s2 = strsep(&stringp, "#");
10176 if (s2 && (*(s2 + 1) == '0')) {
10177 if (*(s2 + 2))
10178 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10179 }
10180 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10181 else ast_copy_string(exten, "911", sizeof(exten));
10182 } else
10183 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10184 }
10185 if (p->sig == SIG_FEATB) {
10186 if (exten[0] == '*') {
10187 char *stringp=NULL;
10188 ast_copy_string(exten2, exten, sizeof(exten2));
10189
10190 stringp=exten2 +1;
10191 s1 = strsep(&stringp, "#");
10192 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10193 } else
10194 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10195 }
10196 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10197 dahdi_wink(p, idx);
10198
10199
10200
10201 if (ast_safe_sleep(chan, 100)) {
10202 ast_hangup(chan);
10203 goto quit;
10204 }
10205 }
10206 dahdi_enable_ec(p);
10207 if (NEED_MFDETECT(p)) {
10208 if (p->dsp) {
10209 if (!p->hardwaredtmf)
10210 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10211 else {
10212 ast_dsp_free(p->dsp);
10213 p->dsp = NULL;
10214 }
10215 }
10216 }
10217
10218 if (ast_exists_extension(chan, chan->context, exten, 1,
10219 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10220 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10221 if (p->dsp) ast_dsp_digitreset(p->dsp);
10222 res = ast_pbx_run(chan);
10223 if (res) {
10224 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10225 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10226 }
10227 goto quit;
10228 } else {
10229 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10230 sleep(2);
10231 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10232 if (res < 0)
10233 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10234 else
10235 sleep(1);
10236 res = ast_streamfile(chan, "ss-noservice", chan->language);
10237 if (res >= 0)
10238 ast_waitstream(chan, "");
10239 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10240 ast_hangup(chan);
10241 goto quit;
10242 }
10243 break;
10244 case SIG_FXOLS:
10245 case SIG_FXOGS:
10246 case SIG_FXOKS:
10247
10248 timeout = firstdigittimeout;
10249
10250
10251 if (p->subs[SUB_THREEWAY].owner)
10252 timeout = 999999;
10253 while (len < AST_MAX_EXTENSION-1) {
10254
10255
10256 if (p->immediate)
10257 res = 's';
10258 else
10259 res = ast_waitfordigit(chan, timeout);
10260 timeout = 0;
10261 if (res < 0) {
10262 ast_debug(1, "waitfordigit returned < 0...\n");
10263 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10264 ast_hangup(chan);
10265 goto quit;
10266 } else if (res) {
10267 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10268 exten[len++]=res;
10269 exten[len] = '\0';
10270 }
10271 if (!ast_ignore_pattern(chan->context, exten))
10272 tone_zone_play_tone(p->subs[idx].dfd, -1);
10273 else
10274 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10275 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10276 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10277 if (getforward) {
10278
10279 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10280 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10281 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10282 if (res)
10283 break;
10284 usleep(500000);
10285 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10286 sleep(1);
10287 memset(exten, 0, sizeof(exten));
10288 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10289 len = 0;
10290 getforward = 0;
10291 } else {
10292 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10293 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10294 if (!ast_strlen_zero(p->cid_num)) {
10295 if (!p->hidecallerid)
10296 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10297 else
10298 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10299 }
10300 if (!ast_strlen_zero(p->cid_name)) {
10301 if (!p->hidecallerid)
10302 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10303 }
10304 ast_setstate(chan, AST_STATE_RING);
10305 dahdi_enable_ec(p);
10306 res = ast_pbx_run(chan);
10307 if (res) {
10308 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10309 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10310 }
10311 goto quit;
10312 }
10313 } else {
10314
10315
10316 timeout = matchdigittimeout;
10317 }
10318 } else if (res == 0) {
10319 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10320 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10321 dahdi_wait_event(p->subs[idx].dfd);
10322 ast_hangup(chan);
10323 goto quit;
10324 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10325 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10326
10327 p->callwaiting = 0;
10328 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10329 if (res) {
10330 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10331 chan->name, strerror(errno));
10332 }
10333 len = 0;
10334 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10335 memset(exten, 0, sizeof(exten));
10336 timeout = firstdigittimeout;
10337
10338 } else if (!strcmp(exten,ast_pickup_ext())) {
10339
10340
10341
10342
10343 if (idx == SUB_REAL) {
10344
10345 if (p->subs[SUB_THREEWAY].owner) {
10346
10347
10348 alloc_sub(p, SUB_CALLWAIT);
10349 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10350 unalloc_sub(p, SUB_THREEWAY);
10351 }
10352 dahdi_enable_ec(p);
10353 if (ast_pickup_call(chan)) {
10354 ast_debug(1, "No call pickup possible...\n");
10355 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10356 dahdi_wait_event(p->subs[idx].dfd);
10357 }
10358 ast_hangup(chan);
10359 goto quit;
10360 } else {
10361 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10362 ast_hangup(chan);
10363 goto quit;
10364 }
10365
10366 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10367 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10368
10369 p->hidecallerid = 1;
10370 ast_party_number_free(&chan->caller.id.number);
10371 ast_party_number_init(&chan->caller.id.number);
10372 ast_party_name_free(&chan->caller.id.name);
10373 ast_party_name_init(&chan->caller.id.name);
10374 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10375 if (res) {
10376 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10377 chan->name, strerror(errno));
10378 }
10379 len = 0;
10380 memset(exten, 0, sizeof(exten));
10381 timeout = firstdigittimeout;
10382 } else if (p->callreturn && !strcmp(exten, "*69")) {
10383 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384 break;
10385 } else if (!strcmp(exten, "*78")) {
10386 dahdi_dnd(p, 1);
10387
10388 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10389 getforward = 0;
10390 memset(exten, 0, sizeof(exten));
10391 len = 0;
10392 } else if (!strcmp(exten, "*79")) {
10393 dahdi_dnd(p, 0);
10394
10395 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10396 getforward = 0;
10397 memset(exten, 0, sizeof(exten));
10398 len = 0;
10399 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10400 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401 getforward = 1;
10402 memset(exten, 0, sizeof(exten));
10403 len = 0;
10404 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10405 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10406 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10407 memset(p->call_forward, 0, sizeof(p->call_forward));
10408 getforward = 0;
10409 memset(exten, 0, sizeof(exten));
10410 len = 0;
10411 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10412 p->subs[SUB_THREEWAY].owner &&
10413 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10414
10415
10416 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10417 chan, exten, chan->context, 0, NULL);
10418 ast_verb(3, "Parking call to '%s'\n", chan->name);
10419 break;
10420 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10421 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10422
10423 p->hidecallerid = 0;
10424 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10425 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10426 if (res) {
10427 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10428 chan->name, strerror(errno));
10429 }
10430 len = 0;
10431 memset(exten, 0, sizeof(exten));
10432 timeout = firstdigittimeout;
10433 } else if (!strcmp(exten, "*0")) {
10434 struct ast_channel *nbridge =
10435 p->subs[SUB_THREEWAY].owner;
10436 struct dahdi_pvt *pbridge = NULL;
10437
10438 if (nbridge && ast_bridged_channel(nbridge))
10439 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10440 if (nbridge && pbridge &&
10441 (nbridge->tech == &dahdi_tech) &&
10442 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10443 ISTRUNK(pbridge)) {
10444 int func = DAHDI_FLASH;
10445
10446 p->dop.dialstr[0] = '\0';
10447
10448 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10449 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10450 nbridge->name, strerror(errno));
10451 }
10452 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10453 unalloc_sub(p, SUB_THREEWAY);
10454 p->owner = p->subs[SUB_REAL].owner;
10455 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10456 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10457 ast_hangup(chan);
10458 goto quit;
10459 } else {
10460 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10461 dahdi_wait_event(p->subs[idx].dfd);
10462 tone_zone_play_tone(p->subs[idx].dfd, -1);
10463 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10464 unalloc_sub(p, SUB_THREEWAY);
10465 p->owner = p->subs[SUB_REAL].owner;
10466 ast_hangup(chan);
10467 goto quit;
10468 }
10469 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10470 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10471 && !canmatch_featurecode(exten)) {
10472 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10473 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10474 chan->context);
10475 break;
10476 }
10477 if (!timeout)
10478 timeout = gendigittimeout;
10479 if (len && !ast_ignore_pattern(chan->context, exten))
10480 tone_zone_play_tone(p->subs[idx].dfd, -1);
10481 }
10482 break;
10483 case SIG_FXSLS:
10484 case SIG_FXSGS:
10485 case SIG_FXSKS:
10486
10487 if (p->use_smdi && p->smdi_iface) {
10488 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10489
10490 if (smdi_msg != NULL) {
10491 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10492
10493 if (smdi_msg->type == 'B')
10494 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10495 else if (smdi_msg->type == 'N')
10496 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10497
10498 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10499 } else {
10500 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10501 }
10502 }
10503
10504 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10505 number = smdi_msg->calling_st;
10506
10507
10508
10509
10510 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10511 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10512
10513 if (p->cid_signalling == CID_SIG_DTMF) {
10514 int k = 0;
10515 cs = NULL;
10516 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10517 dahdi_setlinear(p->subs[idx].dfd, 0);
10518
10519
10520
10521
10522
10523
10524 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10525 res = 4000;
10526 for (;;) {
10527 struct ast_frame *f;
10528 res = ast_waitfor(chan, res);
10529 if (res <= 0) {
10530
10531
10532
10533
10534
10535 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10536 "Exiting simple switch\n");
10537 ast_hangup(chan);
10538 goto quit;
10539 }
10540 f = ast_read(chan);
10541 if (!f)
10542 break;
10543 if (f->frametype == AST_FRAME_DTMF) {
10544 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10545 dtmfbuf[k++] = f->subclass.integer;
10546 }
10547 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10548 res = 4000;
10549 }
10550 ast_frfree(f);
10551 if (chan->_state == AST_STATE_RING ||
10552 chan->_state == AST_STATE_RINGING)
10553 break;
10554 }
10555 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10556 dtmfbuf[k] = '\0';
10557 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10558
10559 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10560 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10561 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10562
10563 if (!ast_strlen_zero(dtmfcid))
10564 number = dtmfcid;
10565 else
10566 number = NULL;
10567
10568 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10569 cs = callerid_new(p->cid_signalling);
10570 if (cs) {
10571 samples = 0;
10572 #if 1
10573 bump_gains(p);
10574 #endif
10575
10576 dahdi_setlinear(p->subs[idx].dfd, 0);
10577
10578
10579 for (;;) {
10580 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10581 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10582 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10583 callerid_free(cs);
10584 ast_hangup(chan);
10585 goto quit;
10586 }
10587 if (i & DAHDI_IOMUX_SIGEVENT) {
10588 res = dahdi_get_event(p->subs[idx].dfd);
10589 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10590 if (res == DAHDI_EVENT_NOALARM) {
10591 p->inalarm = 0;
10592 }
10593
10594 if (p->cid_signalling == CID_SIG_V23_JP) {
10595 if (res == DAHDI_EVENT_RINGBEGIN) {
10596 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10597 usleep(1);
10598 }
10599 } else {
10600 res = 0;
10601 break;
10602 }
10603 } else if (i & DAHDI_IOMUX_READ) {
10604 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10605 if (res < 0) {
10606 if (errno != ELAST) {
10607 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10608 callerid_free(cs);
10609 ast_hangup(chan);
10610 goto quit;
10611 }
10612 break;
10613 }
10614 samples += res;
10615
10616 if (p->cid_signalling == CID_SIG_V23_JP) {
10617 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10618 } else {
10619 res = callerid_feed(cs, buf, res, AST_LAW(p));
10620 }
10621 if (res < 0) {
10622
10623
10624
10625
10626 ast_log(LOG_WARNING,
10627 "Failed to decode CallerID on channel '%s'\n",
10628 chan->name);
10629 break;
10630 } else if (res)
10631 break;
10632 else if (samples > (8000 * 10))
10633 break;
10634 }
10635 }
10636 if (res == 1) {
10637 callerid_get(cs, &name, &number, &flags);
10638 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10639 }
10640
10641 if (p->cid_signalling == CID_SIG_V23_JP) {
10642 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10643 usleep(1);
10644 }
10645
10646
10647 res = 4000;
10648 for (;;) {
10649 struct ast_frame *f;
10650 res = ast_waitfor(chan, res);
10651 if (res <= 0) {
10652 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10653 "Exiting simple switch\n");
10654 ast_hangup(chan);
10655 goto quit;
10656 }
10657 if (!(f = ast_read(chan))) {
10658 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10659 ast_hangup(chan);
10660 goto quit;
10661 }
10662 ast_frfree(f);
10663 if (chan->_state == AST_STATE_RING ||
10664 chan->_state == AST_STATE_RINGING)
10665 break;
10666 }
10667
10668
10669
10670 if (p->usedistinctiveringdetection) {
10671 len = 0;
10672 distMatches = 0;
10673
10674 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10675 curRingData[receivedRingT] = 0;
10676 receivedRingT = 0;
10677 counter = 0;
10678 counter1 = 0;
10679
10680 if (strcmp(p->context,p->defcontext) != 0) {
10681 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10682 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10683 }
10684
10685 for (;;) {
10686 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10687 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10688 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10689 callerid_free(cs);
10690 ast_hangup(chan);
10691 goto quit;
10692 }
10693 if (i & DAHDI_IOMUX_SIGEVENT) {
10694 res = dahdi_get_event(p->subs[idx].dfd);
10695 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10696 if (res == DAHDI_EVENT_NOALARM) {
10697 p->inalarm = 0;
10698 }
10699 res = 0;
10700
10701
10702 curRingData[receivedRingT] = p->ringt;
10703
10704 if (p->ringt < p->ringt_base/2)
10705 break;
10706
10707
10708 if (++receivedRingT == ARRAY_LEN(curRingData))
10709 break;
10710 } else if (i & DAHDI_IOMUX_READ) {
10711 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10712 if (res < 0) {
10713 if (errno != ELAST) {
10714 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10715 callerid_free(cs);
10716 ast_hangup(chan);
10717 goto quit;
10718 }
10719 break;
10720 }
10721 if (p->ringt > 0) {
10722 if (!(--p->ringt)) {
10723 res = -1;
10724 break;
10725 }
10726 }
10727 }
10728 }
10729
10730 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10731 for (counter = 0; counter < 3; counter++) {
10732
10733
10734 distMatches = 0;
10735 for (counter1 = 0; counter1 < 3; counter1++) {
10736 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10737 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10738 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10739 curRingData[counter1]);
10740 distMatches++;
10741 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10742 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10743 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10744 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10745 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10746 distMatches++;
10747 }
10748 }
10749
10750 if (distMatches == 3) {
10751
10752 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10753 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10754 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10755 break;
10756 }
10757 }
10758 }
10759
10760 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10761 #if 1
10762 restore_gains(p);
10763 #endif
10764 } else
10765 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10766 } else {
10767 ast_log(LOG_WARNING, "Channel %s in prering "
10768 "state, but I have nothing to do. "
10769 "Terminating simple switch, should be "
10770 "restarted by the actual ring.\n",
10771 chan->name);
10772 ast_hangup(chan);
10773 goto quit;
10774 }
10775 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10776 if (p->cid_signalling == CID_SIG_DTMF) {
10777 int k = 0;
10778 cs = NULL;
10779 dahdi_setlinear(p->subs[idx].dfd, 0);
10780 res = 2000;
10781 for (;;) {
10782 struct ast_frame *f;
10783 res = ast_waitfor(chan, res);
10784 if (res <= 0) {
10785 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10786 "Exiting simple switch\n");
10787 ast_hangup(chan);
10788 goto quit;
10789 }
10790 f = ast_read(chan);
10791 if (!f) {
10792
10793 ast_hangup(chan);
10794 goto quit;
10795 }
10796 if (f->frametype == AST_FRAME_DTMF) {
10797 dtmfbuf[k++] = f->subclass.integer;
10798 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10799 res = 2000;
10800 }
10801 ast_frfree(f);
10802
10803 if (p->ringt_base == p->ringt)
10804 break;
10805 }
10806 dtmfbuf[k] = '\0';
10807 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10808
10809 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10810 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10811 dtmfcid, flags);
10812
10813 if (!ast_strlen_zero(dtmfcid))
10814 number = dtmfcid;
10815 else
10816 number = NULL;
10817
10818 } else {
10819
10820 cs = callerid_new(p->cid_signalling);
10821 if (cs) {
10822 #if 1
10823 bump_gains(p);
10824 #endif
10825 samples = 0;
10826 len = 0;
10827 distMatches = 0;
10828
10829 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10830 curRingData[receivedRingT] = 0;
10831 receivedRingT = 0;
10832 counter = 0;
10833 counter1 = 0;
10834
10835 if (strcmp(p->context,p->defcontext) != 0) {
10836 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10837 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10838 }
10839
10840
10841 dahdi_setlinear(p->subs[idx].dfd, 0);
10842 for (;;) {
10843 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10844 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10845 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10846 callerid_free(cs);
10847 ast_hangup(chan);
10848 goto quit;
10849 }
10850 if (i & DAHDI_IOMUX_SIGEVENT) {
10851 res = dahdi_get_event(p->subs[idx].dfd);
10852 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10853 if (res == DAHDI_EVENT_NOALARM) {
10854 p->inalarm = 0;
10855 }
10856
10857 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10858 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10859 p->polarity = POLARITY_IDLE;
10860 callerid_free(cs);
10861 ast_hangup(chan);
10862 goto quit;
10863 }
10864 res = 0;
10865
10866
10867 curRingData[receivedRingT] = p->ringt;
10868
10869 if (p->ringt < p->ringt_base/2)
10870 break;
10871
10872
10873 if (++receivedRingT == ARRAY_LEN(curRingData))
10874 break;
10875 } else if (i & DAHDI_IOMUX_READ) {
10876 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10877 if (res < 0) {
10878 if (errno != ELAST) {
10879 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10880 callerid_free(cs);
10881 ast_hangup(chan);
10882 goto quit;
10883 }
10884 break;
10885 }
10886 if (p->ringt > 0) {
10887 if (!(--p->ringt)) {
10888 res = -1;
10889 break;
10890 }
10891 }
10892 samples += res;
10893 res = callerid_feed(cs, buf, res, AST_LAW(p));
10894 if (res < 0) {
10895
10896
10897
10898
10899 ast_log(LOG_WARNING,
10900 "Failed to decode CallerID on channel '%s'\n",
10901 chan->name);
10902 break;
10903 } else if (res)
10904 break;
10905 else if (samples > (8000 * 10))
10906 break;
10907 }
10908 }
10909 if (res == 1) {
10910 callerid_get(cs, &name, &number, &flags);
10911 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10912 }
10913 if (distinctiveringaftercid == 1) {
10914
10915 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10916 curRingData[receivedRingT] = 0;
10917 }
10918 receivedRingT = 0;
10919 ast_verb(3, "Detecting post-CID distinctive ring\n");
10920 for (;;) {
10921 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10922 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10923 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10924 callerid_free(cs);
10925 ast_hangup(chan);
10926 goto quit;
10927 }
10928 if (i & DAHDI_IOMUX_SIGEVENT) {
10929 res = dahdi_get_event(p->subs[idx].dfd);
10930 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10931 if (res == DAHDI_EVENT_NOALARM) {
10932 p->inalarm = 0;
10933 }
10934 res = 0;
10935
10936
10937 curRingData[receivedRingT] = p->ringt;
10938
10939 if (p->ringt < p->ringt_base/2)
10940 break;
10941
10942
10943 if (++receivedRingT == ARRAY_LEN(curRingData))
10944 break;
10945 } else if (i & DAHDI_IOMUX_READ) {
10946 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10947 if (res < 0) {
10948 if (errno != ELAST) {
10949 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10950 callerid_free(cs);
10951 ast_hangup(chan);
10952 goto quit;
10953 }
10954 break;
10955 }
10956 if (p->ringt > 0) {
10957 if (!(--p->ringt)) {
10958 res = -1;
10959 break;
10960 }
10961 }
10962 }
10963 }
10964 }
10965 if (p->usedistinctiveringdetection) {
10966
10967 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10968
10969 for (counter = 0; counter < 3; counter++) {
10970
10971
10972
10973 ast_verb(3, "Checking %d,%d,%d\n",
10974 p->drings.ringnum[counter].ring[0],
10975 p->drings.ringnum[counter].ring[1],
10976 p->drings.ringnum[counter].ring[2]);
10977 distMatches = 0;
10978 for (counter1 = 0; counter1 < 3; counter1++) {
10979 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10980 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10981 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10982 curRingData[counter1]);
10983 distMatches++;
10984 }
10985 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10986 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10987 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10988 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10989 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10990 distMatches++;
10991 }
10992 }
10993 if (distMatches == 3) {
10994
10995 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10996 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10997 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10998 break;
10999 }
11000 }
11001 }
11002
11003 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11004 #if 1
11005 restore_gains(p);
11006 #endif
11007 if (res < 0) {
11008 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11009 }
11010 } else
11011 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11012 }
11013 } else
11014 cs = NULL;
11015
11016 if (number)
11017 ast_shrink_phone_number(number);
11018 ast_set_callerid(chan, number, name, number);
11019
11020 if (smdi_msg)
11021 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11022
11023 if (cs)
11024 callerid_free(cs);
11025
11026 my_handle_notify_message(chan, p, flags, -1);
11027
11028 ast_setstate(chan, AST_STATE_RING);
11029 chan->rings = 1;
11030 p->ringt = p->ringt_base;
11031 res = ast_pbx_run(chan);
11032 if (res) {
11033 ast_hangup(chan);
11034 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11035 }
11036 goto quit;
11037 default:
11038 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11039 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11040 if (res < 0)
11041 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11042 }
11043 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11044 if (res < 0)
11045 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11046 ast_hangup(chan);
11047 quit:
11048 ast_mutex_lock(&ss_thread_lock);
11049 ss_thread_count--;
11050 ast_cond_signal(&ss_thread_complete);
11051 ast_mutex_unlock(&ss_thread_lock);
11052 return NULL;
11053 }
11054
11055 struct mwi_thread_data {
11056 struct dahdi_pvt *pvt;
11057 unsigned char buf[READ_SIZE];
11058 size_t len;
11059 };
11060
11061 static int calc_energy(const unsigned char *buf, int len, format_t law)
11062 {
11063 int x;
11064 int sum = 0;
11065
11066 if (!len)
11067 return 0;
11068
11069 for (x = 0; x < len; x++)
11070 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11071
11072 return sum / len;
11073 }
11074
11075 static void *mwi_thread(void *data)
11076 {
11077 struct mwi_thread_data *mtd = data;
11078 struct callerid_state *cs;
11079 pthread_t threadid;
11080 int samples = 0;
11081 char *name, *number;
11082 int flags;
11083 int i, res;
11084 unsigned int spill_done = 0;
11085 int spill_result = -1;
11086
11087 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11088 goto quit_no_clean;
11089 }
11090
11091 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11092
11093 bump_gains(mtd->pvt);
11094
11095 for (;;) {
11096 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11097 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11098 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11099 goto quit;
11100 }
11101
11102 if (i & DAHDI_IOMUX_SIGEVENT) {
11103 struct ast_channel *chan;
11104
11105
11106
11107
11108 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11109
11110 switch (res) {
11111 case DAHDI_EVENT_NEONMWI_ACTIVE:
11112 case DAHDI_EVENT_NEONMWI_INACTIVE:
11113 case DAHDI_EVENT_NONE:
11114 case DAHDI_EVENT_BITSCHANGED:
11115 break;
11116 case DAHDI_EVENT_NOALARM:
11117 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11118 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11119
11120 analog_p->inalarm = 0;
11121 }
11122 mtd->pvt->inalarm = 0;
11123 handle_clear_alarms(mtd->pvt);
11124 break;
11125 case DAHDI_EVENT_ALARM:
11126 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11127 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11128
11129 analog_p->inalarm = 1;
11130 }
11131 mtd->pvt->inalarm = 1;
11132 res = get_alarms(mtd->pvt);
11133 handle_alarms(mtd->pvt, res);
11134 break;
11135 default:
11136 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11137 callerid_free(cs);
11138
11139 restore_gains(mtd->pvt);
11140 mtd->pvt->ringt = mtd->pvt->ringt_base;
11141
11142 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11143 int result;
11144
11145 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11146 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11147 } else {
11148 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11149 }
11150 if (result) {
11151 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11152 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11153 if (res < 0)
11154 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11155 ast_hangup(chan);
11156 }
11157 } else {
11158 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11159 }
11160 goto quit_no_clean;
11161 }
11162 } else if (i & DAHDI_IOMUX_READ) {
11163 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11164 if (errno != ELAST) {
11165 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11166 goto quit;
11167 }
11168 break;
11169 }
11170 samples += res;
11171 if (!spill_done) {
11172 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11173
11174
11175
11176
11177 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11178 break;
11179 } else if (spill_result) {
11180 spill_done = 1;
11181 }
11182 } else {
11183
11184
11185
11186 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11187 break;
11188 }
11189 if (samples > (8000 * 4))
11190 break;
11191 }
11192 }
11193
11194 if (spill_result == 1) {
11195 callerid_get(cs, &name, &number, &flags);
11196 if (flags & CID_MSGWAITING) {
11197 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11198 notify_message(mtd->pvt->mailbox, 1);
11199 } else if (flags & CID_NOMSGWAITING) {
11200 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11201 notify_message(mtd->pvt->mailbox, 0);
11202 } else {
11203 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11204 }
11205 }
11206
11207
11208 quit:
11209 callerid_free(cs);
11210
11211 restore_gains(mtd->pvt);
11212
11213 quit_no_clean:
11214 mtd->pvt->mwimonitoractive = 0;
11215 ast_free(mtd);
11216
11217 return NULL;
11218 }
11219
11220
11221
11222
11223
11224
11225
11226
11227 static int mwi_send_init(struct dahdi_pvt * pvt)
11228 {
11229 int x;
11230
11231 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11232
11233 if (pvt->mwisend_rpas) {
11234 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11235 pvt->mwisendactive = 1;
11236 } else if (pvt->mwisend_fsk) {
11237 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11238 pvt->mwisendactive = 1;
11239 } else {
11240 pvt->mwisendactive = 0;
11241 return 0;
11242 }
11243 #else
11244 if (mwisend_rpas) {
11245 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11246 } else {
11247 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11248 }
11249 pvt->mwisendactive = 1;
11250 #endif
11251
11252 if (pvt->cidspill) {
11253 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11254 ast_free(pvt->cidspill);
11255 pvt->cidspill = NULL;
11256 pvt->cidpos = 0;
11257 pvt->cidlen = 0;
11258 }
11259 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11260 if (!pvt->cidspill) {
11261 pvt->mwisendactive = 0;
11262 return -1;
11263 }
11264 x = DAHDI_FLUSH_BOTH;
11265 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11266 x = 3000;
11267 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11268 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11269 if (pvt->mwisend_fsk) {
11270 #endif
11271 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11272 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11273 pvt->cidpos = 0;
11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11275 }
11276 #endif
11277 return 0;
11278 }
11279
11280 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11281 {
11282 struct timeval now;
11283 int res;
11284
11285
11286
11287
11288 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11289 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11290 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11291
11292 switch ( pvt->mwisend_data.mwisend_current) {
11293 case MWI_SEND_SA:
11294
11295 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11296 if (res) {
11297 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11298 goto quit;
11299 }
11300 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11301 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11302 break;
11303 case MWI_SEND_SA_WAIT:
11304 break;
11305 case MWI_SEND_PAUSE:
11306 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11307 if (pvt->mwisend_fsk) {
11308 #endif
11309 gettimeofday(&now, NULL);
11310 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11311 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11312 }
11313 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11314 } else {
11315 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11316 }
11317 #endif
11318 break;
11319 case MWI_SEND_SPILL:
11320
11321 if(0 < num_read) {
11322 if (num_read > pvt->cidlen - pvt->cidpos)
11323 num_read = pvt->cidlen - pvt->cidpos;
11324 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11325 if (res > 0) {
11326 pvt->cidpos += res;
11327 if (pvt->cidpos >= pvt->cidlen) {
11328 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11329 }
11330 } else {
11331 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11332 goto quit;
11333 }
11334 }
11335 break;
11336 case MWI_SEND_CLEANUP:
11337
11338 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11339 break;
11340 default:
11341
11342 goto quit;
11343 }
11344 }
11345
11346 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11347 if (pvt->cidspill) {
11348 ast_free(pvt->cidspill);
11349 pvt->cidspill = NULL;
11350 pvt->cidpos = 0;
11351 pvt->cidlen = 0;
11352 }
11353 pvt->mwisendactive = 0;
11354 }
11355 return 0;
11356 quit:
11357 if (pvt->cidspill) {
11358 ast_free(pvt->cidspill);
11359 pvt->cidspill = NULL;
11360 pvt->cidpos = 0;
11361 pvt->cidlen = 0;
11362 }
11363 pvt->mwisendactive = 0;
11364 return -1;
11365 }
11366
11367 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11368 {
11369 int handled = 0;
11370
11371 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11372 switch (event) {
11373 case DAHDI_EVENT_RINGEROFF:
11374 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11375 handled = 1;
11376
11377 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11378 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11379 ast_free(pvt->cidspill);
11380 pvt->cidspill = NULL;
11381 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11382 pvt->mwisendactive = 0;
11383 } else {
11384 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11385 gettimeofday(&pvt->mwisend_data.pause, NULL);
11386 }
11387 }
11388 break;
11389
11390 case DAHDI_EVENT_RINGOFFHOOK:
11391 if (pvt->cidspill) {
11392 ast_free(pvt->cidspill);
11393 pvt->cidspill = NULL;
11394 pvt->cidpos = 0;
11395 pvt->cidlen = 0;
11396 }
11397 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11398 pvt->mwisendactive = 0;
11399 break;
11400 case DAHDI_EVENT_RINGERON:
11401 case DAHDI_EVENT_HOOKCOMPLETE:
11402 break;
11403 default:
11404 break;
11405 }
11406 }
11407 return handled;
11408 }
11409
11410
11411 static int dahdi_destroy_channel_bynum(int channel)
11412 {
11413 struct dahdi_pvt *cur;
11414
11415 ast_mutex_lock(&iflock);
11416 for (cur = iflist; cur; cur = cur->next) {
11417 if (cur->channel == channel) {
11418 int x = DAHDI_FLASH;
11419
11420
11421 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11422
11423 destroy_channel(cur, 1);
11424 ast_mutex_unlock(&iflock);
11425 ast_module_unref(ast_module_info->self);
11426 return RESULT_SUCCESS;
11427 }
11428 }
11429 ast_mutex_unlock(&iflock);
11430 return RESULT_FAILURE;
11431 }
11432
11433 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11434 {
11435 int res;
11436 pthread_t threadid;
11437 struct ast_channel *chan;
11438
11439
11440
11441 switch (event) {
11442 case DAHDI_EVENT_NONE:
11443 case DAHDI_EVENT_BITSCHANGED:
11444 break;
11445 case DAHDI_EVENT_WINKFLASH:
11446 case DAHDI_EVENT_RINGOFFHOOK:
11447 if (i->inalarm) break;
11448 if (i->radio) break;
11449
11450 switch (i->sig) {
11451 case SIG_FXOLS:
11452 case SIG_FXOGS:
11453 case SIG_FXOKS:
11454 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11455 if (res && (errno == EBUSY))
11456 break;
11457
11458
11459 ast_free(i->cidspill);
11460 i->cidspill = NULL;
11461 restore_conference(i);
11462
11463 if (i->immediate) {
11464 dahdi_enable_ec(i);
11465
11466 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11467 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11468 if (!chan) {
11469 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11470 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11471 if (res < 0)
11472 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11473 }
11474 } else {
11475
11476 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11477 if (chan) {
11478 if (has_voicemail(i))
11479 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11480 else
11481 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11482 if (res < 0)
11483 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11484 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11485 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11486 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11487 if (res < 0)
11488 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11489 ast_hangup(chan);
11490 }
11491 } else
11492 ast_log(LOG_WARNING, "Unable to create channel\n");
11493 }
11494 break;
11495 case SIG_FXSLS:
11496 case SIG_FXSGS:
11497 case SIG_FXSKS:
11498 i->ringt = i->ringt_base;
11499
11500 case SIG_EMWINK:
11501 case SIG_FEATD:
11502 case SIG_FEATDMF:
11503 case SIG_FEATDMF_TA:
11504 case SIG_E911:
11505 case SIG_FGC_CAMA:
11506 case SIG_FGC_CAMAMF:
11507 case SIG_FEATB:
11508 case SIG_EM:
11509 case SIG_EM_E1:
11510 case SIG_SFWINK:
11511 case SIG_SF_FEATD:
11512 case SIG_SF_FEATDMF:
11513 case SIG_SF_FEATB:
11514 case SIG_SF:
11515
11516 if (i->cid_start == CID_START_POLARITY_IN) {
11517 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11518 } else {
11519 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11520 }
11521
11522 if (!chan) {
11523 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11524 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11525 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11526 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11527 if (res < 0) {
11528 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11529 }
11530 ast_hangup(chan);
11531 }
11532 break;
11533 default:
11534 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11535 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11536 if (res < 0)
11537 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11538 return NULL;
11539 }
11540 break;
11541 case DAHDI_EVENT_NOALARM:
11542 switch (i->sig) {
11543 #if defined(HAVE_PRI)
11544 case SIG_PRI_LIB_HANDLE_CASES:
11545 ast_mutex_lock(&i->lock);
11546 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11547 ast_mutex_unlock(&i->lock);
11548 break;
11549 #endif
11550 #if defined(HAVE_SS7)
11551 case SIG_SS7:
11552 sig_ss7_set_alarm(i->sig_pvt, 0);
11553 break;
11554 #endif
11555 default:
11556 i->inalarm = 0;
11557 break;
11558 }
11559 handle_clear_alarms(i);
11560 break;
11561 case DAHDI_EVENT_ALARM:
11562 switch (i->sig) {
11563 #if defined(HAVE_PRI)
11564 case SIG_PRI_LIB_HANDLE_CASES:
11565 ast_mutex_lock(&i->lock);
11566 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11567 ast_mutex_unlock(&i->lock);
11568 break;
11569 #endif
11570 #if defined(HAVE_SS7)
11571 case SIG_SS7:
11572 sig_ss7_set_alarm(i->sig_pvt, 1);
11573 break;
11574 #endif
11575 default:
11576 i->inalarm = 1;
11577 break;
11578 }
11579 res = get_alarms(i);
11580 handle_alarms(i, res);
11581
11582 case DAHDI_EVENT_ONHOOK:
11583 if (i->radio)
11584 break;
11585
11586 switch (i->sig) {
11587 case SIG_FXOLS:
11588 case SIG_FXOGS:
11589 case SIG_FEATD:
11590 case SIG_FEATDMF:
11591 case SIG_FEATDMF_TA:
11592 case SIG_E911:
11593 case SIG_FGC_CAMA:
11594 case SIG_FGC_CAMAMF:
11595 case SIG_FEATB:
11596 case SIG_EM:
11597 case SIG_EM_E1:
11598 case SIG_EMWINK:
11599 case SIG_SF_FEATD:
11600 case SIG_SF_FEATDMF:
11601 case SIG_SF_FEATB:
11602 case SIG_SF:
11603 case SIG_SFWINK:
11604 case SIG_FXSLS:
11605 case SIG_FXSGS:
11606 case SIG_FXSKS:
11607 case SIG_FXOKS:
11608 dahdi_disable_ec(i);
11609
11610 #ifdef ZHONE_HACK
11611 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11612 usleep(1);
11613 #endif
11614 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11615 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11616 break;
11617 case SIG_SS7:
11618 case SIG_PRI_LIB_HANDLE_CASES:
11619 dahdi_disable_ec(i);
11620 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11621 break;
11622 default:
11623 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11624 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11625 return NULL;
11626 }
11627 break;
11628 case DAHDI_EVENT_POLARITY:
11629 switch (i->sig) {
11630 case SIG_FXSLS:
11631 case SIG_FXSKS:
11632 case SIG_FXSGS:
11633
11634
11635
11636
11637 if (i->hanguponpolarityswitch)
11638 i->polarity = POLARITY_REV;
11639 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11640 i->polarity = POLARITY_REV;
11641 ast_verb(2, "Starting post polarity "
11642 "CID detection on channel %d\n",
11643 i->channel);
11644 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11645 if (!chan) {
11646 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11647 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11648 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11649 ast_hangup(chan);
11650 }
11651 }
11652 break;
11653 default:
11654 ast_log(LOG_WARNING, "handle_init_event detected "
11655 "polarity reversal on non-FXO (SIG_FXS) "
11656 "interface %d\n", i->channel);
11657 }
11658 break;
11659 case DAHDI_EVENT_REMOVED:
11660 ast_log(LOG_NOTICE,
11661 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11662 i->channel);
11663 return i;
11664 case DAHDI_EVENT_NEONMWI_ACTIVE:
11665 if (i->mwimonitor_neon) {
11666 notify_message(i->mailbox, 1);
11667 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11668 }
11669 break;
11670 case DAHDI_EVENT_NEONMWI_INACTIVE:
11671 if (i->mwimonitor_neon) {
11672 notify_message(i->mailbox, 0);
11673 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11674 }
11675 break;
11676 }
11677 return NULL;
11678 }
11679
11680 static void *do_monitor(void *data)
11681 {
11682 int count, res, res2, spoint, pollres=0;
11683 struct dahdi_pvt *i;
11684 struct dahdi_pvt *last = NULL;
11685 struct dahdi_pvt *doomed;
11686 time_t thispass = 0, lastpass = 0;
11687 int found;
11688 char buf[1024];
11689 struct pollfd *pfds=NULL;
11690 int lastalloc = -1;
11691
11692
11693
11694 #if 0
11695 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11696 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11697 return NULL;
11698 }
11699 ast_debug(1, "Monitor starting...\n");
11700 #endif
11701 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11702
11703 for (;;) {
11704
11705 ast_mutex_lock(&iflock);
11706 if (!pfds || (lastalloc != ifcount)) {
11707 if (pfds) {
11708 ast_free(pfds);
11709 pfds = NULL;
11710 }
11711 if (ifcount) {
11712 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11713 ast_mutex_unlock(&iflock);
11714 return NULL;
11715 }
11716 }
11717 lastalloc = ifcount;
11718 }
11719
11720
11721 count = 0;
11722 for (i = iflist; i; i = i->next) {
11723 ast_mutex_lock(&i->lock);
11724 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11725 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11726 struct analog_pvt *p = i->sig_pvt;
11727
11728 if (!p) {
11729 ast_log(LOG_ERROR, "No sig_pvt?\n");
11730 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11731
11732 pfds[count].fd = i->subs[SUB_REAL].dfd;
11733 pfds[count].events = POLLPRI;
11734 pfds[count].revents = 0;
11735
11736 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11737 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11738 pfds[count].events |= POLLIN;
11739 }
11740 count++;
11741 }
11742 } else {
11743 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11744
11745 pfds[count].fd = i->subs[SUB_REAL].dfd;
11746 pfds[count].events = POLLPRI;
11747 pfds[count].revents = 0;
11748
11749
11750 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11751 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11752 pfds[count].events |= POLLIN;
11753 }
11754 count++;
11755 }
11756 }
11757 }
11758 ast_mutex_unlock(&i->lock);
11759 }
11760
11761 ast_mutex_unlock(&iflock);
11762
11763 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11764 pthread_testcancel();
11765
11766 res = poll(pfds, count, 1000);
11767 pthread_testcancel();
11768 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11769
11770
11771 if (res < 0) {
11772 if ((errno != EAGAIN) && (errno != EINTR))
11773 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11774 continue;
11775 }
11776
11777
11778 ast_mutex_lock(&iflock);
11779 found = 0;
11780 spoint = 0;
11781 lastpass = thispass;
11782 thispass = time(NULL);
11783 doomed = NULL;
11784 for (i = iflist;; i = i->next) {
11785 if (doomed) {
11786 int res;
11787 res = dahdi_destroy_channel_bynum(doomed->channel);
11788 if (res != RESULT_SUCCESS) {
11789 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11790 }
11791 doomed = NULL;
11792 }
11793 if (!i) {
11794 break;
11795 }
11796
11797 if (thispass != lastpass) {
11798 if (!found && ((i == last) || ((i == iflist) && !last))) {
11799 last = i;
11800 if (last) {
11801 struct analog_pvt *analog_p = last->sig_pvt;
11802
11803 if (analog_p
11804 && !last->mwisendactive
11805 && (last->sig & __DAHDI_SIG_FXO)
11806 && !analog_p->fxsoffhookstate
11807 && !last->owner
11808 && !ast_strlen_zero(last->mailbox)
11809 && (thispass - analog_p->onhooktime > 3)) {
11810 res = has_voicemail(last);
11811 if (analog_p->msgstate != res) {
11812
11813 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11814 if (res2) {
11815
11816 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11817 }
11818
11819 if (mwi_send_init(last)) {
11820 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11821 }
11822 analog_p->msgstate = res;
11823 found ++;
11824 }
11825 }
11826 last = last->next;
11827 }
11828 }
11829 }
11830 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11831 if (i->radio && !i->owner)
11832 {
11833 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11834 if (res)
11835 {
11836 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11837
11838 ast_mutex_unlock(&iflock);
11839 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11840 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11841 else
11842 doomed = handle_init_event(i, res);
11843 ast_mutex_lock(&iflock);
11844 }
11845 continue;
11846 }
11847 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11848 if (pollres & POLLIN) {
11849 if (i->owner || i->subs[SUB_REAL].owner) {
11850 #ifdef HAVE_PRI
11851 if (!i->pri)
11852 #endif
11853 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11854 continue;
11855 }
11856 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11857 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11858 continue;
11859 }
11860 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11861 if (res > 0) {
11862 if (i->mwimonitor_fsk) {
11863 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11864 pthread_attr_t attr;
11865 pthread_t threadid;
11866 struct mwi_thread_data *mtd;
11867
11868 pthread_attr_init(&attr);
11869 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11870
11871 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11872 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11873 mtd->pvt = i;
11874 memcpy(mtd->buf, buf, res);
11875 mtd->len = res;
11876 i->mwimonitoractive = 1;
11877 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11878 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11879 i->mwimonitoractive = 0;
11880 ast_free(mtd);
11881 }
11882 }
11883 }
11884
11885 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11886 int energy;
11887 struct timeval now;
11888
11889
11890
11891 if (1 == i->dtmfcid_holdoff_state) {
11892 gettimeofday(&i->dtmfcid_delay, NULL);
11893 i->dtmfcid_holdoff_state = 2;
11894 } else if (2 == i->dtmfcid_holdoff_state) {
11895 gettimeofday(&now, NULL);
11896 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11897 i->dtmfcid_holdoff_state = 0;
11898 }
11899 } else {
11900 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11901 if (!i->mwisendactive && energy > dtmfcid_level) {
11902 pthread_t threadid;
11903 struct ast_channel *chan;
11904 ast_mutex_unlock(&iflock);
11905 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11906
11907 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11908 i->dtmfcid_holdoff_state = 1;
11909 } else {
11910 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11911 if (!chan) {
11912 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11913 } else {
11914 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11915 if (res) {
11916 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11917 ast_hangup(chan);
11918 } else {
11919 i->dtmfcid_holdoff_state = 1;
11920 }
11921 }
11922 }
11923 ast_mutex_lock(&iflock);
11924 }
11925 }
11926 }
11927 if (i->mwisendactive) {
11928 mwi_send_process_buffer(i, res);
11929 }
11930 } else {
11931 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11932 }
11933 }
11934 if (pollres & POLLPRI) {
11935 if (i->owner || i->subs[SUB_REAL].owner) {
11936 #ifdef HAVE_PRI
11937 if (!i->pri)
11938 #endif
11939 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11940 continue;
11941 }
11942 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11943 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11944
11945 ast_mutex_unlock(&iflock);
11946 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11947 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11948 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11949 else
11950 doomed = handle_init_event(i, res);
11951 }
11952 ast_mutex_lock(&iflock);
11953 }
11954 }
11955 }
11956 ast_mutex_unlock(&iflock);
11957 }
11958
11959 return NULL;
11960
11961 }
11962
11963 static int restart_monitor(void)
11964 {
11965
11966 if (monitor_thread == AST_PTHREADT_STOP)
11967 return 0;
11968 ast_mutex_lock(&monlock);
11969 if (monitor_thread == pthread_self()) {
11970 ast_mutex_unlock(&monlock);
11971 ast_log(LOG_WARNING, "Cannot kill myself\n");
11972 return -1;
11973 }
11974 if (monitor_thread != AST_PTHREADT_NULL) {
11975
11976 pthread_kill(monitor_thread, SIGURG);
11977 } else {
11978
11979 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11980 ast_mutex_unlock(&monlock);
11981 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11982 return -1;
11983 }
11984 }
11985 ast_mutex_unlock(&monlock);
11986 return 0;
11987 }
11988
11989 #if defined(HAVE_PRI)
11990 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11991 {
11992 int x;
11993 int trunkgroup;
11994
11995 trunkgroup = pris[*span].mastertrunkgroup;
11996 if (trunkgroup) {
11997
11998 for (x = 0; x < NUM_SPANS; x++) {
11999 if (pris[x].pri.trunkgroup == trunkgroup) {
12000 *span = x;
12001 return 0;
12002 }
12003 }
12004 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12005 *span = -1;
12006 } else {
12007 if (pris[*span].pri.trunkgroup) {
12008 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);
12009 *span = -1;
12010 } else if (pris[*span].mastertrunkgroup) {
12011 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12012 *span = -1;
12013 } else {
12014 if (si->totalchans == 31) {
12015
12016 pris[*span].dchannels[0] = 16 + offset;
12017 } else if (si->totalchans == 24) {
12018
12019 pris[*span].dchannels[0] = 24 + offset;
12020 } else if (si->totalchans == 3) {
12021
12022 pris[*span].dchannels[0] = 3 + offset;
12023 } else {
12024 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);
12025 *span = -1;
12026 return 0;
12027 }
12028 pris[*span].pri.span = *span + 1;
12029 }
12030 }
12031 return 0;
12032 }
12033 #endif
12034
12035 #if defined(HAVE_PRI)
12036 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12037 {
12038 struct dahdi_spaninfo si;
12039 struct dahdi_params p;
12040 int fd;
12041 int span;
12042 int ospan=0;
12043 int x,y;
12044 for (x = 0; x < NUM_SPANS; x++) {
12045 if (pris[x].pri.trunkgroup == trunkgroup) {
12046 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12047 return -1;
12048 }
12049 }
12050 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12051 if (!channels[y])
12052 break;
12053 memset(&si, 0, sizeof(si));
12054 memset(&p, 0, sizeof(p));
12055 fd = open("/dev/dahdi/channel", O_RDWR);
12056 if (fd < 0) {
12057 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12058 return -1;
12059 }
12060 x = channels[y];
12061 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12062 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12063 close(fd);
12064 return -1;
12065 }
12066 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12067 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12068 return -1;
12069 }
12070 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12071 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12072 close(fd);
12073 return -1;
12074 }
12075 span = p.spanno - 1;
12076 if (pris[span].pri.trunkgroup) {
12077 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12078 close(fd);
12079 return -1;
12080 }
12081 if (pris[span].pri.pvts[0]) {
12082 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12083 close(fd);
12084 return -1;
12085 }
12086 if (!y) {
12087 pris[span].pri.trunkgroup = trunkgroup;
12088 ospan = span;
12089 }
12090 pris[ospan].dchannels[y] = channels[y];
12091 pris[span].pri.span = span + 1;
12092 close(fd);
12093 }
12094 return 0;
12095 }
12096 #endif
12097
12098 #if defined(HAVE_PRI)
12099 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12100 {
12101 if (pris[span].mastertrunkgroup) {
12102 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);
12103 return -1;
12104 }
12105 pris[span].mastertrunkgroup = trunkgroup;
12106 pris[span].prilogicalspan = logicalspan;
12107 return 0;
12108 }
12109 #endif
12110
12111 #if defined(HAVE_SS7)
12112 static unsigned int parse_pointcode(const char *pcstring)
12113 {
12114 unsigned int code1, code2, code3;
12115 int numvals;
12116
12117 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12118 if (numvals == 1)
12119 return code1;
12120 if (numvals == 3)
12121 return (code1 << 16) | (code2 << 8) | code3;
12122
12123 return 0;
12124 }
12125 #endif
12126
12127 #if defined(HAVE_SS7)
12128 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12129 {
12130 if ((linkset < 0) || (linkset >= NUM_SPANS))
12131 return NULL;
12132 else
12133 return &linksets[linkset - 1];
12134 }
12135 #endif
12136
12137 #ifdef HAVE_OPENR2
12138 static void dahdi_r2_destroy_links(void)
12139 {
12140 int i = 0;
12141 if (!r2links) {
12142 return;
12143 }
12144 for (; i < r2links_count; i++) {
12145 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12146 pthread_cancel(r2links[i]->r2master);
12147 pthread_join(r2links[i]->r2master, NULL);
12148 openr2_context_delete(r2links[i]->protocol_context);
12149 }
12150 ast_free(r2links[i]);
12151 }
12152 ast_free(r2links);
12153 r2links = NULL;
12154 r2links_count = 0;
12155 }
12156
12157 #define R2_LINK_CAPACITY 10
12158 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12159 {
12160 struct dahdi_mfcr2 *new_r2link = NULL;
12161 struct dahdi_mfcr2 **new_r2links = NULL;
12162
12163
12164 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12165 new_r2link = ast_calloc(1, sizeof(**r2links));
12166 if (!new_r2link) {
12167 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12168 return NULL;
12169 }
12170 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12171 if (!new_r2links) {
12172 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12173 ast_free(new_r2link);
12174 return NULL;
12175 }
12176 r2links = new_r2links;
12177 new_r2link->r2master = AST_PTHREADT_NULL;
12178 r2links[r2links_count] = new_r2link;
12179 r2links_count++;
12180 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12181 }
12182 return r2links[r2links_count - 1];
12183 }
12184
12185 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12186 {
12187 char tmplogdir[] = "/tmp";
12188 char logdir[OR2_MAX_PATH];
12189 int threshold = 0;
12190 int snres = 0;
12191 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12192 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12193 conf->mfcr2.max_dnis);
12194 if (!r2_link->protocol_context) {
12195 return -1;
12196 }
12197 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12198 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12199 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12200 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12201 #endif
12202 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12203 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12204 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12205 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12206 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12207 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12208 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12209 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12210 }
12211 } else {
12212 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12213 if (snres >= sizeof(logdir)) {
12214 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12215 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12216 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12217 }
12218 } else {
12219 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12220 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12221 }
12222 }
12223 }
12224 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12225 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12226 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12227 }
12228 }
12229 r2_link->monitored_count = 0;
12230 return 0;
12231 }
12232 #endif
12233
12234
12235
12236
12237
12238
12239 static int sigtype_to_signalling(int sigtype)
12240 {
12241 return sigtype;
12242 }
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12257 {
12258 struct stat stbuf;
12259 int num;
12260
12261 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12262 if (stat(path, &stbuf) < 0) {
12263 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12264 return -errno;
12265 }
12266 if (!S_ISCHR(stbuf.st_mode)) {
12267 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12268 return -EINVAL;
12269 }
12270 num = minor(stbuf.st_rdev);
12271 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12272 return num;
12273
12274 }
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12291 {
12292
12293 struct dahdi_pvt *tmp;
12294 char fn[80];
12295 struct dahdi_bufferinfo bi;
12296
12297 int res;
12298 #if defined(HAVE_PRI)
12299 int span = 0;
12300 #endif
12301 int here = 0;
12302 int x;
12303 struct analog_pvt *analog_p = NULL;
12304 struct dahdi_params p;
12305 #if defined(HAVE_PRI)
12306 struct dahdi_spaninfo si;
12307 struct sig_pri_chan *pri_chan = NULL;
12308 #endif
12309 #if defined(HAVE_SS7)
12310 struct sig_ss7_chan *ss7_chan = NULL;
12311 #endif
12312
12313
12314 for (tmp = iflist; tmp; tmp = tmp->next) {
12315 if (!tmp->destroy) {
12316 if (tmp->channel == channel) {
12317
12318 here = 1;
12319 break;
12320 }
12321 if (tmp->channel > channel) {
12322
12323 tmp = NULL;
12324 break;
12325 }
12326 }
12327 }
12328
12329 if (!here && reloading != 1) {
12330 tmp = ast_calloc(1, sizeof(*tmp));
12331 if (!tmp) {
12332 return NULL;
12333 }
12334 tmp->cc_params = ast_cc_config_params_init();
12335 if (!tmp->cc_params) {
12336 ast_free(tmp);
12337 return NULL;
12338 }
12339 ast_mutex_init(&tmp->lock);
12340 ifcount++;
12341 for (x = 0; x < 3; x++)
12342 tmp->subs[x].dfd = -1;
12343 tmp->channel = channel;
12344 tmp->priindication_oob = conf->chan.priindication_oob;
12345 }
12346
12347 if (tmp) {
12348 int chan_sig = conf->chan.sig;
12349
12350
12351 if (reloading && tmp->vars) {
12352 ast_variables_destroy(tmp->vars);
12353 tmp->vars = NULL;
12354 }
12355
12356
12357 if (!here) {
12358
12359 if ((channel != CHAN_PSEUDO)) {
12360 int count = 0;
12361
12362 snprintf(fn, sizeof(fn), "%d", channel);
12363
12364 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12365 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12366 usleep(1);
12367 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12368 count++;
12369 }
12370
12371 if (tmp->subs[SUB_REAL].dfd < 0) {
12372 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);
12373 destroy_dahdi_pvt(tmp);
12374 return NULL;
12375 }
12376 memset(&p, 0, sizeof(p));
12377 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12378 if (res < 0) {
12379 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12380 destroy_dahdi_pvt(tmp);
12381 return NULL;
12382 }
12383 if (conf->is_sig_auto)
12384 chan_sig = sigtype_to_signalling(p.sigtype);
12385 if (p.sigtype != (chan_sig & 0x3ffff)) {
12386 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));
12387 destroy_dahdi_pvt(tmp);
12388 return NULL;
12389 }
12390 tmp->law_default = p.curlaw;
12391 tmp->law = p.curlaw;
12392 tmp->span = p.spanno;
12393 #if defined(HAVE_PRI)
12394 span = p.spanno - 1;
12395 #endif
12396 } else {
12397 chan_sig = 0;
12398 }
12399 tmp->sig = chan_sig;
12400 tmp->outsigmod = conf->chan.outsigmod;
12401
12402 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12403 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12404 if (!analog_p) {
12405 destroy_dahdi_pvt(tmp);
12406 return NULL;
12407 }
12408 tmp->sig_pvt = analog_p;
12409 }
12410 #if defined(HAVE_SS7)
12411 if (chan_sig == SIG_SS7) {
12412 struct dahdi_ss7 *ss7;
12413 int clear = 0;
12414
12415 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12416 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12417 destroy_dahdi_pvt(tmp);
12418 return NULL;
12419 }
12420
12421 ss7 = ss7_resolve_linkset(cur_linkset);
12422 if (!ss7) {
12423 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12424 destroy_dahdi_pvt(tmp);
12425 return NULL;
12426 }
12427 ss7->ss7.span = cur_linkset;
12428 if (cur_cicbeginswith < 0) {
12429 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12430 destroy_dahdi_pvt(tmp);
12431 return NULL;
12432 }
12433 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12434 if (!ss7_chan) {
12435 destroy_dahdi_pvt(tmp);
12436 return NULL;
12437 }
12438 tmp->sig_pvt = ss7_chan;
12439 tmp->ss7 = &ss7->ss7;
12440
12441 ss7_chan->channel = tmp->channel;
12442 ss7_chan->cic = cur_cicbeginswith++;
12443
12444
12445 ss7_chan->dpc = cur_defaultdpc;
12446
12447 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12448
12449 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12450 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12451 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12452 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12453
12454 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12455 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12456 }
12457 #endif
12458 #ifdef HAVE_OPENR2
12459 if (chan_sig == SIG_MFCR2) {
12460 struct dahdi_mfcr2 *r2_link;
12461 r2_link = dahdi_r2_get_link();
12462 if (!r2_link) {
12463 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12464 destroy_dahdi_pvt(tmp);
12465 return NULL;
12466 }
12467 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12468 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12469 destroy_dahdi_pvt(tmp);
12470 return NULL;
12471 }
12472 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12473 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12474 destroy_dahdi_pvt(tmp);
12475 return NULL;
12476 }
12477 r2_link->pvts[r2_link->numchans++] = tmp;
12478 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12479 tmp->subs[SUB_REAL].dfd,
12480 NULL, NULL);
12481 if (!tmp->r2chan) {
12482 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12483 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12484 destroy_dahdi_pvt(tmp);
12485 return NULL;
12486 }
12487 tmp->mfcr2 = r2_link;
12488 if (conf->mfcr2.call_files) {
12489 openr2_chan_enable_call_files(tmp->r2chan);
12490 }
12491 openr2_chan_set_client_data(tmp->r2chan, tmp);
12492
12493 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12494 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12495 tmp->mfcr2_category = conf->mfcr2.category;
12496 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12497 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12498 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12499 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12500 tmp->mfcr2call = 0;
12501 tmp->mfcr2_dnis_index = 0;
12502 tmp->mfcr2_ani_index = 0;
12503 r2_link->monitored_count++;
12504 }
12505 #endif
12506 #ifdef HAVE_PRI
12507 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12508 int offset;
12509 int matchesdchan;
12510 int x,y;
12511 int myswitchtype = 0;
12512
12513 offset = 0;
12514 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12515 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12516 destroy_dahdi_pvt(tmp);
12517 return NULL;
12518 }
12519 if (span >= NUM_SPANS) {
12520 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12521 destroy_dahdi_pvt(tmp);
12522 return NULL;
12523 } else {
12524 si.spanno = 0;
12525 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12526 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12527 destroy_dahdi_pvt(tmp);
12528 return NULL;
12529 }
12530
12531 tmp->logicalspan = pris[span].prilogicalspan;
12532 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12533 if (span < 0) {
12534 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12535 destroy_dahdi_pvt(tmp);
12536 return NULL;
12537 }
12538 myswitchtype = conf->pri.pri.switchtype;
12539
12540 matchesdchan=0;
12541 for (x = 0; x < NUM_SPANS; x++) {
12542 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12543 if (pris[x].dchannels[y] == tmp->channel) {
12544 matchesdchan = 1;
12545 break;
12546 }
12547 }
12548 }
12549 if (!matchesdchan) {
12550 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12551 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12552 destroy_dahdi_pvt(tmp);
12553 return NULL;
12554 }
12555 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12556 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12557 destroy_dahdi_pvt(tmp);
12558 return NULL;
12559 }
12560 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12561 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));
12562 destroy_dahdi_pvt(tmp);
12563 return NULL;
12564 }
12565 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12566 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12567 destroy_dahdi_pvt(tmp);
12568 return NULL;
12569 }
12570 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12571 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12572 destroy_dahdi_pvt(tmp);
12573 return NULL;
12574 }
12575 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12576 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12577 destroy_dahdi_pvt(tmp);
12578 return NULL;
12579 }
12580 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12581 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12582 destroy_dahdi_pvt(tmp);
12583 return NULL;
12584 }
12585 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12586 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12587 pris[span].pri.trunkgroup);
12588 destroy_dahdi_pvt(tmp);
12589 return NULL;
12590 }
12591
12592 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12593 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12594 if (!pri_chan) {
12595 destroy_dahdi_pvt(tmp);
12596 return NULL;
12597 }
12598 tmp->sig_pvt = pri_chan;
12599 tmp->pri = &pris[span].pri;
12600
12601 tmp->priexclusive = conf->chan.priexclusive;
12602
12603 if (!tmp->pri->cc_params) {
12604 tmp->pri->cc_params = ast_cc_config_params_init();
12605 if (!tmp->pri->cc_params) {
12606 destroy_dahdi_pvt(tmp);
12607 return NULL;
12608 }
12609 }
12610 ast_cc_copy_config_params(tmp->pri->cc_params,
12611 conf->chan.cc_params);
12612
12613 pris[span].pri.sig = chan_sig;
12614 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12615 pris[span].pri.switchtype = myswitchtype;
12616 pris[span].pri.nsf = conf->pri.pri.nsf;
12617 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12618 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12619 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12620 pris[span].pri.minunused = conf->pri.pri.minunused;
12621 pris[span].pri.minidle = conf->pri.pri.minidle;
12622 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12623 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12624 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12625 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12626 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12627 #endif
12628 #ifdef HAVE_PRI_INBANDDISCONNECT
12629 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12630 #endif
12631 #if defined(HAVE_PRI_CALL_HOLD)
12632 pris[span].pri.hold_disconnect_transfer =
12633 conf->pri.pri.hold_disconnect_transfer;
12634 #endif
12635 #if defined(HAVE_PRI_CCSS)
12636 pris[span].pri.cc_ptmp_recall_mode =
12637 conf->pri.pri.cc_ptmp_recall_mode;
12638 pris[span].pri.cc_qsig_signaling_link_req =
12639 conf->pri.pri.cc_qsig_signaling_link_req;
12640 pris[span].pri.cc_qsig_signaling_link_rsp =
12641 conf->pri.pri.cc_qsig_signaling_link_rsp;
12642 #endif
12643 #if defined(HAVE_PRI_CALL_WAITING)
12644 pris[span].pri.max_call_waiting_calls =
12645 conf->pri.pri.max_call_waiting_calls;
12646 pris[span].pri.allow_call_waiting_calls =
12647 conf->pri.pri.allow_call_waiting_calls;
12648 #endif
12649 pris[span].pri.transfer = conf->chan.transfer;
12650 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12651 #if defined(HAVE_PRI_L2_PERSISTENCE)
12652 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12653 #endif
12654 #if defined(HAVE_PRI_AOC_EVENTS)
12655 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12656 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12657 #endif
12658 if (chan_sig == SIG_BRI_PTMP) {
12659 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12660 } else {
12661
12662 pris[span].pri.layer1_ignored = 0;
12663 }
12664 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12665 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12666 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12667 #if defined(HAVE_PRI_MWI)
12668 ast_copy_string(pris[span].pri.mwi_mailboxes,
12669 conf->pri.pri.mwi_mailboxes,
12670 sizeof(pris[span].pri.mwi_mailboxes));
12671 #endif
12672 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12673 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12674 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12675 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12676 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12677 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12678 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12679 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12680
12681 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12682 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12683 }
12684
12685 #if defined(HAVE_PRI_CALL_WAITING)
12686
12687 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12688 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12689 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12690 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12691 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12692 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12693 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12694 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12695 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12696 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12697 #endif
12698 } else {
12699 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12700 destroy_dahdi_pvt(tmp);
12701 return NULL;
12702 }
12703 }
12704 }
12705 #endif
12706 } else {
12707
12708 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));
12709 chan_sig = tmp->sig;
12710 if (tmp->subs[SUB_REAL].dfd > -1) {
12711 memset(&p, 0, sizeof(p));
12712 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12713 }
12714 }
12715
12716 switch (chan_sig) {
12717 case SIG_FXSKS:
12718 case SIG_FXSLS:
12719 case SIG_EM:
12720 case SIG_EM_E1:
12721 case SIG_EMWINK:
12722 case SIG_FEATD:
12723 case SIG_FEATDMF:
12724 case SIG_FEATDMF_TA:
12725 case SIG_FEATB:
12726 case SIG_E911:
12727 case SIG_SF:
12728 case SIG_SFWINK:
12729 case SIG_FGC_CAMA:
12730 case SIG_FGC_CAMAMF:
12731 case SIG_SF_FEATD:
12732 case SIG_SF_FEATDMF:
12733 case SIG_SF_FEATB:
12734 p.starttime = 250;
12735 break;
12736 }
12737
12738 if (tmp->radio) {
12739
12740 p.channo = channel;
12741 p.rxwinktime = 1;
12742 p.rxflashtime = 1;
12743 p.starttime = 1;
12744 p.debouncetime = 5;
12745 } else {
12746 p.channo = channel;
12747
12748 if (conf->timing.prewinktime >= 0)
12749 p.prewinktime = conf->timing.prewinktime;
12750 if (conf->timing.preflashtime >= 0)
12751 p.preflashtime = conf->timing.preflashtime;
12752 if (conf->timing.winktime >= 0)
12753 p.winktime = conf->timing.winktime;
12754 if (conf->timing.flashtime >= 0)
12755 p.flashtime = conf->timing.flashtime;
12756 if (conf->timing.starttime >= 0)
12757 p.starttime = conf->timing.starttime;
12758 if (conf->timing.rxwinktime >= 0)
12759 p.rxwinktime = conf->timing.rxwinktime;
12760 if (conf->timing.rxflashtime >= 0)
12761 p.rxflashtime = conf->timing.rxflashtime;
12762 if (conf->timing.debouncetime >= 0)
12763 p.debouncetime = conf->timing.debouncetime;
12764 }
12765
12766
12767 if (tmp->subs[SUB_REAL].dfd >= 0)
12768 {
12769 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12770 if (res < 0) {
12771 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12772 destroy_dahdi_pvt(tmp);
12773 return NULL;
12774 }
12775 }
12776 #if 1
12777 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12778 memset(&bi, 0, sizeof(bi));
12779 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12780 if (!res) {
12781 bi.txbufpolicy = conf->chan.buf_policy;
12782 bi.rxbufpolicy = conf->chan.buf_policy;
12783 bi.numbufs = conf->chan.buf_no;
12784 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12785 if (res < 0) {
12786 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12787 }
12788 } else {
12789 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12790 }
12791 tmp->buf_policy = conf->chan.buf_policy;
12792 tmp->buf_no = conf->chan.buf_no;
12793 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12794 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12795 tmp->faxbuf_no = conf->chan.faxbuf_no;
12796
12797
12798
12799
12800 tmp->bufsize = bi.bufsize;
12801 }
12802 #endif
12803 tmp->immediate = conf->chan.immediate;
12804 tmp->transfertobusy = conf->chan.transfertobusy;
12805 if (chan_sig & __DAHDI_SIG_FXS) {
12806 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12807 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12808 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12809 }
12810 tmp->ringt_base = ringt_base;
12811 tmp->firstradio = 0;
12812 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12813 tmp->permcallwaiting = conf->chan.callwaiting;
12814 else
12815 tmp->permcallwaiting = 0;
12816
12817 tmp->destroy = 0;
12818 tmp->drings = conf->chan.drings;
12819
12820
12821 if (tmp->drings.ringnum[0].range == 0)
12822 tmp->drings.ringnum[0].range = 10;
12823 if (tmp->drings.ringnum[1].range == 0)
12824 tmp->drings.ringnum[1].range = 10;
12825 if (tmp->drings.ringnum[2].range == 0)
12826 tmp->drings.ringnum[2].range = 10;
12827
12828 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12829 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12830 tmp->threewaycalling = conf->chan.threewaycalling;
12831 tmp->adsi = conf->chan.adsi;
12832 tmp->use_smdi = conf->chan.use_smdi;
12833 tmp->permhidecallerid = conf->chan.hidecallerid;
12834 tmp->hidecalleridname = conf->chan.hidecalleridname;
12835 tmp->callreturn = conf->chan.callreturn;
12836 tmp->echocancel = conf->chan.echocancel;
12837 tmp->echotraining = conf->chan.echotraining;
12838 tmp->pulse = conf->chan.pulse;
12839 if (tmp->echocancel.head.tap_length) {
12840 tmp->echocanbridged = conf->chan.echocanbridged;
12841 } else {
12842 if (conf->chan.echocanbridged)
12843 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12844 tmp->echocanbridged = 0;
12845 }
12846 tmp->busydetect = conf->chan.busydetect;
12847 tmp->busycount = conf->chan.busycount;
12848 tmp->busycompare = conf->chan.busycompare;
12849 tmp->busytonelength = conf->chan.busytonelength;
12850 tmp->busyquietlength = conf->chan.busyquietlength;
12851 tmp->busyfuzziness = conf->chan.busyfuzziness;
12852 tmp->silencethreshold = conf->chan.silencethreshold;
12853 tmp->callprogress = conf->chan.callprogress;
12854 tmp->waitfordialtone = conf->chan.waitfordialtone;
12855 tmp->cancallforward = conf->chan.cancallforward;
12856 tmp->dtmfrelax = conf->chan.dtmfrelax;
12857 tmp->callwaiting = tmp->permcallwaiting;
12858 tmp->hidecallerid = tmp->permhidecallerid;
12859 tmp->channel = channel;
12860 tmp->stripmsd = conf->chan.stripmsd;
12861 tmp->use_callerid = conf->chan.use_callerid;
12862 tmp->cid_signalling = conf->chan.cid_signalling;
12863 tmp->cid_start = conf->chan.cid_start;
12864 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12865 tmp->restrictcid = conf->chan.restrictcid;
12866 tmp->use_callingpres = conf->chan.use_callingpres;
12867 if (tmp->usedistinctiveringdetection) {
12868 if (!tmp->use_callerid) {
12869 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12870 tmp->use_callerid = 1;
12871 }
12872 }
12873
12874 if (tmp->cid_signalling == CID_SIG_SMDI) {
12875 if (!tmp->use_smdi) {
12876 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12877 tmp->use_smdi = 1;
12878 }
12879 }
12880 if (tmp->use_smdi) {
12881 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12882 if (!(tmp->smdi_iface)) {
12883 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12884 tmp->use_smdi = 0;
12885 }
12886 }
12887
12888 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12889 tmp->amaflags = conf->chan.amaflags;
12890 if (!here) {
12891 tmp->confno = -1;
12892 tmp->propconfno = -1;
12893 }
12894 tmp->canpark = conf->chan.canpark;
12895 tmp->transfer = conf->chan.transfer;
12896 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12897 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12898 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12899 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12900 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12901 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12902 tmp->cid_ton = 0;
12903 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12904 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12905 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12906 } else {
12907 tmp->cid_num[0] = '\0';
12908 tmp->cid_name[0] = '\0';
12909 }
12910 #if defined(HAVE_PRI)
12911 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12912 tmp->cid_tag[0] = '\0';
12913 } else
12914 #endif
12915 {
12916 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12917 }
12918 tmp->cid_subaddr[0] = '\0';
12919 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12920 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12921 char *mailbox, *context;
12922 mailbox = context = ast_strdupa(tmp->mailbox);
12923 strsep(&context, "@");
12924 if (ast_strlen_zero(context))
12925 context = "default";
12926 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12927 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12928 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12929 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12930 AST_EVENT_IE_END);
12931 }
12932 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12933 tmp->mwisend_setting = conf->chan.mwisend_setting;
12934 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12935 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12936 #endif
12937
12938 tmp->group = conf->chan.group;
12939 tmp->callgroup = conf->chan.callgroup;
12940 tmp->pickupgroup= conf->chan.pickupgroup;
12941 if (conf->chan.vars) {
12942 struct ast_variable *v, *tmpvar;
12943 for (v = conf->chan.vars ; v ; v = v->next) {
12944 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12945 tmpvar->next = tmp->vars;
12946 tmp->vars = tmpvar;
12947 }
12948 }
12949 }
12950 tmp->cid_rxgain = conf->chan.cid_rxgain;
12951 tmp->rxgain = conf->chan.rxgain;
12952 tmp->txgain = conf->chan.txgain;
12953 tmp->txdrc = conf->chan.txdrc;
12954 tmp->rxdrc = conf->chan.rxdrc;
12955 tmp->tonezone = conf->chan.tonezone;
12956 if (tmp->subs[SUB_REAL].dfd > -1) {
12957 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12958 if (tmp->dsp)
12959 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12960 update_conf(tmp);
12961 if (!here) {
12962 switch (chan_sig) {
12963 case SIG_PRI_LIB_HANDLE_CASES:
12964 case SIG_SS7:
12965 case SIG_MFCR2:
12966 break;
12967 default:
12968
12969 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12970 break;
12971 }
12972 }
12973 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12974 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12975
12976 switch (tmp->sig) {
12977 #ifdef HAVE_PRI
12978 case SIG_PRI_LIB_HANDLE_CASES:
12979 sig_pri_set_alarm(tmp->sig_pvt, 1);
12980 break;
12981 #endif
12982 #if defined(HAVE_SS7)
12983 case SIG_SS7:
12984 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12985 break;
12986 #endif
12987 default:
12988
12989 analog_p = tmp->sig_pvt;
12990 if (analog_p) {
12991 analog_p->inalarm = 1;
12992 }
12993 tmp->inalarm = 1;
12994 break;
12995 }
12996 handle_alarms(tmp, res);
12997 }
12998 }
12999
13000 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13001 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13002 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13003 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13004 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13005
13006 if (!here) {
13007 tmp->locallyblocked = 0;
13008 tmp->remotelyblocked = 0;
13009 switch (tmp->sig) {
13010 #if defined(HAVE_PRI)
13011 case SIG_PRI_LIB_HANDLE_CASES:
13012 tmp->inservice = 1;
13013 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13014 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13015 if (chan_sig == SIG_PRI) {
13016 char db_chan_name[20];
13017 char db_answer[5];
13018
13019
13020
13021
13022
13023 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13024 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13025 unsigned *why;
13026
13027 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13028 if (tmp->pri->enable_service_message_support) {
13029 char state;
13030
13031 sscanf(db_answer, "%1c:%30u", &state, why);
13032
13033
13034 *why &= (SRVST_NEAREND | SRVST_FAREND);
13035 }
13036 if (!*why) {
13037 ast_db_del(db_chan_name, SRVST_DBKEY);
13038 }
13039 }
13040 }
13041 #endif
13042 break;
13043 #endif
13044 #if defined(HAVE_SS7)
13045 case SIG_SS7:
13046 tmp->inservice = 0;
13047 break;
13048 #endif
13049 default:
13050
13051 tmp->inservice = 1;
13052 break;
13053 }
13054 }
13055
13056 switch (tmp->sig) {
13057 #if defined(HAVE_PRI)
13058 case SIG_PRI_LIB_HANDLE_CASES:
13059 if (pri_chan) {
13060 pri_chan->channel = tmp->channel;
13061 pri_chan->hidecallerid = tmp->hidecallerid;
13062 pri_chan->hidecalleridname = tmp->hidecalleridname;
13063 pri_chan->immediate = tmp->immediate;
13064 pri_chan->inalarm = tmp->inalarm;
13065 pri_chan->priexclusive = tmp->priexclusive;
13066 pri_chan->priindication_oob = tmp->priindication_oob;
13067 pri_chan->use_callerid = tmp->use_callerid;
13068 pri_chan->use_callingpres = tmp->use_callingpres;
13069 ast_copy_string(pri_chan->context, tmp->context,
13070 sizeof(pri_chan->context));
13071 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13072 sizeof(pri_chan->mohinterpret));
13073 pri_chan->stripmsd = tmp->stripmsd;
13074 }
13075 break;
13076 #endif
13077 #if defined(HAVE_SS7)
13078 case SIG_SS7:
13079 if (ss7_chan) {
13080 ss7_chan->inalarm = tmp->inalarm;
13081
13082 ss7_chan->stripmsd = tmp->stripmsd;
13083 ss7_chan->hidecallerid = tmp->hidecallerid;
13084 ss7_chan->use_callerid = tmp->use_callerid;
13085 ss7_chan->use_callingpres = tmp->use_callingpres;
13086 ss7_chan->immediate = tmp->immediate;
13087 ss7_chan->locallyblocked = tmp->locallyblocked;
13088 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13089 ast_copy_string(ss7_chan->context, tmp->context,
13090 sizeof(ss7_chan->context));
13091 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13092 sizeof(ss7_chan->mohinterpret));
13093 }
13094 break;
13095 #endif
13096 default:
13097
13098 analog_p = tmp->sig_pvt;
13099 if (analog_p) {
13100 analog_p->channel = tmp->channel;
13101 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13102 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13103 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13104 analog_p->permcallwaiting = conf->chan.callwaiting;
13105 analog_p->callreturn = conf->chan.callreturn;
13106 analog_p->cancallforward = conf->chan.cancallforward;
13107 analog_p->canpark = conf->chan.canpark;
13108 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13109 analog_p->immediate = conf->chan.immediate;
13110 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13111 analog_p->pulse = conf->chan.pulse;
13112 analog_p->threewaycalling = conf->chan.threewaycalling;
13113 analog_p->transfer = conf->chan.transfer;
13114 analog_p->transfertobusy = conf->chan.transfertobusy;
13115 analog_p->use_callerid = tmp->use_callerid;
13116 analog_p->use_smdi = tmp->use_smdi;
13117 analog_p->smdi_iface = tmp->smdi_iface;
13118 analog_p->outsigmod = ANALOG_SIG_NONE;
13119 analog_p->echotraining = conf->chan.echotraining;
13120 analog_p->cid_signalling = conf->chan.cid_signalling;
13121 analog_p->stripmsd = conf->chan.stripmsd;
13122 switch (conf->chan.cid_start) {
13123 case CID_START_POLARITY:
13124 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13125 break;
13126 case CID_START_POLARITY_IN:
13127 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13128 break;
13129 case CID_START_DTMF_NOALERT:
13130 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13131 break;
13132 default:
13133 analog_p->cid_start = ANALOG_CID_START_RING;
13134 break;
13135 }
13136 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13137 analog_p->ringt = conf->chan.ringt;
13138 analog_p->ringt_base = ringt_base;
13139 analog_p->chan_tech = &dahdi_tech;
13140 analog_p->onhooktime = time(NULL);
13141 if (chan_sig & __DAHDI_SIG_FXO) {
13142 memset(&p, 0, sizeof(p));
13143 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13144 if (!res) {
13145 analog_p->fxsoffhookstate = p.rxisoffhook;
13146 }
13147 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13148 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13149 #endif
13150 }
13151 analog_p->msgstate = -1;
13152
13153 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13154 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13155 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13156
13157 analog_config_complete(analog_p);
13158 }
13159 break;
13160 }
13161 #if defined(HAVE_PRI)
13162 if (tmp->channel == CHAN_PSEUDO) {
13163
13164
13165
13166
13167 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13168 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13169 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13170 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13171 }
13172 #endif
13173 }
13174 if (tmp && !here) {
13175
13176 dahdi_iflist_insert(tmp);
13177 }
13178 return tmp;
13179 }
13180
13181 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13182 {
13183 #if defined(HAVE_PRI)
13184 if (0 < span) {
13185
13186 if (!p->pri || p->pri->span != span) {
13187 return 0;
13188 }
13189 if (!groupmatch && channelmatch == -1) {
13190
13191 *groupmatched = 1;
13192 return 1;
13193 }
13194 }
13195 #endif
13196
13197 if (groupmatch) {
13198 if ((p->group & groupmatch) != groupmatch)
13199
13200 return 0;
13201 *groupmatched = 1;
13202 }
13203
13204 if (channelmatch != -1) {
13205 if (p->channel != channelmatch)
13206
13207 return 0;
13208 *channelmatched = 1;
13209 }
13210
13211 return 1;
13212 }
13213
13214 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13215 {
13216 struct dahdi_pvt *p = *pvt;
13217
13218 if (p->inalarm)
13219 return 0;
13220
13221 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13222 return analog_available(p->sig_pvt);
13223
13224 switch (p->sig) {
13225 #if defined(HAVE_PRI)
13226 case SIG_PRI_LIB_HANDLE_CASES:
13227 {
13228 struct sig_pri_chan *pvt_chan;
13229 int res;
13230
13231 pvt_chan = p->sig_pvt;
13232 res = sig_pri_available(&pvt_chan, is_specific_channel);
13233 *pvt = pvt_chan->chan_pvt;
13234 return res;
13235 }
13236 #endif
13237 #if defined(HAVE_SS7)
13238 case SIG_SS7:
13239 return sig_ss7_available(p->sig_pvt);
13240 #endif
13241 default:
13242 break;
13243 }
13244
13245 if (p->locallyblocked || p->remotelyblocked) {
13246 return 0;
13247 }
13248
13249
13250 if (!p->owner) {
13251 #ifdef HAVE_OPENR2
13252
13253 if (p->mfcr2) {
13254 if (p->mfcr2call) {
13255 return 0;
13256 } else {
13257 return 1;
13258 }
13259 }
13260 #endif
13261 return 1;
13262 }
13263
13264 return 0;
13265 }
13266
13267 #if defined(HAVE_PRI)
13268 #if defined(HAVE_PRI_CALL_WAITING)
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279
13280
13281 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13282 {
13283 struct dahdi_pvt *pvt = priv;
13284
13285 pvt->stripmsd = pri->ch_cfg.stripmsd;
13286 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13287 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13288 pvt->immediate = pri->ch_cfg.immediate;
13289 pvt->priexclusive = pri->ch_cfg.priexclusive;
13290 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13291 pvt->use_callerid = pri->ch_cfg.use_callerid;
13292 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13293 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13294 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13295 }
13296 #endif
13297 #endif
13298
13299 #if defined(HAVE_PRI)
13300
13301
13302
13303
13304
13305
13306
13307
13308
13309
13310
13311
13312 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13313 {
13314 int pvt_idx;
13315 int res;
13316 unsigned idx;
13317 struct dahdi_pvt *pvt;
13318 struct sig_pri_chan *chan;
13319 struct dahdi_bufferinfo bi;
13320
13321 static int nobch_channel = CHAN_PSEUDO;
13322
13323
13324 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13325 if (!pri->pvts[pvt_idx]) {
13326 break;
13327 }
13328 }
13329 if (pri->numchans == pvt_idx) {
13330 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13331 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13332 return -1;
13333 }
13334
13335
13336 pri->pvts[pvt_idx] = NULL;
13337 ++pri->numchans;
13338 }
13339
13340 pvt = ast_calloc(1, sizeof(*pvt));
13341 if (!pvt) {
13342 return -1;
13343 }
13344 pvt->cc_params = ast_cc_config_params_init();
13345 if (!pvt->cc_params) {
13346 ast_free(pvt);
13347 return -1;
13348 }
13349 ast_mutex_init(&pvt->lock);
13350 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13351 pvt->subs[idx].dfd = -1;
13352 }
13353 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13354 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13355 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13356 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13357
13358 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13359 if (!chan) {
13360 destroy_dahdi_pvt(pvt);
13361 return -1;
13362 }
13363 chan->no_b_channel = 1;
13364
13365
13366
13367
13368
13369
13370 pvt->law_default = DAHDI_LAW_ALAW;
13371
13372 pvt->sig = pri->sig;
13373 pvt->outsigmod = -1;
13374 pvt->pri = pri;
13375 pvt->sig_pvt = chan;
13376 pri->pvts[pvt_idx] = chan;
13377
13378 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13379 if (pvt->subs[SUB_REAL].dfd < 0) {
13380 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13381 strerror(errno));
13382 destroy_dahdi_pvt(pvt);
13383 return -1;
13384 }
13385 memset(&bi, 0, sizeof(bi));
13386 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13387 if (!res) {
13388 pvt->bufsize = bi.bufsize;
13389 bi.txbufpolicy = pvt->buf_policy;
13390 bi.rxbufpolicy = pvt->buf_policy;
13391 bi.numbufs = pvt->buf_no;
13392 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13393 if (res < 0) {
13394 ast_log(LOG_WARNING,
13395 "Unable to set buffer policy on no B channel interface: %s\n",
13396 strerror(errno));
13397 }
13398 } else
13399 ast_log(LOG_WARNING,
13400 "Unable to check buffer policy on no B channel interface: %s\n",
13401 strerror(errno));
13402
13403 --nobch_channel;
13404 if (CHAN_PSEUDO < nobch_channel) {
13405 nobch_channel = CHAN_PSEUDO - 1;
13406 }
13407 pvt->channel = nobch_channel;
13408 pvt->span = pri->span;
13409 chan->channel = pvt->channel;
13410
13411 dahdi_nobch_insert(pri, pvt);
13412
13413 return pvt_idx;
13414 }
13415 #endif
13416
13417
13418
13419
13420
13421
13422 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13423 {
13424 struct dahdi_pvt *p;
13425 struct dahdi_bufferinfo bi;
13426 int res;
13427
13428 p = ast_malloc(sizeof(*p));
13429 if (!p) {
13430 return NULL;
13431 }
13432 *p = *src;
13433
13434
13435 p->cc_params = ast_cc_config_params_init();
13436 if (!p->cc_params) {
13437 ast_free(p);
13438 return NULL;
13439 }
13440 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13441
13442 p->which_iflist = DAHDI_IFLIST_NONE;
13443 p->next = NULL;
13444 p->prev = NULL;
13445 ast_mutex_init(&p->lock);
13446 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13447 if (p->subs[SUB_REAL].dfd < 0) {
13448 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13449 destroy_dahdi_pvt(p);
13450 return NULL;
13451 }
13452 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13453 if (!res) {
13454 bi.txbufpolicy = src->buf_policy;
13455 bi.rxbufpolicy = src->buf_policy;
13456 bi.numbufs = src->buf_no;
13457 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13458 if (res < 0) {
13459 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13460 }
13461 } else
13462 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13463 p->destroy = 1;
13464 dahdi_iflist_insert(p);
13465 return p;
13466 }
13467
13468 struct dahdi_starting_point {
13469
13470 ast_group_t groupmatch;
13471
13472 int channelmatch;
13473
13474 int rr_starting_point;
13475
13476 int span;
13477
13478 int cadance;
13479
13480 char opt;
13481
13482 char backwards;
13483
13484 char roundrobin;
13485 };
13486 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13487 {
13488 char *dest;
13489 char *s;
13490 int x;
13491 int res = 0;
13492 struct dahdi_pvt *p;
13493 char *subdir = NULL;
13494 AST_DECLARE_APP_ARGS(args,
13495 AST_APP_ARG(group);
13496
13497
13498 AST_APP_ARG(other);
13499 );
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524 if (data) {
13525 dest = ast_strdupa(data);
13526 } else {
13527 ast_log(LOG_WARNING, "Channel requested with no data\n");
13528 return NULL;
13529 }
13530 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13531 if (!args.argc || ast_strlen_zero(args.group)) {
13532 ast_log(LOG_WARNING, "No channel/group specified\n");
13533 return NULL;
13534 }
13535
13536
13537 memset(param, 0, sizeof(*param));
13538 param->channelmatch = -1;
13539
13540 if (strchr(args.group, '!') != NULL) {
13541 char *prev = args.group;
13542 while ((s = strchr(prev, '!')) != NULL) {
13543 *s++ = '/';
13544 prev = s;
13545 }
13546 *(prev - 1) = '\0';
13547 subdir = args.group;
13548 args.group = prev;
13549 } else if (args.group[0] == 'i') {
13550
13551 res = sscanf(args.group + 1, "%30d", &x);
13552 if (res < 1) {
13553 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13554 return NULL;
13555 }
13556 param->span = x;
13557
13558
13559 s = strchr(args.group, '-');
13560 if (!s) {
13561
13562 return iflist;
13563 }
13564 args.group = s + 1;
13565 res = 0;
13566 }
13567 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13568
13569 s = args.group + 1;
13570 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13571 if (res < 1) {
13572 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13573 return NULL;
13574 }
13575 param->groupmatch = ((ast_group_t) 1 << x);
13576
13577 if (toupper(args.group[0]) == 'G') {
13578 if (args.group[0] == 'G') {
13579 param->backwards = 1;
13580 p = ifend;
13581 } else
13582 p = iflist;
13583 } else {
13584 if (ARRAY_LEN(round_robin) <= x) {
13585 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13586 x, data);
13587 return NULL;
13588 }
13589 if (args.group[0] == 'R') {
13590 param->backwards = 1;
13591 p = round_robin[x] ? round_robin[x]->prev : ifend;
13592 if (!p)
13593 p = ifend;
13594 } else {
13595 p = round_robin[x] ? round_robin[x]->next : iflist;
13596 if (!p)
13597 p = iflist;
13598 }
13599 param->roundrobin = 1;
13600 param->rr_starting_point = x;
13601 }
13602 } else {
13603 s = args.group;
13604 if (!strcasecmp(s, "pseudo")) {
13605
13606 x = CHAN_PSEUDO;
13607 param->channelmatch = x;
13608 } else {
13609 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13610 if (res < 1) {
13611 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13612 return NULL;
13613 } else {
13614 param->channelmatch = x;
13615 }
13616 }
13617 if (subdir) {
13618 char path[PATH_MAX];
13619 struct stat stbuf;
13620
13621 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13622 subdir, param->channelmatch);
13623 if (stat(path, &stbuf) < 0) {
13624 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13625 path, strerror(errno));
13626 return NULL;
13627 }
13628 if (!S_ISCHR(stbuf.st_mode)) {
13629 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13630 path);
13631 return NULL;
13632 }
13633 param->channelmatch = minor(stbuf.st_rdev);
13634 }
13635
13636 p = iflist;
13637 }
13638
13639 if (param->opt == 'r' && res < 3) {
13640 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13641 param->opt = '\0';
13642 }
13643
13644 return p;
13645 }
13646
13647 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13648 {
13649 int callwait = 0;
13650 struct dahdi_pvt *p;
13651 struct ast_channel *tmp = NULL;
13652 struct dahdi_pvt *exitpvt;
13653 int channelmatched = 0;
13654 int groupmatched = 0;
13655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13656 int transcapdigital = 0;
13657 #endif
13658 struct dahdi_starting_point start;
13659
13660 ast_mutex_lock(&iflock);
13661 p = determine_starting_point(data, &start);
13662 if (!p) {
13663
13664 ast_mutex_unlock(&iflock);
13665 return NULL;
13666 }
13667
13668
13669 exitpvt = p;
13670 while (p && !tmp) {
13671 if (start.roundrobin)
13672 round_robin[start.rr_starting_point] = p;
13673
13674 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13675 && available(&p, channelmatched)) {
13676 ast_debug(1, "Using channel %d\n", p->channel);
13677
13678 callwait = (p->owner != NULL);
13679 #ifdef HAVE_OPENR2
13680 if (p->mfcr2) {
13681 ast_mutex_lock(&p->lock);
13682 if (p->mfcr2call) {
13683 ast_mutex_unlock(&p->lock);
13684 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13685 goto next;
13686 }
13687 p->mfcr2call = 1;
13688 ast_mutex_unlock(&p->lock);
13689 }
13690 #endif
13691 if (p->channel == CHAN_PSEUDO) {
13692 p = duplicate_pseudo(p);
13693 if (!p) {
13694 break;
13695 }
13696 }
13697
13698 p->distinctivering = 0;
13699
13700 switch (start.opt) {
13701 case '\0':
13702
13703 break;
13704 case 'c':
13705
13706 p->confirmanswer = 1;
13707 break;
13708 case 'r':
13709
13710 p->distinctivering = start.cadance;
13711 break;
13712 case 'd':
13713 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13714
13715 transcapdigital = AST_TRANS_CAP_DIGITAL;
13716 #endif
13717 break;
13718 default:
13719 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13720 break;
13721 }
13722
13723 p->outgoing = 1;
13724 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13725 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13726 #ifdef HAVE_PRI
13727 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13728
13729
13730
13731
13732
13733 ast_mutex_lock(&p->lock);
13734 ast_mutex_unlock(&p->lock);
13735
13736 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13737 sizeof(p->dnid));
13738 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13739 #endif
13740 #if defined(HAVE_SS7)
13741 } else if (p->sig == SIG_SS7) {
13742 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13743 #endif
13744 } else {
13745 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13746 }
13747 if (!tmp) {
13748 p->outgoing = 0;
13749 #if defined(HAVE_PRI)
13750 switch (p->sig) {
13751 case SIG_PRI_LIB_HANDLE_CASES:
13752 #if defined(HAVE_PRI_CALL_WAITING)
13753 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13754 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13755 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13756 }
13757 #endif
13758
13759
13760
13761
13762 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13763 break;
13764 default:
13765 break;
13766 }
13767 #endif
13768 } else {
13769 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13770 }
13771 break;
13772 }
13773 #ifdef HAVE_OPENR2
13774 next:
13775 #endif
13776 if (start.backwards) {
13777 p = p->prev;
13778 if (!p)
13779 p = ifend;
13780 } else {
13781 p = p->next;
13782 if (!p)
13783 p = iflist;
13784 }
13785
13786 if (p == exitpvt)
13787 break;
13788 }
13789 ast_mutex_unlock(&iflock);
13790 restart_monitor();
13791 if (cause && !tmp) {
13792 if (callwait || channelmatched) {
13793 *cause = AST_CAUSE_BUSY;
13794 } else if (groupmatched) {
13795 *cause = AST_CAUSE_CONGESTION;
13796 } else {
13797
13798
13799
13800
13801 }
13802 }
13803
13804 return tmp;
13805 }
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817 static int dahdi_devicestate(void *data)
13818 {
13819 #if defined(HAVE_PRI)
13820 char *device;
13821 unsigned span;
13822 int res;
13823
13824 device = data;
13825
13826 if (*device != 'I') {
13827
13828 return AST_DEVICE_UNKNOWN;
13829 }
13830 res = sscanf(device, "I%30u", &span);
13831 if (res != 1 || !span || NUM_SPANS < span) {
13832
13833 return AST_DEVICE_UNKNOWN;
13834 }
13835 device = strchr(device, '/');
13836 if (!device) {
13837
13838 return AST_DEVICE_UNKNOWN;
13839 }
13840
13841
13842
13843
13844
13845 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13846 ++device;
13847 if (!strcmp(device, "congestion"))
13848 #endif
13849 {
13850 return pris[span - 1].pri.congestion_devstate;
13851 }
13852 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13853 else if (!strcmp(device, "threshold")) {
13854 return pris[span - 1].pri.threshold_devstate;
13855 }
13856 return AST_DEVICE_UNKNOWN;
13857 #endif
13858 #else
13859 return AST_DEVICE_UNKNOWN;
13860 #endif
13861 }
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874
13875
13876
13877
13878
13879 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13880 {
13881 struct dahdi_pvt *p;
13882 struct dahdi_pvt *exitpvt;
13883 struct dahdi_starting_point start;
13884 int groupmatched = 0;
13885 int channelmatched = 0;
13886
13887 ast_mutex_lock(&iflock);
13888 p = determine_starting_point(dest, &start);
13889 if (!p) {
13890 ast_mutex_unlock(&iflock);
13891 return -1;
13892 }
13893 exitpvt = p;
13894 for (;;) {
13895 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13896
13897 struct ast_str *device_name;
13898 char *dash;
13899 const char *monitor_type;
13900 char dialstring[AST_CHANNEL_NAME];
13901 char full_device_name[AST_CHANNEL_NAME];
13902
13903 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13904 case AST_CC_MONITOR_NEVER:
13905 break;
13906 case AST_CC_MONITOR_NATIVE:
13907 case AST_CC_MONITOR_ALWAYS:
13908 case AST_CC_MONITOR_GENERIC:
13909 #if defined(HAVE_PRI)
13910 if (dahdi_sig_pri_lib_handles(p->sig)) {
13911
13912
13913
13914
13915 snprintf(full_device_name, sizeof(full_device_name),
13916 "DAHDI/I%d/congestion", p->pri->span);
13917 } else
13918 #endif
13919 {
13920 #if defined(HAVE_PRI)
13921 device_name = create_channel_name(p, 1, "");
13922 #else
13923 device_name = create_channel_name(p);
13924 #endif
13925 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13926 device_name ? ast_str_buffer(device_name) : "");
13927 ast_free(device_name);
13928
13929
13930
13931
13932
13933 dash = strrchr(full_device_name, '-');
13934 if (dash) {
13935 *dash = '\0';
13936 }
13937 }
13938 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13939
13940
13941
13942
13943
13944
13945
13946 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13947 callback(inbound,
13948 #if defined(HAVE_PRI)
13949 p->pri ? p->pri->cc_params : p->cc_params,
13950 #else
13951 p->cc_params,
13952 #endif
13953 monitor_type, full_device_name, dialstring, NULL);
13954 break;
13955 }
13956 }
13957 p = start.backwards ? p->prev : p->next;
13958 if (!p) {
13959 p = start.backwards ? ifend : iflist;
13960 }
13961 if (p == exitpvt) {
13962 break;
13963 }
13964 }
13965 ast_mutex_unlock(&iflock);
13966 return 0;
13967 }
13968
13969 #if defined(HAVE_SS7)
13970 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13971 {
13972 int i;
13973
13974 if (ss7) {
13975 for (i = 0; i < NUM_SPANS; i++) {
13976 if (linksets[i].ss7.ss7 == ss7) {
13977 ast_verbose("[%d] %s", i + 1, s);
13978 return;
13979 }
13980 }
13981 }
13982 ast_verbose("%s", s);
13983 }
13984 #endif
13985
13986 #if defined(HAVE_SS7)
13987 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13988 {
13989 int i;
13990
13991 if (ss7) {
13992 for (i = 0; i < NUM_SPANS; i++) {
13993 if (linksets[i].ss7.ss7 == ss7) {
13994 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13995 return;
13996 }
13997 }
13998 }
13999 ast_log(LOG_ERROR, "%s", s);
14000 }
14001 #endif
14002
14003 #if defined(HAVE_OPENR2)
14004 static void *mfcr2_monitor(void *data)
14005 {
14006 struct dahdi_mfcr2 *mfcr2 = data;
14007
14008
14009
14010
14011
14012 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14013 int res = 0;
14014 int i = 0;
14015 int oldstate = 0;
14016 int quit_loop = 0;
14017 int maxsleep = 20;
14018 int was_idle = 0;
14019 int pollsize = 0;
14020
14021
14022 for (i = 0; i < mfcr2->numchans; i++) {
14023 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14024 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14025 }
14026 while (1) {
14027
14028
14029 pollsize = 0;
14030 for (i = 0; i < mfcr2->numchans; i++) {
14031 pollers[i].revents = 0;
14032 pollers[i].events = 0;
14033 if (mfcr2->pvts[i]->owner) {
14034 continue;
14035 }
14036 if (!mfcr2->pvts[i]->r2chan) {
14037 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14038 quit_loop = 1;
14039 break;
14040 }
14041 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14042 pollers[i].events = POLLIN | POLLPRI;
14043 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14044 pollsize++;
14045 }
14046 if (quit_loop) {
14047 break;
14048 }
14049 if (pollsize == 0) {
14050 if (!was_idle) {
14051 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14052 was_idle = 1;
14053 }
14054 poll(NULL, 0, maxsleep);
14055 continue;
14056 }
14057 was_idle = 0;
14058
14059
14060 pthread_testcancel();
14061 res = poll(pollers, mfcr2->numchans, maxsleep);
14062 pthread_testcancel();
14063 if ((res < 0) && (errno != EINTR)) {
14064 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14065 break;
14066 }
14067
14068 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14069 for (i = 0; i < mfcr2->numchans; i++) {
14070 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14071 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14072 }
14073 }
14074 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14075 }
14076 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14077 return 0;
14078 }
14079 #endif
14080
14081 #if defined(HAVE_PRI)
14082 #ifndef PRI_RESTART
14083 #error "Upgrade your libpri"
14084 #endif
14085 static void dahdi_pri_message(struct pri *pri, char *s)
14086 {
14087 int x;
14088 int y;
14089 int dchan = -1;
14090 int span = -1;
14091 int dchancount = 0;
14092
14093 if (pri) {
14094 for (x = 0; x < NUM_SPANS; x++) {
14095 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14096 if (pris[x].pri.dchans[y]) {
14097 dchancount++;
14098 }
14099
14100 if (pris[x].pri.dchans[y] == pri) {
14101 dchan = y;
14102 }
14103 }
14104 if (dchan >= 0) {
14105 span = x;
14106 break;
14107 }
14108 dchancount = 0;
14109 }
14110 if (-1 < span) {
14111 if (1 < dchancount) {
14112 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14113 } else {
14114 ast_verbose("PRI Span: %d %s", span + 1, s);
14115 }
14116 } else {
14117 ast_verbose("PRI Span: ? %s", s);
14118 }
14119 } else {
14120 ast_verbose("PRI Span: ? %s", s);
14121 }
14122
14123 ast_mutex_lock(&pridebugfdlock);
14124
14125 if (pridebugfd >= 0) {
14126 if (write(pridebugfd, s, strlen(s)) < 0) {
14127 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14128 }
14129 }
14130
14131 ast_mutex_unlock(&pridebugfdlock);
14132 }
14133 #endif
14134
14135 #if defined(HAVE_PRI)
14136 static void dahdi_pri_error(struct pri *pri, char *s)
14137 {
14138 int x;
14139 int y;
14140 int dchan = -1;
14141 int span = -1;
14142 int dchancount = 0;
14143
14144 if (pri) {
14145 for (x = 0; x < NUM_SPANS; x++) {
14146 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14147 if (pris[x].pri.dchans[y]) {
14148 dchancount++;
14149 }
14150
14151 if (pris[x].pri.dchans[y] == pri) {
14152 dchan = y;
14153 }
14154 }
14155 if (dchan >= 0) {
14156 span = x;
14157 break;
14158 }
14159 dchancount = 0;
14160 }
14161 if (-1 < span) {
14162 if (1 < dchancount) {
14163 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14164 } else {
14165 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14166 }
14167 } else {
14168 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14169 }
14170 } else {
14171 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14172 }
14173
14174 ast_mutex_lock(&pridebugfdlock);
14175
14176 if (pridebugfd >= 0) {
14177 if (write(pridebugfd, s, strlen(s)) < 0) {
14178 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14179 }
14180 }
14181
14182 ast_mutex_unlock(&pridebugfdlock);
14183 }
14184 #endif
14185
14186 #if defined(HAVE_PRI)
14187 static int prepare_pri(struct dahdi_pri *pri)
14188 {
14189 int i, res, x;
14190 struct dahdi_params p;
14191 struct dahdi_bufferinfo bi;
14192 struct dahdi_spaninfo si;
14193
14194 pri->pri.calls = &dahdi_pri_callbacks;
14195
14196 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14197 if (!pri->dchannels[i])
14198 break;
14199 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14200 x = pri->dchannels[i];
14201 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14202 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14203 return -1;
14204 }
14205 memset(&p, 0, sizeof(p));
14206 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14207 if (res) {
14208 dahdi_close_pri_fd(pri, i);
14209 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14210 return -1;
14211 }
14212 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14213 dahdi_close_pri_fd(pri, i);
14214 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14215 return -1;
14216 }
14217 memset(&si, 0, sizeof(si));
14218 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14219 if (res) {
14220 dahdi_close_pri_fd(pri, i);
14221 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14222 }
14223 if (!si.alarms) {
14224 pri_event_noalarm(&pri->pri, i, 1);
14225 } else {
14226 pri_event_alarm(&pri->pri, i, 1);
14227 }
14228 memset(&bi, 0, sizeof(bi));
14229 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14230 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14231 bi.numbufs = 32;
14232 bi.bufsize = 1024;
14233 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14234 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14235 dahdi_close_pri_fd(pri, i);
14236 return -1;
14237 }
14238 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14239 }
14240 return 0;
14241 }
14242 #endif
14243
14244 #if defined(HAVE_PRI)
14245 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14246 {
14247 int which, span;
14248 char *ret = NULL;
14249
14250 if (pos != rpos)
14251 return ret;
14252
14253 for (which = span = 0; span < NUM_SPANS; span++) {
14254 if (pris[span].pri.pri && ++which > state) {
14255 if (asprintf(&ret, "%d", span + 1) < 0) {
14256 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14257 }
14258 break;
14259 }
14260 }
14261 return ret;
14262 }
14263 #endif
14264
14265 #if defined(HAVE_PRI)
14266 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14267 {
14268 return complete_span_helper(line,word,pos,state,3);
14269 }
14270 #endif
14271
14272 #if defined(HAVE_PRI)
14273 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14274 {
14275 int myfd;
14276 switch (cmd) {
14277 case CLI_INIT:
14278 e->command = "pri set debug file";
14279 e->usage = "Usage: pri set debug file [output-file]\n"
14280 " Sends PRI debug output to the specified output file\n";
14281 return NULL;
14282 case CLI_GENERATE:
14283 return NULL;
14284 }
14285 if (a->argc < 5)
14286 return CLI_SHOWUSAGE;
14287
14288 if (ast_strlen_zero(a->argv[4]))
14289 return CLI_SHOWUSAGE;
14290
14291 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14292 if (myfd < 0) {
14293 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14294 return CLI_SUCCESS;
14295 }
14296
14297 ast_mutex_lock(&pridebugfdlock);
14298
14299 if (pridebugfd >= 0)
14300 close(pridebugfd);
14301
14302 pridebugfd = myfd;
14303 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14304 ast_mutex_unlock(&pridebugfdlock);
14305 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14306 return CLI_SUCCESS;
14307 }
14308 #endif
14309
14310 #if defined(HAVE_PRI)
14311 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14312 {
14313 int span;
14314 int x;
14315 int level = 0;
14316 switch (cmd) {
14317 case CLI_INIT:
14318 e->command = "pri set debug {on|off|0|1|2} span";
14319 e->usage =
14320 "Usage: pri set debug {<level>|on|off} span <span>\n"
14321 " Enables debugging on a given PRI span\n";
14322 return NULL;
14323 case CLI_GENERATE:
14324 return complete_span_4(a->line, a->word, a->pos, a->n);
14325 }
14326 if (a->argc < 6) {
14327 return CLI_SHOWUSAGE;
14328 }
14329
14330 if (!strcasecmp(a->argv[3], "on")) {
14331 level = 1;
14332 } else if (!strcasecmp(a->argv[3], "off")) {
14333 level = 0;
14334 } else {
14335 level = atoi(a->argv[3]);
14336 }
14337 span = atoi(a->argv[5]);
14338 if ((span < 1) || (span > NUM_SPANS)) {
14339 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14340 return CLI_SUCCESS;
14341 }
14342 if (!pris[span-1].pri.pri) {
14343 ast_cli(a->fd, "No PRI running on span %d\n", span);
14344 return CLI_SUCCESS;
14345 }
14346
14347
14348 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14349 if (pris[span - 1].pri.dchans[x]) {
14350 switch (level) {
14351 case 0:
14352 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14353 break;
14354 case 1:
14355 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14356 break;
14357 default:
14358 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14359 break;
14360 }
14361 }
14362 }
14363 if (level == 0) {
14364
14365 ast_mutex_lock(&pridebugfdlock);
14366 if (0 <= pridebugfd) {
14367 close(pridebugfd);
14368 pridebugfd = -1;
14369 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14370 pridebugfilename);
14371 }
14372 ast_mutex_unlock(&pridebugfdlock);
14373 }
14374 pris[span - 1].pri.debug = (level) ? 1 : 0;
14375 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14376 return CLI_SUCCESS;
14377 }
14378 #endif
14379
14380 #if defined(HAVE_PRI)
14381 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14382 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14383 {
14384 unsigned *why;
14385 int channel;
14386 int trunkgroup;
14387 int x, y, fd = a->fd;
14388 int interfaceid = 0;
14389 char db_chan_name[20], db_answer[5];
14390 struct dahdi_pvt *tmp;
14391 struct dahdi_pri *pri;
14392
14393 if (a->argc < 5 || a->argc > 6)
14394 return CLI_SHOWUSAGE;
14395 if (strchr(a->argv[4], ':')) {
14396 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14397 return CLI_SHOWUSAGE;
14398 if ((trunkgroup < 1) || (channel < 1))
14399 return CLI_SHOWUSAGE;
14400 pri = NULL;
14401 for (x=0;x<NUM_SPANS;x++) {
14402 if (pris[x].pri.trunkgroup == trunkgroup) {
14403 pri = pris + x;
14404 break;
14405 }
14406 }
14407 if (!pri) {
14408 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14409 return CLI_FAILURE;
14410 }
14411 } else
14412 channel = atoi(a->argv[4]);
14413
14414 if (a->argc == 6)
14415 interfaceid = atoi(a->argv[5]);
14416
14417
14418 for (x = 0; x < NUM_SPANS; x++) {
14419 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14420 if (pris[x].dchannels[y] == channel) {
14421 pri = pris + x;
14422 if (pri->pri.enable_service_message_support) {
14423 ast_mutex_lock(&pri->pri.lock);
14424 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14425 ast_mutex_unlock(&pri->pri.lock);
14426 } else {
14427 ast_cli(fd,
14428 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14429 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14430 }
14431 return CLI_SUCCESS;
14432 }
14433 }
14434 }
14435
14436
14437 ast_mutex_lock(&iflock);
14438 for (tmp = iflist; tmp; tmp = tmp->next) {
14439 if (tmp->pri && tmp->channel == channel) {
14440 ast_mutex_unlock(&iflock);
14441 ast_mutex_lock(&tmp->pri->lock);
14442 if (!tmp->pri->enable_service_message_support) {
14443 ast_mutex_unlock(&tmp->pri->lock);
14444 ast_cli(fd,
14445 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14446 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14447 return CLI_SUCCESS;
14448 }
14449 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14450 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14451 switch(changestatus) {
14452 case 0:
14453
14454 ast_db_del(db_chan_name, SRVST_DBKEY);
14455 *why &= ~SRVST_NEAREND;
14456 if (*why) {
14457 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14458 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14459 } else {
14460 dahdi_pri_update_span_devstate(tmp->pri);
14461 }
14462 break;
14463
14464 case 2:
14465
14466 ast_db_del(db_chan_name, SRVST_DBKEY);
14467 *why |= SRVST_NEAREND;
14468 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14469 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14470 dahdi_pri_update_span_devstate(tmp->pri);
14471 break;
14472
14473
14474 default:
14475 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14476 break;
14477 }
14478 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14479 ast_mutex_unlock(&tmp->pri->lock);
14480 return CLI_SUCCESS;
14481 }
14482 }
14483 ast_mutex_unlock(&iflock);
14484
14485 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14486 return CLI_FAILURE;
14487 }
14488
14489 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14490 {
14491 switch (cmd) {
14492 case CLI_INIT:
14493 e->command = "pri service enable channel";
14494 e->usage =
14495 "Usage: pri service enable channel <channel> [<interface id>]\n"
14496 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14497 " to restore a channel to service, with optional interface id\n"
14498 " as agreed upon with remote switch operator\n";
14499 return NULL;
14500 case CLI_GENERATE:
14501 return NULL;
14502 }
14503 return handle_pri_service_generic(e, cmd, a, 0);
14504 }
14505
14506 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14507 {
14508 switch (cmd) {
14509 case CLI_INIT:
14510 e->command = "pri service disable channel";
14511 e->usage =
14512 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14513 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14514 " to remove a channel from service, with optional interface id\n"
14515 " as agreed upon with remote switch operator\n";
14516 return NULL;
14517 case CLI_GENERATE:
14518 return NULL;
14519 }
14520 return handle_pri_service_generic(e, cmd, a, 2);
14521 }
14522 #endif
14523 #endif
14524
14525 #if defined(HAVE_PRI)
14526 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14527 {
14528 int span;
14529
14530 switch (cmd) {
14531 case CLI_INIT:
14532 e->command = "pri show channels";
14533 e->usage =
14534 "Usage: pri show channels\n"
14535 " Displays PRI channel information such as the current mapping\n"
14536 " of DAHDI B channels to Asterisk channel names and which calls\n"
14537 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14538 " are not associated with any B channel.\n";
14539 return NULL;
14540 case CLI_GENERATE:
14541 return NULL;
14542 }
14543
14544 if (a->argc != 3)
14545 return CLI_SHOWUSAGE;
14546
14547 sig_pri_cli_show_channels_header(a->fd);
14548 for (span = 0; span < NUM_SPANS; ++span) {
14549 if (pris[span].pri.pri) {
14550 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14551 }
14552 }
14553 return CLI_SUCCESS;
14554 }
14555 #endif
14556
14557 #if defined(HAVE_PRI)
14558 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14559 {
14560 int span;
14561
14562 switch (cmd) {
14563 case CLI_INIT:
14564 e->command = "pri show spans";
14565 e->usage =
14566 "Usage: pri show spans\n"
14567 " Displays PRI span information\n";
14568 return NULL;
14569 case CLI_GENERATE:
14570 return NULL;
14571 }
14572
14573 if (a->argc != 3)
14574 return CLI_SHOWUSAGE;
14575
14576 for (span = 0; span < NUM_SPANS; span++) {
14577 if (pris[span].pri.pri) {
14578 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14579 }
14580 }
14581 return CLI_SUCCESS;
14582 }
14583 #endif
14584
14585 #if defined(HAVE_PRI)
14586 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588 int span;
14589
14590 switch (cmd) {
14591 case CLI_INIT:
14592 e->command = "pri show span";
14593 e->usage =
14594 "Usage: pri show span <span>\n"
14595 " Displays PRI Information on a given PRI span\n";
14596 return NULL;
14597 case CLI_GENERATE:
14598 return complete_span_4(a->line, a->word, a->pos, a->n);
14599 }
14600
14601 if (a->argc < 4)
14602 return CLI_SHOWUSAGE;
14603 span = atoi(a->argv[3]);
14604 if ((span < 1) || (span > NUM_SPANS)) {
14605 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14606 return CLI_SUCCESS;
14607 }
14608 if (!pris[span-1].pri.pri) {
14609 ast_cli(a->fd, "No PRI running on span %d\n", span);
14610 return CLI_SUCCESS;
14611 }
14612
14613 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14614
14615 return CLI_SUCCESS;
14616 }
14617 #endif
14618
14619 #if defined(HAVE_PRI)
14620 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14621 {
14622 int x;
14623 int span;
14624 int count=0;
14625 int debug;
14626
14627 switch (cmd) {
14628 case CLI_INIT:
14629 e->command = "pri show debug";
14630 e->usage =
14631 "Usage: pri show debug\n"
14632 " Show the debug state of pri spans\n";
14633 return NULL;
14634 case CLI_GENERATE:
14635 return NULL;
14636 }
14637
14638 for (span = 0; span < NUM_SPANS; span++) {
14639 if (pris[span].pri.pri) {
14640 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14641 if (pris[span].pri.dchans[x]) {
14642 debug = pri_get_debug(pris[span].pri.dchans[x]);
14643 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" );
14644 count++;
14645 }
14646 }
14647 }
14648
14649 }
14650 ast_mutex_lock(&pridebugfdlock);
14651 if (pridebugfd >= 0)
14652 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14653 ast_mutex_unlock(&pridebugfdlock);
14654
14655 if (!count)
14656 ast_cli(a->fd, "No PRI running\n");
14657 return CLI_SUCCESS;
14658 }
14659 #endif
14660
14661 #if defined(HAVE_PRI)
14662 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14663 {
14664 switch (cmd) {
14665 case CLI_INIT:
14666 e->command = "pri show version";
14667 e->usage =
14668 "Usage: pri show version\n"
14669 "Show libpri version information\n";
14670 return NULL;
14671 case CLI_GENERATE:
14672 return NULL;
14673 }
14674
14675 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14676
14677 return CLI_SUCCESS;
14678 }
14679 #endif
14680
14681 #if defined(HAVE_PRI)
14682 static struct ast_cli_entry dahdi_pri_cli[] = {
14683 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14684 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14685 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14686 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14687 #endif
14688 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14689 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14690 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14691 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14692 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14693 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14694 };
14695 #endif
14696
14697 #ifdef HAVE_OPENR2
14698
14699 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14700 {
14701 switch (cmd) {
14702 case CLI_INIT:
14703 e->command = "mfcr2 show version";
14704 e->usage =
14705 "Usage: mfcr2 show version\n"
14706 " Shows the version of the OpenR2 library being used.\n";
14707 return NULL;
14708 case CLI_GENERATE:
14709 return NULL;
14710 }
14711 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14712 return CLI_SUCCESS;
14713 }
14714
14715 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14716 {
14717 #define FORMAT "%4s %40s\n"
14718 int i = 0;
14719 int numvariants = 0;
14720 const openr2_variant_entry_t *variants;
14721 switch (cmd) {
14722 case CLI_INIT:
14723 e->command = "mfcr2 show variants";
14724 e->usage =
14725 "Usage: mfcr2 show variants\n"
14726 " Shows the list of MFC/R2 variants supported.\n";
14727 return NULL;
14728 case CLI_GENERATE:
14729 return NULL;
14730 }
14731 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14732 ast_cli(a->fd, "Failed to get list of variants.\n");
14733 return CLI_FAILURE;
14734 }
14735 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14736 for (i = 0; i < numvariants; i++) {
14737 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14738 }
14739 return CLI_SUCCESS;
14740 #undef FORMAT
14741 }
14742
14743 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14744 {
14745 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14746 int filtertype = 0;
14747 int targetnum = 0;
14748 char channo[5];
14749 char anino[5];
14750 char dnisno[5];
14751 struct dahdi_pvt *p;
14752 openr2_context_t *r2context;
14753 openr2_variant_t r2variant;
14754 switch (cmd) {
14755 case CLI_INIT:
14756 e->command = "mfcr2 show channels [group|context]";
14757 e->usage =
14758 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14759 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14760 return NULL;
14761 case CLI_GENERATE:
14762 return NULL;
14763 }
14764 if (!((a->argc == 3) || (a->argc == 5))) {
14765 return CLI_SHOWUSAGE;
14766 }
14767 if (a->argc == 5) {
14768 if (!strcasecmp(a->argv[3], "group")) {
14769 targetnum = atoi(a->argv[4]);
14770 if ((targetnum < 0) || (targetnum > 63))
14771 return CLI_SHOWUSAGE;
14772 targetnum = 1 << targetnum;
14773 filtertype = 1;
14774 } else if (!strcasecmp(a->argv[3], "context")) {
14775 filtertype = 2;
14776 } else {
14777 return CLI_SHOWUSAGE;
14778 }
14779 }
14780 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14781 ast_mutex_lock(&iflock);
14782 for (p = iflist; p; p = p->next) {
14783 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14784 continue;
14785 }
14786 if (filtertype) {
14787 switch(filtertype) {
14788 case 1:
14789 if (p->group != targetnum) {
14790 continue;
14791 }
14792 break;
14793 case 2:
14794 if (strcasecmp(p->context, a->argv[4])) {
14795 continue;
14796 }
14797 break;
14798 default:
14799 ;
14800 }
14801 }
14802 r2context = openr2_chan_get_context(p->r2chan);
14803 r2variant = openr2_context_get_variant(r2context);
14804 snprintf(channo, sizeof(channo), "%d", p->channel);
14805 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14806 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14807 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14808 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14809 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14810 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14811 }
14812 ast_mutex_unlock(&iflock);
14813 return CLI_SUCCESS;
14814 #undef FORMAT
14815 }
14816
14817 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14818 {
14819 struct dahdi_pvt *p = NULL;
14820 int channo = 0;
14821 char *toklevel = NULL;
14822 char *saveptr = NULL;
14823 char *logval = NULL;
14824 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14825 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14826 switch (cmd) {
14827 case CLI_INIT:
14828 e->command = "mfcr2 set debug";
14829 e->usage =
14830 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14831 " Set a new logging level for the specified channel.\n"
14832 " If no channel is specified the logging level will be applied to all channels.\n";
14833 return NULL;
14834 case CLI_GENERATE:
14835 return NULL;
14836 }
14837 if (a->argc < 4) {
14838 return CLI_SHOWUSAGE;
14839 }
14840 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14841 logval = ast_strdupa(a->argv[3]);
14842 toklevel = strtok_r(logval, ",", &saveptr);
14843 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14844 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14845 return CLI_FAILURE;
14846 } else if (OR2_LOG_NOTHING == tmplevel) {
14847 loglevel = tmplevel;
14848 } else {
14849 loglevel |= tmplevel;
14850 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14851 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14852 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14853 continue;
14854 }
14855 loglevel |= tmplevel;
14856 }
14857 }
14858 ast_mutex_lock(&iflock);
14859 for (p = iflist; p; p = p->next) {
14860 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14861 continue;
14862 }
14863 if ((channo != -1) && (p->channel != channo )) {
14864 continue;
14865 }
14866 openr2_chan_set_log_level(p->r2chan, loglevel);
14867 if (channo != -1) {
14868 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14869 break;
14870 }
14871 }
14872 if ((channo != -1) && !p) {
14873 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14874 }
14875 if (channo == -1) {
14876 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14877 }
14878 ast_mutex_unlock(&iflock);
14879 return CLI_SUCCESS;
14880 }
14881
14882 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14883 {
14884 struct dahdi_pvt *p = NULL;
14885 int channo = 0;
14886 switch (cmd) {
14887 case CLI_INIT:
14888 e->command = "mfcr2 call files [on|off]";
14889 e->usage =
14890 "Usage: mfcr2 call files [on|off] <channel>\n"
14891 " Enable call files creation on the specified channel.\n"
14892 " If no channel is specified call files creation policy will be applied to all channels.\n";
14893 return NULL;
14894 case CLI_GENERATE:
14895 return NULL;
14896 }
14897 if (a->argc < 4) {
14898 return CLI_SHOWUSAGE;
14899 }
14900 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14901 ast_mutex_lock(&iflock);
14902 for (p = iflist; p; p = p->next) {
14903 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14904 continue;
14905 }
14906 if ((channo != -1) && (p->channel != channo )) {
14907 continue;
14908 }
14909 if (ast_true(a->argv[3])) {
14910 openr2_chan_enable_call_files(p->r2chan);
14911 } else {
14912 openr2_chan_disable_call_files(p->r2chan);
14913 }
14914 if (channo != -1) {
14915 if (ast_true(a->argv[3])) {
14916 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14917 } else {
14918 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14919 }
14920 break;
14921 }
14922 }
14923 if ((channo != -1) && !p) {
14924 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14925 }
14926 if (channo == -1) {
14927 if (ast_true(a->argv[3])) {
14928 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14929 } else {
14930 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14931 }
14932 }
14933 ast_mutex_unlock(&iflock);
14934 return CLI_SUCCESS;
14935 }
14936
14937 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14938 {
14939 struct dahdi_pvt *p = NULL;
14940 int channo = 0;
14941 switch (cmd) {
14942 case CLI_INIT:
14943 e->command = "mfcr2 set idle";
14944 e->usage =
14945 "Usage: mfcr2 set idle <channel>\n"
14946 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14947 " Force the given channel into IDLE state.\n"
14948 " If no channel is specified, all channels will be set to IDLE.\n";
14949 return NULL;
14950 case CLI_GENERATE:
14951 return NULL;
14952 }
14953 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14954 ast_mutex_lock(&iflock);
14955 for (p = iflist; p; p = p->next) {
14956 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14957 continue;
14958 }
14959 if ((channo != -1) && (p->channel != channo )) {
14960 continue;
14961 }
14962 openr2_chan_set_idle(p->r2chan);
14963 ast_mutex_lock(&p->lock);
14964 p->locallyblocked = 0;
14965 p->mfcr2call = 0;
14966 ast_mutex_unlock(&p->lock);
14967 if (channo != -1) {
14968 break;
14969 }
14970 }
14971 if ((channo != -1) && !p) {
14972 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14973 }
14974 ast_mutex_unlock(&iflock);
14975 return CLI_SUCCESS;
14976 }
14977
14978 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14979 {
14980 struct dahdi_pvt *p = NULL;
14981 int channo = 0;
14982 switch (cmd) {
14983 case CLI_INIT:
14984 e->command = "mfcr2 set blocked";
14985 e->usage =
14986 "Usage: mfcr2 set blocked <channel>\n"
14987 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14988 " Force the given channel into BLOCKED state.\n"
14989 " If no channel is specified, all channels will be set to BLOCKED.\n";
14990 return NULL;
14991 case CLI_GENERATE:
14992 return NULL;
14993 }
14994 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14995 ast_mutex_lock(&iflock);
14996 for (p = iflist; p; p = p->next) {
14997 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14998 continue;
14999 }
15000 if ((channo != -1) && (p->channel != channo )) {
15001 continue;
15002 }
15003 openr2_chan_set_blocked(p->r2chan);
15004 ast_mutex_lock(&p->lock);
15005 p->locallyblocked = 1;
15006 ast_mutex_unlock(&p->lock);
15007 if (channo != -1) {
15008 break;
15009 }
15010 }
15011 if ((channo != -1) && !p) {
15012 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15013 }
15014 ast_mutex_unlock(&iflock);
15015 return CLI_SUCCESS;
15016 }
15017
15018 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15019 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15020 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15021 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15022 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15023 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15024 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15025 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15026 };
15027
15028 #endif
15029
15030 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15031 {
15032 int channel;
15033 int ret;
15034 switch (cmd) {
15035 case CLI_INIT:
15036 e->command = "dahdi destroy channel";
15037 e->usage =
15038 "Usage: dahdi destroy channel <chan num>\n"
15039 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15040 return NULL;
15041 case CLI_GENERATE:
15042 return NULL;
15043 }
15044 if (a->argc != 4)
15045 return CLI_SHOWUSAGE;
15046
15047 channel = atoi(a->argv[3]);
15048 ret = dahdi_destroy_channel_bynum(channel);
15049 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15050 }
15051
15052 static void dahdi_softhangup_all(void)
15053 {
15054 struct dahdi_pvt *p;
15055 retry:
15056 ast_mutex_lock(&iflock);
15057 for (p = iflist; p; p = p->next) {
15058 ast_mutex_lock(&p->lock);
15059 if (p->owner && !p->restartpending) {
15060 if (ast_channel_trylock(p->owner)) {
15061 if (option_debug > 2)
15062 ast_verbose("Avoiding deadlock\n");
15063
15064 ast_mutex_unlock(&p->lock);
15065 ast_mutex_unlock(&iflock);
15066 goto retry;
15067 }
15068 if (option_debug > 2)
15069 ast_verbose("Softhanging up on %s\n", p->owner->name);
15070 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15071 p->restartpending = 1;
15072 num_restart_pending++;
15073 ast_channel_unlock(p->owner);
15074 }
15075 ast_mutex_unlock(&p->lock);
15076 }
15077 ast_mutex_unlock(&iflock);
15078 }
15079
15080 static int setup_dahdi(int reload);
15081 static int dahdi_restart(void)
15082 {
15083 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15084 int i, j;
15085 #endif
15086 int cancel_code;
15087 struct dahdi_pvt *p;
15088
15089 ast_mutex_lock(&restart_lock);
15090 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15091 dahdi_softhangup_all();
15092 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15093 #ifdef HAVE_OPENR2
15094 dahdi_r2_destroy_links();
15095 #endif
15096
15097 #if defined(HAVE_PRI)
15098 for (i = 0; i < NUM_SPANS; i++) {
15099 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15100 cancel_code = pthread_cancel(pris[i].pri.master);
15101 pthread_kill(pris[i].pri.master, SIGURG);
15102 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);
15103 pthread_join(pris[i].pri.master, NULL);
15104 ast_debug(4, "Joined thread of span %d\n", i);
15105 }
15106 }
15107 #endif
15108
15109 #if defined(HAVE_SS7)
15110 for (i = 0; i < NUM_SPANS; i++) {
15111 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15112 cancel_code = pthread_cancel(linksets[i].ss7.master);
15113 pthread_kill(linksets[i].ss7.master, SIGURG);
15114 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);
15115 pthread_join(linksets[i].ss7.master, NULL);
15116 ast_debug(4, "Joined thread of span %d\n", i);
15117 }
15118 }
15119 #endif
15120
15121 ast_mutex_lock(&monlock);
15122 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15123 cancel_code = pthread_cancel(monitor_thread);
15124 pthread_kill(monitor_thread, SIGURG);
15125 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15126 pthread_join(monitor_thread, NULL);
15127 ast_debug(4, "Joined monitor thread\n");
15128 }
15129 monitor_thread = AST_PTHREADT_NULL;
15130
15131 ast_mutex_lock(&ss_thread_lock);
15132 while (ss_thread_count > 0) {
15133 int x = DAHDI_FLASH;
15134 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15135
15136 ast_mutex_lock(&iflock);
15137 for (p = iflist; p; p = p->next) {
15138 if (p->owner) {
15139
15140 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15141 }
15142 }
15143 ast_mutex_unlock(&iflock);
15144 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15145 }
15146
15147
15148 dahdi_softhangup_all();
15149 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15150 destroy_all_channels();
15151 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15152
15153 ast_mutex_unlock(&monlock);
15154
15155 #ifdef HAVE_PRI
15156 for (i = 0; i < NUM_SPANS; i++) {
15157 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15158 dahdi_close_pri_fd(&(pris[i]), j);
15159 }
15160
15161 memset(pris, 0, sizeof(pris));
15162 for (i = 0; i < NUM_SPANS; i++) {
15163 sig_pri_init_pri(&pris[i].pri);
15164 }
15165 pri_set_error(dahdi_pri_error);
15166 pri_set_message(dahdi_pri_message);
15167 #endif
15168 #if defined(HAVE_SS7)
15169 for (i = 0; i < NUM_SPANS; i++) {
15170 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15171 dahdi_close_ss7_fd(&(linksets[i]), j);
15172 }
15173
15174 memset(linksets, 0, sizeof(linksets));
15175 for (i = 0; i < NUM_SPANS; i++) {
15176 sig_ss7_init_linkset(&linksets[i].ss7);
15177 }
15178 ss7_set_error(dahdi_ss7_error);
15179 ss7_set_message(dahdi_ss7_message);
15180 #endif
15181
15182 if (setup_dahdi(2) != 0) {
15183 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15184 ast_mutex_unlock(&ss_thread_lock);
15185 return 1;
15186 }
15187 ast_mutex_unlock(&ss_thread_lock);
15188 ast_mutex_unlock(&restart_lock);
15189 return 0;
15190 }
15191
15192 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15193 {
15194 switch (cmd) {
15195 case CLI_INIT:
15196 e->command = "dahdi restart";
15197 e->usage =
15198 "Usage: dahdi restart\n"
15199 " Restarts the DAHDI channels: destroys them all and then\n"
15200 " re-reads them from chan_dahdi.conf.\n"
15201 " Note that this will STOP any running CALL on DAHDI channels.\n"
15202 "";
15203 return NULL;
15204 case CLI_GENERATE:
15205 return NULL;
15206 }
15207 if (a->argc != 2)
15208 return CLI_SHOWUSAGE;
15209
15210 if (dahdi_restart() != 0)
15211 return CLI_FAILURE;
15212 return CLI_SUCCESS;
15213 }
15214
15215 static int action_dahdirestart(struct mansession *s, const struct message *m)
15216 {
15217 if (dahdi_restart() != 0) {
15218 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15219 return 1;
15220 }
15221 astman_send_ack(s, m, "DAHDIRestart: Success");
15222 return 0;
15223 }
15224
15225 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15226 {
15227 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15228 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15229 unsigned int targetnum = 0;
15230 int filtertype = 0;
15231 struct dahdi_pvt *tmp = NULL;
15232 char tmps[20] = "";
15233 char statestr[20] = "";
15234 char blockstr[20] = "";
15235
15236 switch (cmd) {
15237 case CLI_INIT:
15238 e->command = "dahdi show channels [group|context]";
15239 e->usage =
15240 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15241 " Shows a list of available channels with optional filtering\n"
15242 " <group> must be a number between 0 and 63\n";
15243 return NULL;
15244 case CLI_GENERATE:
15245 return NULL;
15246 }
15247
15248
15249
15250 if (!((a->argc == 3) || (a->argc == 5)))
15251 return CLI_SHOWUSAGE;
15252
15253 if (a->argc == 5) {
15254 if (!strcasecmp(a->argv[3], "group")) {
15255 targetnum = atoi(a->argv[4]);
15256 if ((targetnum < 0) || (targetnum > 63))
15257 return CLI_SHOWUSAGE;
15258 targetnum = 1 << targetnum;
15259 filtertype = 1;
15260 } else if (!strcasecmp(a->argv[3], "context")) {
15261 filtertype = 2;
15262 }
15263 }
15264
15265 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15266 ast_mutex_lock(&iflock);
15267 for (tmp = iflist; tmp; tmp = tmp->next) {
15268 if (filtertype) {
15269 switch(filtertype) {
15270 case 1:
15271 if (!(tmp->group & targetnum)) {
15272 continue;
15273 }
15274 break;
15275 case 2:
15276 if (strcasecmp(tmp->context, a->argv[4])) {
15277 continue;
15278 }
15279 break;
15280 default:
15281 break;
15282 }
15283 }
15284 if (tmp->channel > 0) {
15285 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15286 } else
15287 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15288
15289 if (tmp->locallyblocked)
15290 blockstr[0] = 'L';
15291 else
15292 blockstr[0] = ' ';
15293
15294 if (tmp->remotelyblocked)
15295 blockstr[1] = 'R';
15296 else
15297 blockstr[1] = ' ';
15298
15299 blockstr[2] = '\0';
15300
15301 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15302
15303 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15304 }
15305 ast_mutex_unlock(&iflock);
15306 return CLI_SUCCESS;
15307 #undef FORMAT
15308 #undef FORMAT2
15309 }
15310
15311 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15312 {
15313 int channel;
15314 struct dahdi_pvt *tmp = NULL;
15315 struct dahdi_confinfo ci;
15316 struct dahdi_params ps;
15317 int x;
15318
15319 switch (cmd) {
15320 case CLI_INIT:
15321 e->command = "dahdi show channel";
15322 e->usage =
15323 "Usage: dahdi show channel <chan num>\n"
15324 " Detailed information about a given channel\n";
15325 return NULL;
15326 case CLI_GENERATE:
15327 return NULL;
15328 }
15329
15330 if (a->argc != 4)
15331 return CLI_SHOWUSAGE;
15332
15333 channel = atoi(a->argv[3]);
15334
15335 ast_mutex_lock(&iflock);
15336 for (tmp = iflist; tmp; tmp = tmp->next) {
15337 if (tmp->channel == channel) {
15338 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15339 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15340 ast_cli(a->fd, "Span: %d\n", tmp->span);
15341 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15342 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15343 ast_cli(a->fd, "Context: %s\n", tmp->context);
15344 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15345 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15346 #if defined(HAVE_PRI)
15347 #if defined(HAVE_PRI_SUBADDR)
15348 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15349 #endif
15350 #endif
15351 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15352 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15353 if (tmp->vars) {
15354 struct ast_variable *v;
15355 ast_cli(a->fd, "Variables:\n");
15356 for (v = tmp->vars ; v ; v = v->next)
15357 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15358 }
15359 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15360 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15361 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15362 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15363 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15364 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)" : "");
15365 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)" : "");
15366 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)" : "");
15367 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15368 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15369 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15370 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15371 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15372 if (tmp->busydetect) {
15373 #if defined(BUSYDETECT_TONEONLY)
15374 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15375 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15376 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15377 #endif
15378 #ifdef BUSYDETECT_DEBUG
15379 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15380 #endif
15381 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15382 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15383 }
15384 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15385 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15386 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15387 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15388 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15389 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15390 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15391 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15392 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15393 ast_cli(a->fd, "Echo Cancellation:\n");
15394
15395 if (tmp->echocancel.head.tap_length) {
15396 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15397 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15398 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15399 }
15400 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15401 } else {
15402 ast_cli(a->fd, "\tnone\n");
15403 }
15404 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15405 if (tmp->master)
15406 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15407 for (x = 0; x < MAX_SLAVES; x++) {
15408 if (tmp->slaves[x])
15409 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15410 }
15411 #ifdef HAVE_OPENR2
15412 if (tmp->mfcr2) {
15413 char calldir[OR2_MAX_PATH];
15414 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15415 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15416 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15417 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15418 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15419 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15420 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15421 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15422 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15423 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15424 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15425 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15426 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15427 #endif
15428 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15429 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15430 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15431 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15432 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15433 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15434 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15435 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15436 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15437 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15438 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15439 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15440 }
15441 #endif
15442 #if defined(HAVE_SS7)
15443 if (tmp->ss7) {
15444 struct sig_ss7_chan *chan = tmp->sig_pvt;
15445
15446 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15447 }
15448 #endif
15449 #ifdef HAVE_PRI
15450 if (tmp->pri) {
15451 struct sig_pri_chan *chan = tmp->sig_pvt;
15452
15453 ast_cli(a->fd, "PRI Flags: ");
15454 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15455 ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15456 }
15457 if (chan->call)
15458 ast_cli(a->fd, "Call ");
15459 if (chan->allocated) {
15460 ast_cli(a->fd, "Allocated ");
15461 }
15462 ast_cli(a->fd, "\n");
15463 if (tmp->logicalspan)
15464 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15465 else
15466 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15467 }
15468 #endif
15469 memset(&ci, 0, sizeof(ci));
15470 ps.channo = tmp->channel;
15471 if (tmp->subs[SUB_REAL].dfd > -1) {
15472 memset(&ci, 0, sizeof(ci));
15473 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15474 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15475 }
15476 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15477 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15478 }
15479 memset(&ps, 0, sizeof(ps));
15480 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15481 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15482 } else {
15483 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15484 }
15485 }
15486 if (ISTRUNK(tmp)) {
15487 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
15488 if (!ast_strlen_zero(progzone))
15489 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15490 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
15491 if(tmp->busydetect) {
15492 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15493 if(tmp->busytonelength > 0) {
15494 ast_cli(a->fd, "Busy Pattern:\n");
15495 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15496 if (tmp->busyquietlength > 0)
15497 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15498 else
15499 ast_cli(a->fd, " -- Detect Tone Only\n");
15500 if(tmp->busyfuzziness > 0)
15501 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15502 }
15503 }
15504 }
15505 ast_mutex_unlock(&iflock);
15506 return CLI_SUCCESS;
15507 }
15508 }
15509 ast_mutex_unlock(&iflock);
15510
15511 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15512 return CLI_FAILURE;
15513 }
15514
15515 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15516 {
15517 int i, j;
15518 switch (cmd) {
15519 case CLI_INIT:
15520 e->command = "dahdi show cadences";
15521 e->usage =
15522 "Usage: dahdi show cadences\n"
15523 " Shows all cadences currently defined\n";
15524 return NULL;
15525 case CLI_GENERATE:
15526 return NULL;
15527 }
15528 for (i = 0; i < num_cadence; i++) {
15529 char output[1024];
15530 char tmp[16], tmp2[64];
15531 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15532 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15533
15534 for (j = 0; j < 16; j++) {
15535 if (cadences[i].ringcadence[j] == 0)
15536 break;
15537 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15538 if (cidrings[i] * 2 - 1 == j)
15539 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15540 else
15541 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15542 if (j != 0)
15543 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15544 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15545 }
15546 ast_cli(a->fd,"%s\n",output);
15547 }
15548 return CLI_SUCCESS;
15549 }
15550
15551
15552 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15553 {
15554 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15555 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15556 int span;
15557 int res;
15558 char alarmstr[50];
15559
15560 int ctl;
15561 struct dahdi_spaninfo s;
15562
15563 switch (cmd) {
15564 case CLI_INIT:
15565 e->command = "dahdi show status";
15566 e->usage =
15567 "Usage: dahdi show status\n"
15568 " Shows a list of DAHDI cards with status\n";
15569 return NULL;
15570 case CLI_GENERATE:
15571 return NULL;
15572 }
15573 ctl = open("/dev/dahdi/ctl", O_RDWR);
15574 if (ctl < 0) {
15575 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15576 return CLI_FAILURE;
15577 }
15578 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15579
15580 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15581 s.spanno = span;
15582 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15583 if (res) {
15584 continue;
15585 }
15586 alarmstr[0] = '\0';
15587 if (s.alarms > 0) {
15588 if (s.alarms & DAHDI_ALARM_BLUE)
15589 strcat(alarmstr, "BLU/");
15590 if (s.alarms & DAHDI_ALARM_YELLOW)
15591 strcat(alarmstr, "YEL/");
15592 if (s.alarms & DAHDI_ALARM_RED)
15593 strcat(alarmstr, "RED/");
15594 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15595 strcat(alarmstr, "LB/");
15596 if (s.alarms & DAHDI_ALARM_RECOVER)
15597 strcat(alarmstr, "REC/");
15598 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15599 strcat(alarmstr, "NOP/");
15600 if (!strlen(alarmstr))
15601 strcat(alarmstr, "UUU/");
15602 if (strlen(alarmstr)) {
15603
15604 alarmstr[strlen(alarmstr) - 1] = '\0';
15605 }
15606 } else {
15607 if (s.numchans)
15608 strcpy(alarmstr, "OK");
15609 else
15610 strcpy(alarmstr, "UNCONFIGURED");
15611 }
15612
15613 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15614 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15615 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15616 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15617 "CAS",
15618 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15619 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15620 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15621 "Unk",
15622 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15623 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15624 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15625 lbostr[s.lbo]
15626 );
15627 }
15628 close(ctl);
15629
15630 return CLI_SUCCESS;
15631 #undef FORMAT
15632 #undef FORMAT2
15633 }
15634
15635 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15636 {
15637 int pseudo_fd = -1;
15638 struct dahdi_versioninfo vi;
15639
15640 switch (cmd) {
15641 case CLI_INIT:
15642 e->command = "dahdi show version";
15643 e->usage =
15644 "Usage: dahdi show version\n"
15645 " Shows the DAHDI version in use\n";
15646 return NULL;
15647 case CLI_GENERATE:
15648 return NULL;
15649 }
15650 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15651 ast_cli(a->fd, "Failed to open control file to get version.\n");
15652 return CLI_SUCCESS;
15653 }
15654
15655 strcpy(vi.version, "Unknown");
15656 strcpy(vi.echo_canceller, "Unknown");
15657
15658 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15659 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15660 else
15661 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15662
15663 close(pseudo_fd);
15664
15665 return CLI_SUCCESS;
15666 }
15667
15668 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15669 {
15670 int channel;
15671 int gain;
15672 int tx;
15673 struct dahdi_hwgain hwgain;
15674 struct dahdi_pvt *tmp = NULL;
15675
15676 switch (cmd) {
15677 case CLI_INIT:
15678 e->command = "dahdi set hwgain";
15679 e->usage =
15680 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15681 " Sets the hardware gain on a a given channel, overriding the\n"
15682 " value provided at module loadtime, whether the channel is in\n"
15683 " use or not. Changes take effect immediately.\n"
15684 " <rx|tx> which direction do you want to change (relative to our module)\n"
15685 " <chan num> is the channel number relative to the device\n"
15686 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15687 return NULL;
15688 case CLI_GENERATE:
15689 return NULL;
15690 }
15691
15692 if (a->argc != 6)
15693 return CLI_SHOWUSAGE;
15694
15695 if (!strcasecmp("rx", a->argv[3]))
15696 tx = 0;
15697 else if (!strcasecmp("tx", a->argv[3]))
15698 tx = 1;
15699 else
15700 return CLI_SHOWUSAGE;
15701
15702 channel = atoi(a->argv[4]);
15703 gain = atof(a->argv[5])*10.0;
15704
15705 ast_mutex_lock(&iflock);
15706
15707 for (tmp = iflist; tmp; tmp = tmp->next) {
15708
15709 if (tmp->channel != channel)
15710 continue;
15711
15712 if (tmp->subs[SUB_REAL].dfd == -1)
15713 break;
15714
15715 hwgain.newgain = gain;
15716 hwgain.tx = tx;
15717 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15718 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15719 ast_mutex_unlock(&iflock);
15720 return CLI_FAILURE;
15721 }
15722 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15723 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15724 break;
15725 }
15726
15727 ast_mutex_unlock(&iflock);
15728
15729 if (tmp)
15730 return CLI_SUCCESS;
15731
15732 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15733 return CLI_FAILURE;
15734
15735 }
15736
15737 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15738 {
15739 int channel;
15740 float gain;
15741 int tx;
15742 int res;
15743 struct dahdi_pvt *tmp = NULL;
15744
15745 switch (cmd) {
15746 case CLI_INIT:
15747 e->command = "dahdi set swgain";
15748 e->usage =
15749 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15750 " Sets the software gain on a a given channel, overriding the\n"
15751 " value provided at module loadtime, whether the channel is in\n"
15752 " use or not. Changes take effect immediately.\n"
15753 " <rx|tx> which direction do you want to change (relative to our module)\n"
15754 " <chan num> is the channel number relative to the device\n"
15755 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15756 return NULL;
15757 case CLI_GENERATE:
15758 return NULL;
15759 }
15760
15761 if (a->argc != 6)
15762 return CLI_SHOWUSAGE;
15763
15764 if (!strcasecmp("rx", a->argv[3]))
15765 tx = 0;
15766 else if (!strcasecmp("tx", a->argv[3]))
15767 tx = 1;
15768 else
15769 return CLI_SHOWUSAGE;
15770
15771 channel = atoi(a->argv[4]);
15772 gain = atof(a->argv[5]);
15773
15774 ast_mutex_lock(&iflock);
15775 for (tmp = iflist; tmp; tmp = tmp->next) {
15776
15777 if (tmp->channel != channel)
15778 continue;
15779
15780 if (tmp->subs[SUB_REAL].dfd == -1)
15781 break;
15782
15783 if (tx)
15784 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15785 else
15786 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15787
15788 if (res) {
15789 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15790 ast_mutex_unlock(&iflock);
15791 return CLI_FAILURE;
15792 }
15793
15794 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15795 tx ? "tx" : "rx", gain, channel);
15796 break;
15797 }
15798 ast_mutex_unlock(&iflock);
15799
15800 if (tmp)
15801 return CLI_SUCCESS;
15802
15803 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15804 return CLI_FAILURE;
15805
15806 }
15807
15808 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15809 {
15810 int channel;
15811 int on;
15812 struct dahdi_pvt *dahdi_chan = NULL;
15813
15814 switch (cmd) {
15815 case CLI_INIT:
15816 e->command = "dahdi set dnd";
15817 e->usage =
15818 "Usage: dahdi set dnd <chan#> <on|off>\n"
15819 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15820 " Changes take effect immediately.\n"
15821 " <chan num> is the channel number\n"
15822 " <on|off> Enable or disable DND mode?\n"
15823 ;
15824 return NULL;
15825 case CLI_GENERATE:
15826 return NULL;
15827 }
15828
15829 if (a->argc != 5)
15830 return CLI_SHOWUSAGE;
15831
15832 if ((channel = atoi(a->argv[3])) <= 0) {
15833 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15834 return CLI_SHOWUSAGE;
15835 }
15836
15837 if (ast_true(a->argv[4]))
15838 on = 1;
15839 else if (ast_false(a->argv[4]))
15840 on = 0;
15841 else {
15842 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15843 return CLI_SHOWUSAGE;
15844 }
15845
15846 ast_mutex_lock(&iflock);
15847 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15848 if (dahdi_chan->channel != channel)
15849 continue;
15850
15851
15852 dahdi_dnd(dahdi_chan, on);
15853 break;
15854 }
15855 ast_mutex_unlock(&iflock);
15856
15857 if (!dahdi_chan) {
15858 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15859 return CLI_FAILURE;
15860 }
15861
15862 return CLI_SUCCESS;
15863 }
15864
15865 static struct ast_cli_entry dahdi_cli[] = {
15866 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15867 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15868 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15869 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15870 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15871 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15872 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15873 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15874 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15875 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15876 };
15877
15878 #define TRANSFER 0
15879 #define HANGUP 1
15880
15881 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15882 {
15883 if (p) {
15884 switch (mode) {
15885 case TRANSFER:
15886 p->fake_event = DAHDI_EVENT_WINKFLASH;
15887 break;
15888 case HANGUP:
15889 p->fake_event = DAHDI_EVENT_ONHOOK;
15890 break;
15891 default:
15892 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15893 }
15894 }
15895 return 0;
15896 }
15897 static struct dahdi_pvt *find_channel(int channel)
15898 {
15899 struct dahdi_pvt *p;
15900
15901 ast_mutex_lock(&iflock);
15902 for (p = iflist; p; p = p->next) {
15903 if (p->channel == channel) {
15904 break;
15905 }
15906 }
15907 ast_mutex_unlock(&iflock);
15908 return p;
15909 }
15910
15911
15912
15913
15914
15915
15916
15917
15918
15919
15920 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15921 {
15922 int chan_num;
15923
15924 if (sscanf(channel, "%30d", &chan_num) != 1) {
15925
15926 return NULL;
15927 }
15928
15929 return find_channel(chan_num);
15930 }
15931
15932 static int action_dahdidndon(struct mansession *s, const struct message *m)
15933 {
15934 struct dahdi_pvt *p;
15935 const char *channel = astman_get_header(m, "DAHDIChannel");
15936
15937 if (ast_strlen_zero(channel)) {
15938 astman_send_error(s, m, "No channel specified");
15939 return 0;
15940 }
15941 p = find_channel_from_str(channel);
15942 if (!p) {
15943 astman_send_error(s, m, "No such channel");
15944 return 0;
15945 }
15946 dahdi_dnd(p, 1);
15947 astman_send_ack(s, m, "DND Enabled");
15948 return 0;
15949 }
15950
15951 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15952 {
15953 struct dahdi_pvt *p;
15954 const char *channel = astman_get_header(m, "DAHDIChannel");
15955
15956 if (ast_strlen_zero(channel)) {
15957 astman_send_error(s, m, "No channel specified");
15958 return 0;
15959 }
15960 p = find_channel_from_str(channel);
15961 if (!p) {
15962 astman_send_error(s, m, "No such channel");
15963 return 0;
15964 }
15965 dahdi_dnd(p, 0);
15966 astman_send_ack(s, m, "DND Disabled");
15967 return 0;
15968 }
15969
15970 static int action_transfer(struct mansession *s, const struct message *m)
15971 {
15972 struct dahdi_pvt *p;
15973 const char *channel = astman_get_header(m, "DAHDIChannel");
15974
15975 if (ast_strlen_zero(channel)) {
15976 astman_send_error(s, m, "No channel specified");
15977 return 0;
15978 }
15979 p = find_channel_from_str(channel);
15980 if (!p) {
15981 astman_send_error(s, m, "No such channel");
15982 return 0;
15983 }
15984 if (!analog_lib_handles(p->sig, 0, 0)) {
15985 astman_send_error(s, m, "Channel signaling is not analog");
15986 return 0;
15987 }
15988 dahdi_fake_event(p,TRANSFER);
15989 astman_send_ack(s, m, "DAHDITransfer");
15990 return 0;
15991 }
15992
15993 static int action_transferhangup(struct mansession *s, const struct message *m)
15994 {
15995 struct dahdi_pvt *p;
15996 const char *channel = astman_get_header(m, "DAHDIChannel");
15997
15998 if (ast_strlen_zero(channel)) {
15999 astman_send_error(s, m, "No channel specified");
16000 return 0;
16001 }
16002 p = find_channel_from_str(channel);
16003 if (!p) {
16004 astman_send_error(s, m, "No such channel");
16005 return 0;
16006 }
16007 if (!analog_lib_handles(p->sig, 0, 0)) {
16008 astman_send_error(s, m, "Channel signaling is not analog");
16009 return 0;
16010 }
16011 dahdi_fake_event(p,HANGUP);
16012 astman_send_ack(s, m, "DAHDIHangup");
16013 return 0;
16014 }
16015
16016 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16017 {
16018 struct dahdi_pvt *p;
16019 const char *channel = astman_get_header(m, "DAHDIChannel");
16020 const char *number = astman_get_header(m, "Number");
16021 int i;
16022
16023 if (ast_strlen_zero(channel)) {
16024 astman_send_error(s, m, "No channel specified");
16025 return 0;
16026 }
16027 if (ast_strlen_zero(number)) {
16028 astman_send_error(s, m, "No number specified");
16029 return 0;
16030 }
16031 p = find_channel_from_str(channel);
16032 if (!p) {
16033 astman_send_error(s, m, "No such channel");
16034 return 0;
16035 }
16036 if (!p->owner) {
16037 astman_send_error(s, m, "Channel does not have it's owner");
16038 return 0;
16039 }
16040 for (i = 0; i < strlen(number); i++) {
16041 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16042 dahdi_queue_frame(p, &f);
16043 }
16044 astman_send_ack(s, m, "DAHDIDialOffhook");
16045 return 0;
16046 }
16047
16048 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16049 {
16050 struct dahdi_pvt *tmp = NULL;
16051 const char *id = astman_get_header(m, "ActionID");
16052 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16053 char idText[256] = "";
16054 int channels = 0;
16055 int dahdichanquery;
16056
16057 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16058
16059 dahdichanquery = -1;
16060 }
16061
16062 astman_send_ack(s, m, "DAHDI channel status will follow");
16063 if (!ast_strlen_zero(id))
16064 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16065
16066 ast_mutex_lock(&iflock);
16067
16068 for (tmp = iflist; tmp; tmp = tmp->next) {
16069 if (tmp->channel > 0) {
16070 int alm;
16071
16072
16073 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16074 continue;
16075
16076 alm = get_alarms(tmp);
16077 channels++;
16078 if (tmp->owner) {
16079
16080 astman_append(s,
16081 "Event: DAHDIShowChannels\r\n"
16082 "DAHDIChannel: %d\r\n"
16083 "Channel: %s\r\n"
16084 "Uniqueid: %s\r\n"
16085 "AccountCode: %s\r\n"
16086 "Signalling: %s\r\n"
16087 "SignallingCode: %d\r\n"
16088 "Context: %s\r\n"
16089 "DND: %s\r\n"
16090 "Alarm: %s\r\n"
16091 "%s"
16092 "\r\n",
16093 tmp->channel,
16094 tmp->owner->name,
16095 tmp->owner->uniqueid,
16096 tmp->owner->accountcode,
16097 sig2str(tmp->sig),
16098 tmp->sig,
16099 tmp->context,
16100 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16101 alarm2str(alm), idText);
16102 } else {
16103 astman_append(s,
16104 "Event: DAHDIShowChannels\r\n"
16105 "DAHDIChannel: %d\r\n"
16106 "Signalling: %s\r\n"
16107 "SignallingCode: %d\r\n"
16108 "Context: %s\r\n"
16109 "DND: %s\r\n"
16110 "Alarm: %s\r\n"
16111 "%s"
16112 "\r\n",
16113 tmp->channel, sig2str(tmp->sig), tmp->sig,
16114 tmp->context,
16115 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16116 alarm2str(alm), idText);
16117 }
16118 }
16119 }
16120
16121 ast_mutex_unlock(&iflock);
16122
16123 astman_append(s,
16124 "Event: DAHDIShowChannelsComplete\r\n"
16125 "%s"
16126 "Items: %d\r\n"
16127 "\r\n",
16128 idText,
16129 channels);
16130 return 0;
16131 }
16132
16133 #if defined(HAVE_SS7)
16134 static int linkset_addsigchan(int sigchan)
16135 {
16136 struct dahdi_ss7 *link;
16137 int res;
16138 int curfd;
16139 struct dahdi_params params;
16140 struct dahdi_bufferinfo bi;
16141 struct dahdi_spaninfo si;
16142
16143 if (sigchan < 0) {
16144 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16145 return -1;
16146 }
16147 if (cur_ss7type < 0) {
16148 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16149 return -1;
16150 }
16151 if (cur_pointcode < 0) {
16152 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16153 return -1;
16154 }
16155 if (cur_adjpointcode < 0) {
16156 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16157 return -1;
16158 }
16159 if (cur_defaultdpc < 0) {
16160 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16161 return -1;
16162 }
16163 if (cur_networkindicator < 0) {
16164 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16165 return -1;
16166 }
16167 link = ss7_resolve_linkset(cur_linkset);
16168 if (!link) {
16169 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16170 return -1;
16171 }
16172 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16173 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16174 return -1;
16175 }
16176
16177 curfd = link->ss7.numsigchans;
16178
16179
16180 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16181 if (link->ss7.fds[curfd] < 0) {
16182 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16183 strerror(errno));
16184 return -1;
16185 }
16186 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16187 dahdi_close_ss7_fd(link, curfd);
16188 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16189 strerror(errno));
16190 return -1;
16191 }
16192
16193
16194 memset(¶ms, 0, sizeof(params));
16195 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16196 if (res) {
16197 dahdi_close_ss7_fd(link, curfd);
16198 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16199 strerror(errno));
16200 return -1;
16201 }
16202 if (params.sigtype != DAHDI_SIG_HDLCFCS
16203 && params.sigtype != DAHDI_SIG_HARDHDLC
16204 && params.sigtype != DAHDI_SIG_MTP2) {
16205 dahdi_close_ss7_fd(link, curfd);
16206 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16207 return -1;
16208 }
16209
16210
16211 memset(&bi, 0, sizeof(bi));
16212 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16213 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16214 bi.numbufs = 32;
16215 bi.bufsize = 512;
16216 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16217 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16218 sigchan, strerror(errno));
16219 dahdi_close_ss7_fd(link, curfd);
16220 return -1;
16221 }
16222
16223
16224 memset(&si, 0, sizeof(si));
16225 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16226 if (res) {
16227 dahdi_close_ss7_fd(link, curfd);
16228 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16229 strerror(errno));
16230 }
16231
16232 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16233 (params.sigtype == DAHDI_SIG_MTP2)
16234 ? SS7_TRANSPORT_DAHDIMTP2
16235 : SS7_TRANSPORT_DAHDIDCHAN,
16236 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16237 if (res) {
16238 dahdi_close_ss7_fd(link, curfd);
16239 return -1;
16240 }
16241
16242 ++link->ss7.numsigchans;
16243
16244 return 0;
16245 }
16246 #endif
16247
16248 #if defined(HAVE_SS7)
16249 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16250 {
16251 int span;
16252 switch (cmd) {
16253 case CLI_INIT:
16254 e->command = "ss7 set debug {on|off} linkset";
16255 e->usage =
16256 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16257 " Enables debugging on a given SS7 linkset\n";
16258 return NULL;
16259 case CLI_GENERATE:
16260 return NULL;
16261 }
16262 if (a->argc < 6)
16263 return CLI_SHOWUSAGE;
16264 span = atoi(a->argv[5]);
16265 if ((span < 1) || (span > NUM_SPANS)) {
16266 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16267 return CLI_SUCCESS;
16268 }
16269 if (!linksets[span-1].ss7.ss7) {
16270 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16271 } else {
16272 if (!strcasecmp(a->argv[3], "on")) {
16273 linksets[span - 1].ss7.debug = 1;
16274 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16275 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16276 } else {
16277 linksets[span - 1].ss7.debug = 0;
16278 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16279 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16280 }
16281 }
16282
16283 return CLI_SUCCESS;
16284 }
16285 #endif
16286
16287 #if defined(HAVE_SS7)
16288 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16289 {
16290 int linkset, cic;
16291 int blocked = -1, i;
16292 switch (cmd) {
16293 case CLI_INIT:
16294 e->command = "ss7 block cic";
16295 e->usage =
16296 "Usage: ss7 block cic <linkset> <CIC>\n"
16297 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16298 return NULL;
16299 case CLI_GENERATE:
16300 return NULL;
16301 }
16302 if (a->argc == 5)
16303 linkset = atoi(a->argv[3]);
16304 else
16305 return CLI_SHOWUSAGE;
16306
16307 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16308 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16309 return CLI_SUCCESS;
16310 }
16311
16312 if (!linksets[linkset-1].ss7.ss7) {
16313 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16314 return CLI_SUCCESS;
16315 }
16316
16317 cic = atoi(a->argv[4]);
16318
16319 if (cic < 1) {
16320 ast_cli(a->fd, "Invalid CIC specified!\n");
16321 return CLI_SUCCESS;
16322 }
16323
16324 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16325 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16326 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16327 if (!blocked) {
16328 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16329 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16330 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16331 }
16332 }
16333 }
16334
16335 if (blocked < 0) {
16336 ast_cli(a->fd, "Invalid CIC specified!\n");
16337 return CLI_SUCCESS;
16338 }
16339
16340 if (!blocked)
16341 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16342 else
16343 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16344
16345
16346 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16347
16348 return CLI_SUCCESS;
16349 }
16350 #endif
16351
16352 #if defined(HAVE_SS7)
16353 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16354 {
16355 int linkset;
16356 int i;
16357 switch (cmd) {
16358 case CLI_INIT:
16359 e->command = "ss7 block linkset";
16360 e->usage =
16361 "Usage: ss7 block linkset <linkset number>\n"
16362 " Sends a remote blocking request for all CICs on the given linkset\n";
16363 return NULL;
16364 case CLI_GENERATE:
16365 return NULL;
16366 }
16367 if (a->argc == 4)
16368 linkset = atoi(a->argv[3]);
16369 else
16370 return CLI_SHOWUSAGE;
16371
16372 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16373 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16374 return CLI_SUCCESS;
16375 }
16376
16377 if (!linksets[linkset-1].ss7.ss7) {
16378 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16379 return CLI_SUCCESS;
16380 }
16381
16382 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16383 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16384 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16385 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16386 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16387 }
16388
16389
16390 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16391
16392 return CLI_SUCCESS;
16393 }
16394 #endif
16395
16396 #if defined(HAVE_SS7)
16397 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16398 {
16399 int linkset, cic;
16400 int i, blocked = -1;
16401 switch (cmd) {
16402 case CLI_INIT:
16403 e->command = "ss7 unblock cic";
16404 e->usage =
16405 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16406 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16407 return NULL;
16408 case CLI_GENERATE:
16409 return NULL;
16410 }
16411
16412 if (a->argc == 5)
16413 linkset = atoi(a->argv[3]);
16414 else
16415 return CLI_SHOWUSAGE;
16416
16417 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16418 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16419 return CLI_SUCCESS;
16420 }
16421
16422 if (!linksets[linkset-1].ss7.ss7) {
16423 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16424 return CLI_SUCCESS;
16425 }
16426
16427 cic = atoi(a->argv[4]);
16428
16429 if (cic < 1) {
16430 ast_cli(a->fd, "Invalid CIC specified!\n");
16431 return CLI_SUCCESS;
16432 }
16433
16434 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16435 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16436 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16437 if (blocked) {
16438 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16439 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16440 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16441 }
16442 }
16443 }
16444
16445 if (blocked > 0)
16446 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16447
16448
16449 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16450
16451 return CLI_SUCCESS;
16452 }
16453 #endif
16454
16455 #if defined(HAVE_SS7)
16456 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16457 {
16458 int linkset;
16459 int i;
16460 switch (cmd) {
16461 case CLI_INIT:
16462 e->command = "ss7 unblock linkset";
16463 e->usage =
16464 "Usage: ss7 unblock linkset <linkset number>\n"
16465 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16466 return NULL;
16467 case CLI_GENERATE:
16468 return NULL;
16469 }
16470
16471 if (a->argc == 4)
16472 linkset = atoi(a->argv[3]);
16473 else
16474 return CLI_SHOWUSAGE;
16475
16476 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16477 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16478 return CLI_SUCCESS;
16479 }
16480
16481 if (!linksets[linkset-1].ss7.ss7) {
16482 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16483 return CLI_SUCCESS;
16484 }
16485
16486 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16487 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16488 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16489 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16490 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16491 }
16492
16493
16494 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16495
16496 return CLI_SUCCESS;
16497 }
16498 #endif
16499
16500 #if defined(HAVE_SS7)
16501 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16502 {
16503 int linkset;
16504 struct sig_ss7_linkset *ss7;
16505 switch (cmd) {
16506 case CLI_INIT:
16507 e->command = "ss7 show linkset";
16508 e->usage =
16509 "Usage: ss7 show linkset <span>\n"
16510 " Shows the status of an SS7 linkset.\n";
16511 return NULL;
16512 case CLI_GENERATE:
16513 return NULL;
16514 }
16515
16516 if (a->argc < 4)
16517 return CLI_SHOWUSAGE;
16518 linkset = atoi(a->argv[3]);
16519 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16520 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16521 return CLI_SUCCESS;
16522 }
16523 ss7 = &linksets[linkset - 1].ss7;
16524 if (!ss7->ss7) {
16525 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16526 return CLI_SUCCESS;
16527 }
16528
16529 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16530
16531 return CLI_SUCCESS;
16532 }
16533 #endif
16534
16535 #if defined(HAVE_SS7)
16536 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16537 {
16538 int linkset;
16539
16540 switch (cmd) {
16541 case CLI_INIT:
16542 e->command = "ss7 show channels";
16543 e->usage =
16544 "Usage: ss7 show channels\n"
16545 " Displays SS7 channel information at a glance.\n";
16546 return NULL;
16547 case CLI_GENERATE:
16548 return NULL;
16549 }
16550
16551 if (a->argc != 3)
16552 return CLI_SHOWUSAGE;
16553
16554 sig_ss7_cli_show_channels_header(a->fd);
16555 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16556 if (linksets[linkset].ss7.ss7) {
16557 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16558 }
16559 }
16560 return CLI_SUCCESS;
16561 }
16562 #endif
16563
16564 #if defined(HAVE_SS7)
16565 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16566 {
16567 switch (cmd) {
16568 case CLI_INIT:
16569 e->command = "ss7 show version";
16570 e->usage =
16571 "Usage: ss7 show version\n"
16572 " Show the libss7 version\n";
16573 return NULL;
16574 case CLI_GENERATE:
16575 return NULL;
16576 }
16577
16578 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16579
16580 return CLI_SUCCESS;
16581 }
16582 #endif
16583
16584 #if defined(HAVE_SS7)
16585 static struct ast_cli_entry dahdi_ss7_cli[] = {
16586 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16587 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16588 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16589 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16590 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16591 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16592 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16593 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16594 };
16595 #endif
16596
16597 #if defined(HAVE_PRI)
16598 #if defined(HAVE_PRI_CCSS)
16599
16600
16601
16602
16603
16604
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614
16615
16616 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16617 {
16618 struct dahdi_pvt *pvt;
16619 struct sig_pri_chan *pvt_chan;
16620 int res;
16621
16622 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16623
16624 pvt = chan->tech_pvt;
16625 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16626 pvt_chan = pvt->sig_pvt;
16627 } else {
16628 pvt_chan = NULL;
16629 }
16630 if (!pvt_chan) {
16631 return -1;
16632 }
16633
16634 ast_module_ref(ast_module_info->self);
16635
16636 res = sig_pri_cc_agent_init(agent, pvt_chan);
16637 if (res) {
16638 ast_module_unref(ast_module_info->self);
16639 }
16640 return res;
16641 }
16642 #endif
16643 #endif
16644
16645 #if defined(HAVE_PRI)
16646 #if defined(HAVE_PRI_CCSS)
16647
16648
16649
16650
16651
16652
16653
16654
16655
16656
16657
16658
16659
16660 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16661 {
16662 sig_pri_cc_agent_destructor(agent);
16663
16664 ast_module_unref(ast_module_info->self);
16665 }
16666 #endif
16667 #endif
16668
16669 #if defined(HAVE_PRI)
16670 #if defined(HAVE_PRI_CCSS)
16671 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16672 .type = dahdi_pri_cc_type,
16673 .init = dahdi_pri_cc_agent_init,
16674 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16675 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16676 .respond = sig_pri_cc_agent_req_rsp,
16677 .status_request = sig_pri_cc_agent_status_req,
16678 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16679 .party_b_free = sig_pri_cc_agent_party_b_free,
16680 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16681 .callee_available = sig_pri_cc_agent_callee_available,
16682 .destructor = dahdi_pri_cc_agent_destructor,
16683 };
16684 #endif
16685 #endif
16686
16687 #if defined(HAVE_PRI)
16688 #if defined(HAVE_PRI_CCSS)
16689 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16690 .type = dahdi_pri_cc_type,
16691 .request_cc = sig_pri_cc_monitor_req_cc,
16692 .suspend = sig_pri_cc_monitor_suspend,
16693 .unsuspend = sig_pri_cc_monitor_unsuspend,
16694 .status_response = sig_pri_cc_monitor_status_rsp,
16695 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16696 .destructor = sig_pri_cc_monitor_destructor,
16697 };
16698 #endif
16699 #endif
16700
16701 static int __unload_module(void)
16702 {
16703 struct dahdi_pvt *p;
16704 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16705 int i, j;
16706 #endif
16707
16708 #ifdef HAVE_PRI
16709 for (i = 0; i < NUM_SPANS; i++) {
16710 if (pris[i].pri.master != AST_PTHREADT_NULL)
16711 pthread_cancel(pris[i].pri.master);
16712 }
16713 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16714 ast_unregister_application(dahdi_send_keypad_facility_app);
16715 #ifdef HAVE_PRI_PROG_W_CAUSE
16716 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16717 #endif
16718 #endif
16719 #if defined(HAVE_SS7)
16720 for (i = 0; i < NUM_SPANS; i++) {
16721 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16722 pthread_cancel(linksets[i].ss7.master);
16723 }
16724 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16725 #endif
16726 #if defined(HAVE_OPENR2)
16727 dahdi_r2_destroy_links();
16728 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16729 ast_unregister_application(dahdi_accept_r2_call_app);
16730 #endif
16731
16732 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16733 ast_manager_unregister("DAHDIDialOffhook");
16734 ast_manager_unregister("DAHDIHangup");
16735 ast_manager_unregister("DAHDITransfer");
16736 ast_manager_unregister("DAHDIDNDoff");
16737 ast_manager_unregister("DAHDIDNDon");
16738 ast_manager_unregister("DAHDIShowChannels");
16739 ast_manager_unregister("DAHDIRestart");
16740 ast_data_unregister(NULL);
16741 ast_channel_unregister(&dahdi_tech);
16742
16743
16744 ast_mutex_lock(&iflock);
16745 for (p = iflist; p; p = p->next) {
16746 if (p->owner)
16747 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16748 }
16749 ast_mutex_unlock(&iflock);
16750
16751 ast_mutex_lock(&monlock);
16752 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16753 pthread_cancel(monitor_thread);
16754 pthread_kill(monitor_thread, SIGURG);
16755 pthread_join(monitor_thread, NULL);
16756 }
16757 monitor_thread = AST_PTHREADT_STOP;
16758 ast_mutex_unlock(&monlock);
16759
16760 destroy_all_channels();
16761
16762 #if defined(HAVE_PRI)
16763 for (i = 0; i < NUM_SPANS; i++) {
16764 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16765 pthread_join(pris[i].pri.master, NULL);
16766 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16767 dahdi_close_pri_fd(&(pris[i]), j);
16768 }
16769 sig_pri_stop_pri(&pris[i].pri);
16770 }
16771 #if defined(HAVE_PRI_CCSS)
16772 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16773 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16774 #endif
16775 sig_pri_unload();
16776 #endif
16777
16778 #if defined(HAVE_SS7)
16779 for (i = 0; i < NUM_SPANS; i++) {
16780 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16781 pthread_join(linksets[i].ss7.master, NULL);
16782 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16783 dahdi_close_ss7_fd(&(linksets[i]), j);
16784 }
16785 }
16786 #endif
16787 ast_cond_destroy(&ss_thread_complete);
16788 return 0;
16789 }
16790
16791 static int unload_module(void)
16792 {
16793 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16794 int y;
16795 #endif
16796 #ifdef HAVE_PRI
16797 for (y = 0; y < NUM_SPANS; y++)
16798 ast_mutex_destroy(&pris[y].pri.lock);
16799 #endif
16800 #if defined(HAVE_SS7)
16801 for (y = 0; y < NUM_SPANS; y++)
16802 ast_mutex_destroy(&linksets[y].ss7.lock);
16803 #endif
16804 return __unload_module();
16805 }
16806
16807 static void string_replace(char *str, int char1, int char2)
16808 {
16809 for (; *str; str++) {
16810 if (*str == char1) {
16811 *str = char2;
16812 }
16813 }
16814 }
16815
16816 static char *parse_spanchan(char *chanstr, char **subdir)
16817 {
16818 char *p;
16819
16820 if ((p = strrchr(chanstr, '!')) == NULL) {
16821 *subdir = NULL;
16822 return chanstr;
16823 }
16824 *p++ = '\0';
16825 string_replace(chanstr, '!', '/');
16826 *subdir = chanstr;
16827 return p;
16828 }
16829
16830 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16831 {
16832 char *c, *chan;
16833 char *subdir;
16834 int x, start, finish;
16835 struct dahdi_pvt *tmp;
16836
16837 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16838 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16839 return -1;
16840 }
16841
16842 c = ast_strdupa(value);
16843 c = parse_spanchan(c, &subdir);
16844
16845 while ((chan = strsep(&c, ","))) {
16846 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16847
16848 } else if (sscanf(chan, "%30d", &start)) {
16849
16850 finish = start;
16851 } else if (!strcasecmp(chan, "pseudo")) {
16852 finish = start = CHAN_PSEUDO;
16853 if (found_pseudo)
16854 *found_pseudo = 1;
16855 } else {
16856 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16857 return -1;
16858 }
16859 if (finish < start) {
16860 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16861 x = finish;
16862 finish = start;
16863 start = x;
16864 }
16865
16866 for (x = start; x <= finish; x++) {
16867 char fn[PATH_MAX];
16868 int real_channel = x;
16869
16870 if (!ast_strlen_zero(subdir)) {
16871 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16872 if (real_channel < 0) {
16873 if (conf->ignore_failed_channels) {
16874 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16875 subdir, x, real_channel);
16876 continue;
16877 } else {
16878 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16879 subdir, x, real_channel);
16880 return -1;
16881 }
16882 }
16883 }
16884 tmp = mkintf(real_channel, conf, reload);
16885
16886 if (tmp) {
16887 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16888 } else {
16889 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16890 (reload == 1) ? "reconfigure" : "register", value);
16891 return -1;
16892 }
16893 }
16894 }
16895
16896 return 0;
16897 }
16898
16899
16900
16901 #define MAX_CHANLIST_LEN 80
16902
16903 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16904 {
16905 char *parse = ast_strdupa(data);
16906 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16907 unsigned int param_count;
16908 unsigned int x;
16909
16910 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16911 return;
16912
16913 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16914
16915
16916
16917 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16918
16919 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16920 confp->chan.echocancel.head.tap_length = x;
16921 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16922 confp->chan.echocancel.head.tap_length = 128;
16923
16924
16925
16926 for (x = 1; x < param_count; x++) {
16927 struct {
16928 char *name;
16929 char *value;
16930 } param;
16931
16932 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16933 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16934 continue;
16935 }
16936
16937 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16938 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16939 continue;
16940 }
16941
16942 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16943
16944 if (param.value) {
16945 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16946 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16947 continue;
16948 }
16949 }
16950 confp->chan.echocancel.head.param_count++;
16951 }
16952 }
16953
16954
16955 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16956
16957 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16958
16959 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16960 {
16961 struct dahdi_pvt *tmp;
16962 int y;
16963 int found_pseudo = 0;
16964 struct ast_variable *dahdichan = NULL;
16965
16966 for (; v; v = v->next) {
16967 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16968 continue;
16969
16970
16971 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16972 if (options & PROC_DAHDI_OPT_NOCHAN) {
16973 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16974 continue;
16975 }
16976 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16977 if (confp->ignore_failed_channels) {
16978 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16979 continue;
16980 } else {
16981 return -1;
16982 }
16983 }
16984 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16985 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16986 confp->ignore_failed_channels = ast_true(v->value);
16987 } else if (!strcasecmp(v->name, "buffers")) {
16988 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16989 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16990 confp->chan.buf_no = numbufs;
16991 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16992 }
16993 } else if (!strcasecmp(v->name, "faxbuffers")) {
16994 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16995 confp->chan.usefaxbuffers = 1;
16996 }
16997 } else if (!strcasecmp(v->name, "dahdichan")) {
16998
16999 dahdichan = v;
17000 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17001 usedistinctiveringdetection = ast_true(v->value);
17002 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17003 distinctiveringaftercid = ast_true(v->value);
17004 } else if (!strcasecmp(v->name, "dring1context")) {
17005 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17006 } else if (!strcasecmp(v->name, "dring2context")) {
17007 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17008 } else if (!strcasecmp(v->name, "dring3context")) {
17009 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17010 } else if (!strcasecmp(v->name, "dring1range")) {
17011 confp->chan.drings.ringnum[0].range = atoi(v->value);
17012 } else if (!strcasecmp(v->name, "dring2range")) {
17013 confp->chan.drings.ringnum[1].range = atoi(v->value);
17014 } else if (!strcasecmp(v->name, "dring3range")) {
17015 confp->chan.drings.ringnum[2].range = atoi(v->value);
17016 } else if (!strcasecmp(v->name, "dring1")) {
17017 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]);
17018 } else if (!strcasecmp(v->name, "dring2")) {
17019 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]);
17020 } else if (!strcasecmp(v->name, "dring3")) {
17021 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]);
17022 } else if (!strcasecmp(v->name, "usecallerid")) {
17023 confp->chan.use_callerid = ast_true(v->value);
17024 } else if (!strcasecmp(v->name, "cidsignalling")) {
17025 if (!strcasecmp(v->value, "bell"))
17026 confp->chan.cid_signalling = CID_SIG_BELL;
17027 else if (!strcasecmp(v->value, "v23"))
17028 confp->chan.cid_signalling = CID_SIG_V23;
17029 else if (!strcasecmp(v->value, "dtmf"))
17030 confp->chan.cid_signalling = CID_SIG_DTMF;
17031 else if (!strcasecmp(v->value, "smdi"))
17032 confp->chan.cid_signalling = CID_SIG_SMDI;
17033 else if (!strcasecmp(v->value, "v23_jp"))
17034 confp->chan.cid_signalling = CID_SIG_V23_JP;
17035 else if (ast_true(v->value))
17036 confp->chan.cid_signalling = CID_SIG_BELL;
17037 } else if (!strcasecmp(v->name, "cidstart")) {
17038 if (!strcasecmp(v->value, "ring"))
17039 confp->chan.cid_start = CID_START_RING;
17040 else if (!strcasecmp(v->value, "polarity_in"))
17041 confp->chan.cid_start = CID_START_POLARITY_IN;
17042 else if (!strcasecmp(v->value, "polarity"))
17043 confp->chan.cid_start = CID_START_POLARITY;
17044 else if (!strcasecmp(v->value, "dtmf"))
17045 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17046 else if (ast_true(v->value))
17047 confp->chan.cid_start = CID_START_RING;
17048 } else if (!strcasecmp(v->name, "threewaycalling")) {
17049 confp->chan.threewaycalling = ast_true(v->value);
17050 } else if (!strcasecmp(v->name, "cancallforward")) {
17051 confp->chan.cancallforward = ast_true(v->value);
17052 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17053 if (ast_true(v->value))
17054 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17055 else
17056 confp->chan.dtmfrelax = 0;
17057 } else if (!strcasecmp(v->name, "mailbox")) {
17058 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17059 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17060 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17061 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17062 }
17063 } else if (!strcasecmp(v->name, "adsi")) {
17064 confp->chan.adsi = ast_true(v->value);
17065 } else if (!strcasecmp(v->name, "usesmdi")) {
17066 confp->chan.use_smdi = ast_true(v->value);
17067 } else if (!strcasecmp(v->name, "smdiport")) {
17068 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17069 } else if (!strcasecmp(v->name, "transfer")) {
17070 confp->chan.transfer = ast_true(v->value);
17071 } else if (!strcasecmp(v->name, "canpark")) {
17072 confp->chan.canpark = ast_true(v->value);
17073 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17074 confp->chan.echocanbridged = ast_true(v->value);
17075 } else if (!strcasecmp(v->name, "busydetect")) {
17076 confp->chan.busydetect = ast_true(v->value);
17077 } else if (!strcasecmp(v->name, "busycount")) {
17078 confp->chan.busycount = atoi(v->value);
17079 } else if (!strcasecmp(v->name, "silencethreshold")) {
17080 confp->chan.silencethreshold = atoi(v->value);
17081 } else if (!strcasecmp(v->name, "busycompare")) {
17082 confp->chan.busycompare = ast_true(v->value);
17083 } else if (!strcasecmp(v->name, "busypattern")) {
17084 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17085 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17086 }
17087 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17088 if (count == 1)
17089 confp->chan.busyquietlength = 0;
17090 else if (count < 1)
17091 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17092 } else if (!strcasecmp(v->name, "busyfuzziness")) {
17093 confp->chan.busyfuzziness = atoi(v->value);
17094 } else if (!strcasecmp(v->name, "callprogress")) {
17095 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17096 if (ast_true(v->value))
17097 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17098 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17099 confp->chan.waitfordialtone = atoi(v->value);
17100 } else if (!strcasecmp(v->name, "faxdetect")) {
17101 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17102 if (!strcasecmp(v->value, "incoming")) {
17103 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17104 } else if (!strcasecmp(v->value, "outgoing")) {
17105 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17106 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17107 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17108 } else if (!strcasecmp(v->name, "echocancel")) {
17109 process_echocancel(confp, v->value, v->lineno);
17110 } else if (!strcasecmp(v->name, "echotraining")) {
17111 if (sscanf(v->value, "%30d", &y) == 1) {
17112 if ((y < 10) || (y > 4000)) {
17113 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17114 } else {
17115 confp->chan.echotraining = y;
17116 }
17117 } else if (ast_true(v->value)) {
17118 confp->chan.echotraining = 400;
17119 } else
17120 confp->chan.echotraining = 0;
17121 } else if (!strcasecmp(v->name, "hidecallerid")) {
17122 confp->chan.hidecallerid = ast_true(v->value);
17123 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17124 confp->chan.hidecalleridname = ast_true(v->value);
17125 } else if (!strcasecmp(v->name, "pulsedial")) {
17126 confp->chan.pulse = ast_true(v->value);
17127 } else if (!strcasecmp(v->name, "callreturn")) {
17128 confp->chan.callreturn = ast_true(v->value);
17129 } else if (!strcasecmp(v->name, "callwaiting")) {
17130 confp->chan.callwaiting = ast_true(v->value);
17131 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17132 confp->chan.callwaitingcallerid = ast_true(v->value);
17133 } else if (!strcasecmp(v->name, "context")) {
17134 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17135 } else if (!strcasecmp(v->name, "language")) {
17136 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17137 } else if (!strcasecmp(v->name, "progzone")) {
17138 ast_copy_string(progzone, v->value, sizeof(progzone));
17139 } else if (!strcasecmp(v->name, "mohinterpret")
17140 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17141 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17142 } else if (!strcasecmp(v->name, "mohsuggest")) {
17143 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17144 } else if (!strcasecmp(v->name, "parkinglot")) {
17145 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17146 } else if (!strcasecmp(v->name, "stripmsd")) {
17147 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17148 confp->chan.stripmsd = atoi(v->value);
17149 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17150 numbufs = atoi(v->value);
17151 } else if (!strcasecmp(v->name, "group")) {
17152 confp->chan.group = ast_get_group(v->value);
17153 } else if (!strcasecmp(v->name, "callgroup")) {
17154 if (!strcasecmp(v->value, "none"))
17155 confp->chan.callgroup = 0;
17156 else
17157 confp->chan.callgroup = ast_get_group(v->value);
17158 } else if (!strcasecmp(v->name, "pickupgroup")) {
17159 if (!strcasecmp(v->value, "none"))
17160 confp->chan.pickupgroup = 0;
17161 else
17162 confp->chan.pickupgroup = ast_get_group(v->value);
17163 } else if (!strcasecmp(v->name, "setvar")) {
17164 char *varname = ast_strdupa(v->value), *varval = NULL;
17165 struct ast_variable *tmpvar;
17166 if (varname && (varval = strchr(varname, '='))) {
17167 *varval++ = '\0';
17168 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17169 tmpvar->next = confp->chan.vars;
17170 confp->chan.vars = tmpvar;
17171 }
17172 }
17173 } else if (!strcasecmp(v->name, "immediate")) {
17174 confp->chan.immediate = ast_true(v->value);
17175 } else if (!strcasecmp(v->name, "transfertobusy")) {
17176 confp->chan.transfertobusy = ast_true(v->value);
17177 } else if (!strcasecmp(v->name, "mwimonitor")) {
17178 confp->chan.mwimonitor_neon = 0;
17179 confp->chan.mwimonitor_fsk = 0;
17180 confp->chan.mwimonitor_rpas = 0;
17181 if (strcasestr(v->value, "fsk")) {
17182 confp->chan.mwimonitor_fsk = 1;
17183 }
17184 if (strcasestr(v->value, "rpas")) {
17185 confp->chan.mwimonitor_rpas = 1;
17186 }
17187 if (strcasestr(v->value, "neon")) {
17188 confp->chan.mwimonitor_neon = 1;
17189 }
17190
17191 if (ast_true(v->value)) {
17192 confp->chan.mwimonitor_fsk = 1;
17193 }
17194 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17195 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17196 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17197 }
17198 } else if (!strcasecmp(v->name, "rxgain")) {
17199 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17200 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17201 }
17202 } else if (!strcasecmp(v->name, "txgain")) {
17203 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17204 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17205 }
17206 } else if (!strcasecmp(v->name, "txdrc")) {
17207 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17208 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17209 }
17210 } else if (!strcasecmp(v->name, "rxdrc")) {
17211 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17212 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17213 }
17214 } else if (!strcasecmp(v->name, "tonezone")) {
17215 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17216 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17217 }
17218 } else if (!strcasecmp(v->name, "callerid")) {
17219 if (!strcasecmp(v->value, "asreceived")) {
17220 confp->chan.cid_num[0] = '\0';
17221 confp->chan.cid_name[0] = '\0';
17222 } else {
17223 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17224 }
17225 } else if (!strcasecmp(v->name, "fullname")) {
17226 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17227 } else if (!strcasecmp(v->name, "cid_number")) {
17228 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17229 } else if (!strcasecmp(v->name, "cid_tag")) {
17230 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17231 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17232 confp->chan.dahditrcallerid = ast_true(v->value);
17233 } else if (!strcasecmp(v->name, "restrictcid")) {
17234 confp->chan.restrictcid = ast_true(v->value);
17235 } else if (!strcasecmp(v->name, "usecallingpres")) {
17236 confp->chan.use_callingpres = ast_true(v->value);
17237 } else if (!strcasecmp(v->name, "accountcode")) {
17238 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17239 } else if (!strcasecmp(v->name, "amaflags")) {
17240 y = ast_cdr_amaflags2int(v->value);
17241 if (y < 0)
17242 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17243 else
17244 confp->chan.amaflags = y;
17245 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17246 confp->chan.polarityonanswerdelay = atoi(v->value);
17247 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17248 confp->chan.answeronpolarityswitch = ast_true(v->value);
17249 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17250 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17251 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17252 confp->chan.sendcalleridafter = atoi(v->value);
17253 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17254 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17255 } else if (ast_cc_is_config_param(v->name)) {
17256 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17257 } else if (!strcasecmp(v->name, "mwisendtype")) {
17258 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17259 if (!strcasecmp(v->value, "rpas")) {
17260 mwisend_rpas = 1;
17261 } else {
17262 mwisend_rpas = 0;
17263 }
17264 #else
17265
17266 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17267 if (strcasestr(v->value, "nofsk")) {
17268 confp->chan.mwisend_fsk = 0;
17269 } else {
17270 confp->chan.mwisend_fsk = 1;
17271 }
17272 if (strcasestr(v->value, "rpas")) {
17273 confp->chan.mwisend_rpas = 1;
17274 } else {
17275 confp->chan.mwisend_rpas = 0;
17276 }
17277 if (strcasestr(v->value, "lrev")) {
17278 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17279 }
17280 if (strcasestr(v->value, "hvdc")) {
17281 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17282 }
17283 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17284 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17285 }
17286 #endif
17287 } else if (reload != 1) {
17288 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17289 int orig_radio = confp->chan.radio;
17290 int orig_outsigmod = confp->chan.outsigmod;
17291 int orig_auto = confp->is_sig_auto;
17292
17293 confp->chan.radio = 0;
17294 confp->chan.outsigmod = -1;
17295 confp->is_sig_auto = 0;
17296 if (!strcasecmp(v->value, "em")) {
17297 confp->chan.sig = SIG_EM;
17298 } else if (!strcasecmp(v->value, "em_e1")) {
17299 confp->chan.sig = SIG_EM_E1;
17300 } else if (!strcasecmp(v->value, "em_w")) {
17301 confp->chan.sig = SIG_EMWINK;
17302 } else if (!strcasecmp(v->value, "fxs_ls")) {
17303 confp->chan.sig = SIG_FXSLS;
17304 } else if (!strcasecmp(v->value, "fxs_gs")) {
17305 confp->chan.sig = SIG_FXSGS;
17306 } else if (!strcasecmp(v->value, "fxs_ks")) {
17307 confp->chan.sig = SIG_FXSKS;
17308 } else if (!strcasecmp(v->value, "fxo_ls")) {
17309 confp->chan.sig = SIG_FXOLS;
17310 } else if (!strcasecmp(v->value, "fxo_gs")) {
17311 confp->chan.sig = SIG_FXOGS;
17312 } else if (!strcasecmp(v->value, "fxo_ks")) {
17313 confp->chan.sig = SIG_FXOKS;
17314 } else if (!strcasecmp(v->value, "fxs_rx")) {
17315 confp->chan.sig = SIG_FXSKS;
17316 confp->chan.radio = 1;
17317 } else if (!strcasecmp(v->value, "fxo_rx")) {
17318 confp->chan.sig = SIG_FXOLS;
17319 confp->chan.radio = 1;
17320 } else if (!strcasecmp(v->value, "fxs_tx")) {
17321 confp->chan.sig = SIG_FXSLS;
17322 confp->chan.radio = 1;
17323 } else if (!strcasecmp(v->value, "fxo_tx")) {
17324 confp->chan.sig = SIG_FXOGS;
17325 confp->chan.radio = 1;
17326 } else if (!strcasecmp(v->value, "em_rx")) {
17327 confp->chan.sig = SIG_EM;
17328 confp->chan.radio = 1;
17329 } else if (!strcasecmp(v->value, "em_tx")) {
17330 confp->chan.sig = SIG_EM;
17331 confp->chan.radio = 1;
17332 } else if (!strcasecmp(v->value, "em_rxtx")) {
17333 confp->chan.sig = SIG_EM;
17334 confp->chan.radio = 2;
17335 } else if (!strcasecmp(v->value, "em_txrx")) {
17336 confp->chan.sig = SIG_EM;
17337 confp->chan.radio = 2;
17338 } else if (!strcasecmp(v->value, "sf")) {
17339 confp->chan.sig = SIG_SF;
17340 } else if (!strcasecmp(v->value, "sf_w")) {
17341 confp->chan.sig = SIG_SFWINK;
17342 } else if (!strcasecmp(v->value, "sf_featd")) {
17343 confp->chan.sig = SIG_FEATD;
17344 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17345 confp->chan.sig = SIG_FEATDMF;
17346 } else if (!strcasecmp(v->value, "sf_featb")) {
17347 confp->chan.sig = SIG_SF_FEATB;
17348 } else if (!strcasecmp(v->value, "sf")) {
17349 confp->chan.sig = SIG_SF;
17350 } else if (!strcasecmp(v->value, "sf_rx")) {
17351 confp->chan.sig = SIG_SF;
17352 confp->chan.radio = 1;
17353 } else if (!strcasecmp(v->value, "sf_tx")) {
17354 confp->chan.sig = SIG_SF;
17355 confp->chan.radio = 1;
17356 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17357 confp->chan.sig = SIG_SF;
17358 confp->chan.radio = 2;
17359 } else if (!strcasecmp(v->value, "sf_txrx")) {
17360 confp->chan.sig = SIG_SF;
17361 confp->chan.radio = 2;
17362 } else if (!strcasecmp(v->value, "featd")) {
17363 confp->chan.sig = SIG_FEATD;
17364 } else if (!strcasecmp(v->value, "featdmf")) {
17365 confp->chan.sig = SIG_FEATDMF;
17366 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17367 confp->chan.sig = SIG_FEATDMF_TA;
17368 } else if (!strcasecmp(v->value, "e911")) {
17369 confp->chan.sig = SIG_E911;
17370 } else if (!strcasecmp(v->value, "fgccama")) {
17371 confp->chan.sig = SIG_FGC_CAMA;
17372 } else if (!strcasecmp(v->value, "fgccamamf")) {
17373 confp->chan.sig = SIG_FGC_CAMAMF;
17374 } else if (!strcasecmp(v->value, "featb")) {
17375 confp->chan.sig = SIG_FEATB;
17376 #ifdef HAVE_PRI
17377 } else if (!strcasecmp(v->value, "pri_net")) {
17378 confp->chan.sig = SIG_PRI;
17379 confp->pri.pri.nodetype = PRI_NETWORK;
17380 } else if (!strcasecmp(v->value, "pri_cpe")) {
17381 confp->chan.sig = SIG_PRI;
17382 confp->pri.pri.nodetype = PRI_CPE;
17383 } else if (!strcasecmp(v->value, "bri_cpe")) {
17384 confp->chan.sig = SIG_BRI;
17385 confp->pri.pri.nodetype = PRI_CPE;
17386 } else if (!strcasecmp(v->value, "bri_net")) {
17387 confp->chan.sig = SIG_BRI;
17388 confp->pri.pri.nodetype = PRI_NETWORK;
17389 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17390 confp->chan.sig = SIG_BRI_PTMP;
17391 confp->pri.pri.nodetype = PRI_CPE;
17392 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17393 #if defined(HAVE_PRI_CALL_HOLD)
17394 confp->chan.sig = SIG_BRI_PTMP;
17395 confp->pri.pri.nodetype = PRI_NETWORK;
17396 #else
17397 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17398 #endif
17399 #endif
17400 #if defined(HAVE_SS7)
17401 } else if (!strcasecmp(v->value, "ss7")) {
17402 confp->chan.sig = SIG_SS7;
17403 #endif
17404 #ifdef HAVE_OPENR2
17405 } else if (!strcasecmp(v->value, "mfcr2")) {
17406 confp->chan.sig = SIG_MFCR2;
17407 #endif
17408 } else if (!strcasecmp(v->value, "auto")) {
17409 confp->is_sig_auto = 1;
17410 } else {
17411 confp->chan.outsigmod = orig_outsigmod;
17412 confp->chan.radio = orig_radio;
17413 confp->is_sig_auto = orig_auto;
17414 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17415 }
17416 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17417 if (!strcasecmp(v->value, "em")) {
17418 confp->chan.outsigmod = SIG_EM;
17419 } else if (!strcasecmp(v->value, "em_e1")) {
17420 confp->chan.outsigmod = SIG_EM_E1;
17421 } else if (!strcasecmp(v->value, "em_w")) {
17422 confp->chan.outsigmod = SIG_EMWINK;
17423 } else if (!strcasecmp(v->value, "sf")) {
17424 confp->chan.outsigmod = SIG_SF;
17425 } else if (!strcasecmp(v->value, "sf_w")) {
17426 confp->chan.outsigmod = SIG_SFWINK;
17427 } else if (!strcasecmp(v->value, "sf_featd")) {
17428 confp->chan.outsigmod = SIG_FEATD;
17429 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17430 confp->chan.outsigmod = SIG_FEATDMF;
17431 } else if (!strcasecmp(v->value, "sf_featb")) {
17432 confp->chan.outsigmod = SIG_SF_FEATB;
17433 } else if (!strcasecmp(v->value, "sf")) {
17434 confp->chan.outsigmod = SIG_SF;
17435 } else if (!strcasecmp(v->value, "featd")) {
17436 confp->chan.outsigmod = SIG_FEATD;
17437 } else if (!strcasecmp(v->value, "featdmf")) {
17438 confp->chan.outsigmod = SIG_FEATDMF;
17439 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17440 confp->chan.outsigmod = SIG_FEATDMF_TA;
17441 } else if (!strcasecmp(v->value, "e911")) {
17442 confp->chan.outsigmod = SIG_E911;
17443 } else if (!strcasecmp(v->value, "fgccama")) {
17444 confp->chan.outsigmod = SIG_FGC_CAMA;
17445 } else if (!strcasecmp(v->value, "fgccamamf")) {
17446 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17447 } else if (!strcasecmp(v->value, "featb")) {
17448 confp->chan.outsigmod = SIG_FEATB;
17449 } else {
17450 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17451 }
17452 #ifdef HAVE_PRI
17453 } else if (!strcasecmp(v->name, "pridialplan")) {
17454 if (!strcasecmp(v->value, "national")) {
17455 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17456 } else if (!strcasecmp(v->value, "unknown")) {
17457 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17458 } else if (!strcasecmp(v->value, "private")) {
17459 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17460 } else if (!strcasecmp(v->value, "international")) {
17461 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17462 } else if (!strcasecmp(v->value, "local")) {
17463 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17464 } else if (!strcasecmp(v->value, "dynamic")) {
17465 confp->pri.pri.dialplan = -1;
17466 } else if (!strcasecmp(v->value, "redundant")) {
17467 confp->pri.pri.dialplan = -2;
17468 } else {
17469 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17470 }
17471 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17472 if (!strcasecmp(v->value, "national")) {
17473 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17474 } else if (!strcasecmp(v->value, "unknown")) {
17475 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17476 } else if (!strcasecmp(v->value, "private")) {
17477 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17478 } else if (!strcasecmp(v->value, "international")) {
17479 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17480 } else if (!strcasecmp(v->value, "local")) {
17481 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17482 } else if (!strcasecmp(v->value, "dynamic")) {
17483 confp->pri.pri.localdialplan = -1;
17484 } else if (!strcasecmp(v->value, "redundant")) {
17485 confp->pri.pri.localdialplan = -2;
17486 } else {
17487 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17488 }
17489 } else if (!strcasecmp(v->name, "switchtype")) {
17490 if (!strcasecmp(v->value, "national"))
17491 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17492 else if (!strcasecmp(v->value, "ni1"))
17493 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17494 else if (!strcasecmp(v->value, "dms100"))
17495 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17496 else if (!strcasecmp(v->value, "4ess"))
17497 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17498 else if (!strcasecmp(v->value, "5ess"))
17499 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17500 else if (!strcasecmp(v->value, "euroisdn"))
17501 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17502 else if (!strcasecmp(v->value, "qsig"))
17503 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17504 else {
17505 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17506 return -1;
17507 }
17508 } else if (!strcasecmp(v->name, "msn")) {
17509 ast_copy_string(confp->pri.pri.msn_list, v->value,
17510 sizeof(confp->pri.pri.msn_list));
17511 } else if (!strcasecmp(v->name, "nsf")) {
17512 if (!strcasecmp(v->value, "sdn"))
17513 confp->pri.pri.nsf = PRI_NSF_SDN;
17514 else if (!strcasecmp(v->value, "megacom"))
17515 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17516 else if (!strcasecmp(v->value, "tollfreemegacom"))
17517 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17518 else if (!strcasecmp(v->value, "accunet"))
17519 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17520 else if (!strcasecmp(v->value, "none"))
17521 confp->pri.pri.nsf = PRI_NSF_NONE;
17522 else {
17523 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17524 confp->pri.pri.nsf = PRI_NSF_NONE;
17525 }
17526 } else if (!strcasecmp(v->name, "priindication")) {
17527 if (!strcasecmp(v->value, "outofband"))
17528 confp->chan.priindication_oob = 1;
17529 else if (!strcasecmp(v->value, "inband"))
17530 confp->chan.priindication_oob = 0;
17531 else
17532 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17533 v->value, v->lineno);
17534 } else if (!strcasecmp(v->name, "priexclusive")) {
17535 confp->chan.priexclusive = ast_true(v->value);
17536 } else if (!strcasecmp(v->name, "internationalprefix")) {
17537 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17538 } else if (!strcasecmp(v->name, "nationalprefix")) {
17539 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17540 } else if (!strcasecmp(v->name, "localprefix")) {
17541 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17542 } else if (!strcasecmp(v->name, "privateprefix")) {
17543 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17544 } else if (!strcasecmp(v->name, "unknownprefix")) {
17545 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17546 } else if (!strcasecmp(v->name, "resetinterval")) {
17547 if (!strcasecmp(v->value, "never"))
17548 confp->pri.pri.resetinterval = -1;
17549 else if (atoi(v->value) >= 60)
17550 confp->pri.pri.resetinterval = atoi(v->value);
17551 else
17552 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17553 v->value, v->lineno);
17554 } else if (!strcasecmp(v->name, "minunused")) {
17555 confp->pri.pri.minunused = atoi(v->value);
17556 } else if (!strcasecmp(v->name, "minidle")) {
17557 confp->pri.pri.minidle = atoi(v->value);
17558 } else if (!strcasecmp(v->name, "idleext")) {
17559 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17560 } else if (!strcasecmp(v->name, "idledial")) {
17561 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17562 } else if (!strcasecmp(v->name, "overlapdial")) {
17563 if (ast_true(v->value)) {
17564 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17565 } else if (!strcasecmp(v->value, "incoming")) {
17566 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17567 } else if (!strcasecmp(v->value, "outgoing")) {
17568 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17569 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17570 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17571 } else {
17572 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17573 }
17574 #ifdef HAVE_PRI_PROG_W_CAUSE
17575 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17576 if (!strcasecmp(v->value, "logical")) {
17577 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17578 } else if (!strcasecmp(v->value, "physical")) {
17579 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17580 } else {
17581 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17582 }
17583 #endif
17584 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17585 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17586 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17587 } else if (!strcasecmp(v->name, "service_message_support")) {
17588
17589 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17590 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17591 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17592 confp->pri.pri.enable_service_message_support = 1;
17593 } else {
17594 confp->pri.pri.enable_service_message_support = 0;
17595 }
17596 #endif
17597 #ifdef HAVE_PRI_INBANDDISCONNECT
17598 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17599 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17600 #endif
17601 } else if (!strcasecmp(v->name, "pritimer")) {
17602 #ifdef PRI_GETSET_TIMERS
17603 char tmp[20];
17604 char *timerc;
17605 char *c;
17606 int timer;
17607 int timeridx;
17608
17609 ast_copy_string(tmp, v->value, sizeof(tmp));
17610 c = tmp;
17611 timerc = strsep(&c, ",");
17612 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17613 timeridx = pri_timer2idx(timerc);
17614 timer = atoi(c);
17615 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17616 ast_log(LOG_WARNING,
17617 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17618 v->lineno);
17619 } else if (!timer) {
17620 ast_log(LOG_WARNING,
17621 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17622 c, timerc, v->lineno);
17623 } else {
17624 confp->pri.pri.pritimers[timeridx] = timer;
17625 }
17626 } else {
17627 ast_log(LOG_WARNING,
17628 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17629 v->value, v->lineno);
17630 }
17631 #endif
17632 } else if (!strcasecmp(v->name, "facilityenable")) {
17633 confp->pri.pri.facilityenable = ast_true(v->value);
17634 #if defined(HAVE_PRI_AOC_EVENTS)
17635 } else if (!strcasecmp(v->name, "aoc_enable")) {
17636 confp->pri.pri.aoc_passthrough_flag = 0;
17637 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17638 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17639 }
17640 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17641 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17642 }
17643 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17644 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17645 }
17646 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17647 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17648 #endif
17649 #if defined(HAVE_PRI_CALL_HOLD)
17650 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17651 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17652 #endif
17653 #if defined(HAVE_PRI_CCSS)
17654 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17655 if (!strcasecmp(v->value, "global")) {
17656 confp->pri.pri.cc_ptmp_recall_mode = 0;
17657 } else if (!strcasecmp(v->value, "specific")) {
17658 confp->pri.pri.cc_ptmp_recall_mode = 1;
17659 } else {
17660 confp->pri.pri.cc_ptmp_recall_mode = 1;
17661 }
17662 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17663 if (!strcasecmp(v->value, "release")) {
17664 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17665 } else if (!strcasecmp(v->value, "retain")) {
17666 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17667 } else if (!strcasecmp(v->value, "do_not_care")) {
17668 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17669 } else {
17670 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17671 }
17672 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17673 if (!strcasecmp(v->value, "release")) {
17674 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17675 } else if (!strcasecmp(v->value, "retain")) {
17676 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17677 } else {
17678 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17679 }
17680 #endif
17681 #if defined(HAVE_PRI_CALL_WAITING)
17682 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17683 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17684 if (confp->pri.pri.max_call_waiting_calls < 0) {
17685
17686 confp->pri.pri.max_call_waiting_calls = 0;
17687 }
17688 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17689 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17690 #endif
17691 #if defined(HAVE_PRI_MWI)
17692 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17693 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17694 sizeof(confp->pri.pri.mwi_mailboxes));
17695 #endif
17696 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17697 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17698 } else if (!strcasecmp(v->name, "layer1_presence")) {
17699 if (!strcasecmp(v->value, "required")) {
17700 confp->pri.pri.layer1_ignored = 0;
17701 } else if (!strcasecmp(v->value, "ignore")) {
17702 confp->pri.pri.layer1_ignored = 1;
17703 } else {
17704
17705 confp->pri.pri.layer1_ignored = 0;
17706 }
17707 #if defined(HAVE_PRI_L2_PERSISTENCE)
17708 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17709 if (!strcasecmp(v->value, "keep_up")) {
17710 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17711 } else if (!strcasecmp(v->value, "leave_down")) {
17712 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17713 } else {
17714 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17715 }
17716 #endif
17717 #endif
17718 #if defined(HAVE_SS7)
17719 } else if (!strcasecmp(v->name, "ss7type")) {
17720 if (!strcasecmp(v->value, "itu")) {
17721 cur_ss7type = SS7_ITU;
17722 } else if (!strcasecmp(v->value, "ansi")) {
17723 cur_ss7type = SS7_ANSI;
17724 } else
17725 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17726 } else if (!strcasecmp(v->name, "linkset")) {
17727 cur_linkset = atoi(v->value);
17728 } else if (!strcasecmp(v->name, "pointcode")) {
17729 cur_pointcode = parse_pointcode(v->value);
17730 } else if (!strcasecmp(v->name, "adjpointcode")) {
17731 cur_adjpointcode = parse_pointcode(v->value);
17732 } else if (!strcasecmp(v->name, "defaultdpc")) {
17733 cur_defaultdpc = parse_pointcode(v->value);
17734 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17735 cur_cicbeginswith = atoi(v->value);
17736 } else if (!strcasecmp(v->name, "networkindicator")) {
17737 if (!strcasecmp(v->value, "national"))
17738 cur_networkindicator = SS7_NI_NAT;
17739 else if (!strcasecmp(v->value, "national_spare"))
17740 cur_networkindicator = SS7_NI_NAT_SPARE;
17741 else if (!strcasecmp(v->value, "international"))
17742 cur_networkindicator = SS7_NI_INT;
17743 else if (!strcasecmp(v->value, "international_spare"))
17744 cur_networkindicator = SS7_NI_INT_SPARE;
17745 else
17746 cur_networkindicator = -1;
17747 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17748 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17749 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17750 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17751 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17752 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17753 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17754 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17755 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17756 if (!strcasecmp(v->value, "national")) {
17757 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17758 } else if (!strcasecmp(v->value, "international")) {
17759 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17760 } else if (!strcasecmp(v->value, "subscriber")) {
17761 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17762 } else if (!strcasecmp(v->value, "unknown")) {
17763 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17764 } else if (!strcasecmp(v->value, "dynamic")) {
17765 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17766 } else {
17767 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17768 }
17769 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17770 if (!strcasecmp(v->value, "national")) {
17771 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17772 } else if (!strcasecmp(v->value, "international")) {
17773 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17774 } else if (!strcasecmp(v->value, "subscriber")) {
17775 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17776 } else if (!strcasecmp(v->value, "unknown")) {
17777 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17778 } else if (!strcasecmp(v->value, "dynamic")) {
17779 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17780 } else {
17781 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17782 }
17783 } else if (!strcasecmp(v->name, "sigchan")) {
17784 int sigchan, res;
17785 sigchan = atoi(v->value);
17786 res = linkset_addsigchan(sigchan);
17787 if (res < 0)
17788 return -1;
17789
17790 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17791 struct dahdi_ss7 *link;
17792 link = ss7_resolve_linkset(cur_linkset);
17793 if (!link) {
17794 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17795 return -1;
17796 }
17797 if (ast_true(v->value))
17798 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17799 #endif
17800 #ifdef HAVE_OPENR2
17801 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17802 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17803 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);
17804 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17805 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17806 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17807 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17808 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17809 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17810 confp->mfcr2.variant = OR2_VAR_ITU;
17811 }
17812 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17813 confp->mfcr2.mfback_timeout = atoi(v->value);
17814 if (!confp->mfcr2.mfback_timeout) {
17815 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17816 confp->mfcr2.mfback_timeout = -1;
17817 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17818 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17819 }
17820 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17821 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17822 if (confp->mfcr2.metering_pulse_timeout > 500) {
17823 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17824 }
17825 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17826 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17827 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17828 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17829 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17830 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17831 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17832 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17833 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17834 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17835 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17836 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17837 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17838 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17839 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17840 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17841 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17842 #endif
17843 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17844 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17845 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17846 confp->mfcr2.max_ani = atoi(v->value);
17847 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17848 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17849 }
17850 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17851 confp->mfcr2.max_dnis = atoi(v->value);
17852 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17853 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17854 }
17855 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17856 confp->mfcr2.category = openr2_proto_get_category(v->value);
17857 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17858 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17859 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17860 v->value, v->lineno);
17861 }
17862 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17863 openr2_log_level_t tmplevel;
17864 char *clevel;
17865 char *logval = ast_strdupa(v->value);
17866 while (logval) {
17867 clevel = strsep(&logval,",");
17868 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17869 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17870 continue;
17871 }
17872 confp->mfcr2.loglevel |= tmplevel;
17873 }
17874 #endif
17875 } else if (!strcasecmp(v->name, "cadence")) {
17876
17877 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17878 int i;
17879 struct dahdi_ring_cadence new_cadence;
17880 int cid_location = -1;
17881 int firstcadencepos = 0;
17882 char original_args[80];
17883 int cadence_is_ok = 1;
17884
17885 ast_copy_string(original_args, v->value, sizeof(original_args));
17886
17887 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]);
17888
17889
17890 if (element_count % 2 == 1) {
17891 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17892 cadence_is_ok = 0;
17893 }
17894
17895
17896 for (i = 0; i < element_count; i++) {
17897 if (c[i] == 0) {
17898 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17899 cadence_is_ok = 0;
17900 break;
17901 } else if (c[i] < 0) {
17902 if (i % 2 == 1) {
17903
17904 if (cid_location == -1) {
17905 cid_location = i;
17906 c[i] *= -1;
17907 } else {
17908 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17909 cadence_is_ok = 0;
17910 break;
17911 }
17912 } else {
17913 if (firstcadencepos == 0) {
17914 firstcadencepos = i;
17915
17916 } else {
17917 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17918 cadence_is_ok = 0;
17919 break;
17920 }
17921 }
17922 }
17923 }
17924
17925
17926 for (i = 0; i < 16; i++) {
17927 new_cadence.ringcadence[i] = c[i];
17928 }
17929
17930 if (cadence_is_ok) {
17931
17932 if (element_count < 2) {
17933 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17934 } else {
17935 if (cid_location == -1) {
17936
17937 cid_location = 1;
17938 } else {
17939
17940 cid_location = (cid_location + 1) / 2;
17941 }
17942
17943 if (!user_has_defined_cadences++)
17944
17945 num_cadence = 0;
17946 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17947 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17948 else {
17949 cadences[num_cadence] = new_cadence;
17950 cidrings[num_cadence++] = cid_location;
17951 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17952 }
17953 }
17954 }
17955 } else if (!strcasecmp(v->name, "ringtimeout")) {
17956 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17957 } else if (!strcasecmp(v->name, "prewink")) {
17958 confp->timing.prewinktime = atoi(v->value);
17959 } else if (!strcasecmp(v->name, "preflash")) {
17960 confp->timing.preflashtime = atoi(v->value);
17961 } else if (!strcasecmp(v->name, "wink")) {
17962 confp->timing.winktime = atoi(v->value);
17963 } else if (!strcasecmp(v->name, "flash")) {
17964 confp->timing.flashtime = atoi(v->value);
17965 } else if (!strcasecmp(v->name, "start")) {
17966 confp->timing.starttime = atoi(v->value);
17967 } else if (!strcasecmp(v->name, "rxwink")) {
17968 confp->timing.rxwinktime = atoi(v->value);
17969 } else if (!strcasecmp(v->name, "rxflash")) {
17970 confp->timing.rxflashtime = atoi(v->value);
17971 } else if (!strcasecmp(v->name, "debounce")) {
17972 confp->timing.debouncetime = atoi(v->value);
17973 } else if (!strcasecmp(v->name, "toneduration")) {
17974 int toneduration;
17975 int ctlfd;
17976 int res;
17977 struct dahdi_dialparams dps;
17978
17979 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17980 if (ctlfd == -1) {
17981 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17982 return -1;
17983 }
17984
17985 toneduration = atoi(v->value);
17986 if (toneduration > -1) {
17987 memset(&dps, 0, sizeof(dps));
17988
17989 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17990 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17991 if (res < 0) {
17992 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17993 close(ctlfd);
17994 return -1;
17995 }
17996 }
17997 close(ctlfd);
17998 } else if (!strcasecmp(v->name, "defaultcic")) {
17999 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18000 } else if (!strcasecmp(v->name, "defaultozz")) {
18001 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18002 } else if (!strcasecmp(v->name, "mwilevel")) {
18003 mwilevel = atoi(v->value);
18004 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18005 dtmfcid_level = atoi(v->value);
18006 } else if (!strcasecmp(v->name, "reportalarms")) {
18007 if (!strcasecmp(v->value, "all"))
18008 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18009 if (!strcasecmp(v->value, "none"))
18010 report_alarms = 0;
18011 else if (!strcasecmp(v->value, "channels"))
18012 report_alarms = REPORT_CHANNEL_ALARMS;
18013 else if (!strcasecmp(v->value, "spans"))
18014 report_alarms = REPORT_SPAN_ALARMS;
18015 }
18016 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18017 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18018 }
18019
18020
18021 if (confp->chan.vars) {
18022 ast_variables_destroy(confp->chan.vars);
18023 confp->chan.vars = NULL;
18024 }
18025
18026 if (dahdichan) {
18027
18028 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18029 &found_pseudo)) {
18030 if (confp->ignore_failed_channels) {
18031 ast_log(LOG_WARNING,
18032 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18033 dahdichan->value);
18034 } else {
18035 return -1;
18036 }
18037 }
18038 }
18039
18040
18041 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18042 if (!tmp->destroy && tmp->span != y) {
18043 tmp->manages_span_alarms = 1;
18044 y = tmp->span;
18045 } else {
18046 tmp->manages_span_alarms = 0;
18047 }
18048 }
18049
18050
18051
18052 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18053
18054
18055
18056
18057 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18058
18059 if (conf.chan.cc_params) {
18060 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18061 } else {
18062 tmp = NULL;
18063 }
18064 if (tmp) {
18065 ast_verb(3, "Automatically generated pseudo channel\n");
18066 } else {
18067 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18068 }
18069 ast_cc_config_params_destroy(conf.chan.cc_params);
18070 }
18071 return 0;
18072 }
18073
18074
18075
18076
18077
18078
18079
18080
18081
18082
18083
18084 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18085 {
18086 struct ast_cc_config_params *cc_params;
18087
18088 cc_params = dest->chan.cc_params;
18089 *dest = *src;
18090 dest->chan.cc_params = cc_params;
18091 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18092 }
18093
18094
18095
18096
18097
18098
18099
18100
18101
18102
18103
18104
18105
18106 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18107 {
18108 struct ast_config *cfg;
18109 struct ast_config *ucfg;
18110 struct ast_variable *v;
18111 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18112 const char *chans;
18113 const char *cat;
18114 int res;
18115
18116 #ifdef HAVE_PRI
18117 char *c;
18118 int spanno;
18119 int i;
18120 int logicalspan;
18121 int trunkgroup;
18122 int dchannels[SIG_PRI_NUM_DCHANS];
18123 #endif
18124 int have_cfg_now;
18125 static int had_cfg_before = 1;
18126
18127 cfg = ast_config_load(config, config_flags);
18128 have_cfg_now = !!cfg;
18129 if (!cfg) {
18130
18131 if (had_cfg_before) {
18132 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18133 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18134 }
18135 cfg = ast_config_new();
18136 if (!cfg) {
18137 return 0;
18138 }
18139 ucfg = ast_config_load("users.conf", config_flags);
18140 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18141 ast_config_destroy(cfg);
18142 return 0;
18143 }
18144 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18145 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18146 ast_config_destroy(cfg);
18147 return 0;
18148 }
18149 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18150 ucfg = ast_config_load("users.conf", config_flags);
18151 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18152 return 0;
18153 }
18154 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18155 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18156 return 0;
18157 }
18158 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18159 cfg = ast_config_load(config, config_flags);
18160 have_cfg_now = !!cfg;
18161 if (!cfg) {
18162 if (had_cfg_before) {
18163
18164 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18165 ast_config_destroy(ucfg);
18166 return 0;
18167 }
18168 cfg = ast_config_new();
18169 if (!cfg) {
18170 ast_config_destroy(ucfg);
18171 return 0;
18172 }
18173 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18174 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18175 ast_config_destroy(ucfg);
18176 return 0;
18177 }
18178 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18179 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18180 return 0;
18181 } else {
18182 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18183 ucfg = ast_config_load("users.conf", config_flags);
18184 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18186 ast_config_destroy(cfg);
18187 return 0;
18188 }
18189 }
18190 had_cfg_before = have_cfg_now;
18191
18192
18193 ast_mutex_lock(&iflock);
18194 #ifdef HAVE_PRI
18195 if (reload != 1) {
18196
18197 v = ast_variable_browse(cfg, "trunkgroups");
18198 while (v) {
18199 if (!strcasecmp(v->name, "trunkgroup")) {
18200 trunkgroup = atoi(v->value);
18201 if (trunkgroup > 0) {
18202 if ((c = strchr(v->value, ','))) {
18203 i = 0;
18204 memset(dchannels, 0, sizeof(dchannels));
18205 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18206 dchannels[i] = atoi(c + 1);
18207 if (dchannels[i] < 0) {
18208 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);
18209 } else
18210 i++;
18211 c = strchr(c + 1, ',');
18212 }
18213 if (i) {
18214 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18215 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);
18216 } else
18217 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");
18218 } else
18219 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18220 } else
18221 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18222 } else
18223 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18224 } else if (!strcasecmp(v->name, "spanmap")) {
18225 spanno = atoi(v->value);
18226 if (spanno > 0) {
18227 if ((c = strchr(v->value, ','))) {
18228 trunkgroup = atoi(c + 1);
18229 if (trunkgroup > 0) {
18230 if ((c = strchr(c + 1, ',')))
18231 logicalspan = atoi(c + 1);
18232 else
18233 logicalspan = 0;
18234 if (logicalspan >= 0) {
18235 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18236 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18237 } else
18238 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18239 } else
18240 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);
18241 } else
18242 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18243 } else
18244 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18245 } else
18246 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18247 } else {
18248 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18249 }
18250 v = v->next;
18251 }
18252 }
18253 #endif
18254
18255
18256 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18257
18258 mwimonitornotify[0] = '\0';
18259
18260 v = ast_variable_browse(cfg, "channels");
18261 if ((res = process_dahdi(base_conf,
18262 "" ,
18263 v, reload, 0))) {
18264 ast_mutex_unlock(&iflock);
18265 ast_config_destroy(cfg);
18266 if (ucfg) {
18267 ast_config_destroy(ucfg);
18268 }
18269 return res;
18270 }
18271
18272
18273 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18274
18275
18276
18277 if (!strcasecmp(cat, "general") ||
18278 !strcasecmp(cat, "trunkgroups") ||
18279 !strcasecmp(cat, "globals") ||
18280 !strcasecmp(cat, "channels")) {
18281 continue;
18282 }
18283
18284 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18285 if (ast_strlen_zero(chans)) {
18286
18287 continue;
18288 }
18289
18290
18291 deep_copy_dahdi_chan_conf(conf, base_conf);
18292
18293 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18294 ast_mutex_unlock(&iflock);
18295 ast_config_destroy(cfg);
18296 if (ucfg) {
18297 ast_config_destroy(ucfg);
18298 }
18299 return res;
18300 }
18301 }
18302
18303 ast_config_destroy(cfg);
18304
18305 if (ucfg) {
18306
18307 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18308 process_dahdi(base_conf,
18309 "" ,
18310 ast_variable_browse(ucfg, "general"), 1, 0);
18311
18312 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18313 if (!strcasecmp(cat, "general")) {
18314 continue;
18315 }
18316
18317 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18318 if (ast_strlen_zero(chans)) {
18319
18320 continue;
18321 }
18322
18323
18324 deep_copy_dahdi_chan_conf(conf, base_conf);
18325
18326 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18327 ast_config_destroy(ucfg);
18328 ast_mutex_unlock(&iflock);
18329 return res;
18330 }
18331 }
18332 ast_config_destroy(ucfg);
18333 }
18334 ast_mutex_unlock(&iflock);
18335
18336 #ifdef HAVE_PRI
18337 if (reload != 1) {
18338 int x;
18339 for (x = 0; x < NUM_SPANS; x++) {
18340 if (pris[x].pri.pvts[0]) {
18341 prepare_pri(pris + x);
18342 if (sig_pri_start_pri(&pris[x].pri)) {
18343 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18344 return -1;
18345 } else
18346 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18347 }
18348 }
18349 }
18350 #endif
18351 #if defined(HAVE_SS7)
18352 if (reload != 1) {
18353 int x;
18354 for (x = 0; x < NUM_SPANS; x++) {
18355 if (linksets[x].ss7.ss7) {
18356 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18357 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18358 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18359 return -1;
18360 } else
18361 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18362 }
18363 }
18364 }
18365 #endif
18366 #ifdef HAVE_OPENR2
18367 if (reload != 1) {
18368 int x;
18369 for (x = 0; x < r2links_count; x++) {
18370 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18371 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18372 return -1;
18373 } else {
18374 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18375 }
18376 }
18377 }
18378 #endif
18379
18380 restart_monitor();
18381 return 0;
18382 }
18383
18384
18385
18386
18387
18388
18389
18390
18391
18392
18393 static int setup_dahdi(int reload)
18394 {
18395 int res;
18396 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18397 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18398 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18399
18400 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18401 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18402 } else {
18403 res = -1;
18404 }
18405 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18406 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18407 ast_cc_config_params_destroy(conf.chan.cc_params);
18408
18409 return res;
18410 }
18411
18412
18413
18414
18415
18416
18417
18418
18419 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18420 struct ast_data *data_root)
18421 {
18422 int ctl, res, span;
18423 struct ast_data *data_span, *data_alarms;
18424 struct dahdi_spaninfo s;
18425
18426 ctl = open("/dev/dahdi/ctl", O_RDWR);
18427 if (ctl < 0) {
18428 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18429 return -1;
18430 }
18431 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18432 s.spanno = span;
18433 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18434 if (res) {
18435 continue;
18436 }
18437
18438 data_span = ast_data_add_node(data_root, "span");
18439 if (!data_span) {
18440 continue;
18441 }
18442 ast_data_add_str(data_span, "description", s.desc);
18443
18444
18445 data_alarms = ast_data_add_node(data_span, "alarms");
18446 if (!data_alarms) {
18447 continue;
18448 }
18449
18450 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18451 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18452 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18453 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18454 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18455 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18456
18457 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18458 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18459 ast_data_add_int(data_span, "crc4", s.crc4count);
18460 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18461 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18462 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18463 "CAS");
18464 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18465 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18466 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18467 "Unknown");
18468 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18469 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18470 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18471 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18472
18473
18474 if (!ast_data_search_match(search, data_span)) {
18475 ast_data_remove_node(data_root, data_span);
18476 }
18477 }
18478 close(ctl);
18479
18480 return 0;
18481 }
18482
18483
18484
18485
18486
18487
18488
18489
18490 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18491 struct ast_data *data_root)
18492 {
18493 struct dahdi_pvt *tmp;
18494 struct ast_data *data_channel;
18495
18496 ast_mutex_lock(&iflock);
18497 for (tmp = iflist; tmp; tmp = tmp->next) {
18498 data_channel = ast_data_add_node(data_root, "channel");
18499 if (!data_channel) {
18500 continue;
18501 }
18502
18503 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18504
18505
18506 if (!ast_data_search_match(search, data_channel)) {
18507 ast_data_remove_node(data_root, data_channel);
18508 }
18509 }
18510 ast_mutex_unlock(&iflock);
18511
18512 return 0;
18513 }
18514
18515
18516
18517
18518
18519
18520
18521
18522 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18523 struct ast_data *data_root)
18524 {
18525 int pseudo_fd = -1;
18526 struct dahdi_versioninfo vi = {
18527 .version = "Unknown",
18528 .echo_canceller = "Unknown"
18529 };
18530
18531 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18532 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18533 return -1;
18534 }
18535
18536 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18537 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18538 }
18539
18540 close(pseudo_fd);
18541
18542 ast_data_add_str(data_root, "value", vi.version);
18543 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18544
18545 return 0;
18546 }
18547
18548 static const struct ast_data_handler dahdi_status_data_provider = {
18549 .version = AST_DATA_HANDLER_VERSION,
18550 .get = dahdi_status_data_provider_get
18551 };
18552
18553 static const struct ast_data_handler dahdi_channels_data_provider = {
18554 .version = AST_DATA_HANDLER_VERSION,
18555 .get = dahdi_channels_data_provider_get
18556 };
18557
18558 static const struct ast_data_handler dahdi_version_data_provider = {
18559 .version = AST_DATA_HANDLER_VERSION,
18560 .get = dahdi_version_data_provider_get
18561 };
18562
18563 static const struct ast_data_entry dahdi_data_providers[] = {
18564 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18565 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18566 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18567 };
18568
18569 static int load_module(void)
18570 {
18571 int res;
18572 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18573 int y;
18574 #endif
18575
18576 #ifdef HAVE_PRI
18577 memset(pris, 0, sizeof(pris));
18578 for (y = 0; y < NUM_SPANS; y++) {
18579 sig_pri_init_pri(&pris[y].pri);
18580 }
18581 pri_set_error(dahdi_pri_error);
18582 pri_set_message(dahdi_pri_message);
18583 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18584 #ifdef HAVE_PRI_PROG_W_CAUSE
18585 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18586 #endif
18587 #if defined(HAVE_PRI_CCSS)
18588 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18589 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18590 __unload_module();
18591 return AST_MODULE_LOAD_FAILURE;
18592 }
18593 #endif
18594 if (sig_pri_load(
18595 #if defined(HAVE_PRI_CCSS)
18596 dahdi_pri_cc_type
18597 #else
18598 NULL
18599 #endif
18600 )) {
18601 __unload_module();
18602 return AST_MODULE_LOAD_FAILURE;
18603 }
18604 #endif
18605 #if defined(HAVE_SS7)
18606 memset(linksets, 0, sizeof(linksets));
18607 for (y = 0; y < NUM_SPANS; y++) {
18608 sig_ss7_init_linkset(&linksets[y].ss7);
18609 }
18610 ss7_set_error(dahdi_ss7_error);
18611 ss7_set_message(dahdi_ss7_message);
18612 #endif
18613 res = setup_dahdi(0);
18614
18615 if (res)
18616 return AST_MODULE_LOAD_DECLINE;
18617 if (ast_channel_register(&dahdi_tech)) {
18618 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18619 __unload_module();
18620 return AST_MODULE_LOAD_FAILURE;
18621 }
18622 #ifdef HAVE_PRI
18623 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18624 #endif
18625 #if defined(HAVE_SS7)
18626 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18627 #endif
18628 #ifdef HAVE_OPENR2
18629 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18630 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18631 #endif
18632
18633 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18634
18635 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18636 memset(round_robin, 0, sizeof(round_robin));
18637 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18638 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18639 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18640 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18641 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18642 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18643 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18644
18645 ast_cond_init(&ss_thread_complete, NULL);
18646
18647 return res;
18648 }
18649
18650 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18651 {
18652 #define END_SILENCE_LEN 400
18653 #define HEADER_MS 50
18654 #define TRAILER_MS 5
18655 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18656 #define ASCII_BYTES_PER_CHAR 80
18657
18658 unsigned char *buf,*mybuf;
18659 struct dahdi_pvt *p = c->tech_pvt;
18660 struct pollfd fds[1];
18661 int size,res,fd,len,x;
18662 int bytes=0;
18663
18664 float cr = 1.0;
18665 float ci = 0.0;
18666 float scont = 0.0;
18667 int idx;
18668
18669 idx = dahdi_get_index(c, p, 0);
18670 if (idx < 0) {
18671 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18672 return -1;
18673 }
18674 if (!text[0]) return(0);
18675 if ((!p->tdd) && (!p->mate)) return(0);
18676 if (p->mate)
18677 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18678 else
18679 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18680 if (!buf)
18681 return -1;
18682 mybuf = buf;
18683 if (p->mate) {
18684 int codec = AST_LAW(p);
18685 for (x = 0; x < HEADER_MS; x++) {
18686 PUT_CLID_MARKMS;
18687 }
18688
18689 for (x = 0; text[x]; x++) {
18690 PUT_CLID(text[x]);
18691 }
18692 for (x = 0; x < TRAILER_MS; x++) {
18693 PUT_CLID_MARKMS;
18694 }
18695 len = bytes;
18696 buf = mybuf;
18697 } else {
18698 len = tdd_generate(p->tdd, buf, text);
18699 if (len < 1) {
18700 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18701 ast_free(mybuf);
18702 return -1;
18703 }
18704 }
18705 memset(buf + len, 0x7f, END_SILENCE_LEN);
18706 len += END_SILENCE_LEN;
18707 fd = p->subs[idx].dfd;
18708 while (len) {
18709 if (ast_check_hangup(c)) {
18710 ast_free(mybuf);
18711 return -1;
18712 }
18713 size = len;
18714 if (size > READ_SIZE)
18715 size = READ_SIZE;
18716 fds[0].fd = fd;
18717 fds[0].events = POLLOUT | POLLPRI;
18718 fds[0].revents = 0;
18719 res = poll(fds, 1, -1);
18720 if (!res) {
18721 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18722 continue;
18723 }
18724
18725 if (fds[0].revents & POLLPRI) {
18726 ast_free(mybuf);
18727 return -1;
18728 }
18729 if (!(fds[0].revents & POLLOUT)) {
18730 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18731 continue;
18732 }
18733 res = write(fd, buf, size);
18734 if (res != size) {
18735 if (res == -1) {
18736 ast_free(mybuf);
18737 return -1;
18738 }
18739 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18740 break;
18741 }
18742 len -= size;
18743 buf += size;
18744 }
18745 ast_free(mybuf);
18746 return(0);
18747 }
18748
18749
18750 static int reload(void)
18751 {
18752 int res = 0;
18753
18754 res = setup_dahdi(1);
18755 if (res) {
18756 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18757 return -1;
18758 }
18759 return 0;
18760 }
18761
18762
18763
18764
18765
18766 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18767 .load = load_module,
18768 .unload = unload_module,
18769 .reload = reload,
18770 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18771 .nonoptreq = "res_smdi",
18772 );