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: 358377 $")
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 busy_tonelength;
01130
01131
01132
01133
01134 int busy_quietlength;
01135
01136
01137
01138
01139 int callprogress;
01140
01141
01142
01143
01144 int waitfordialtone;
01145 struct timeval waitingfordt;
01146 struct timeval flashtime;
01147
01148 struct ast_dsp *dsp;
01149
01150 struct dahdi_dialoperation dop;
01151 int whichwink;
01152
01153 char finaldial[64];
01154 char accountcode[AST_MAX_ACCOUNT_CODE];
01155 int amaflags;
01156 struct tdd_state *tdd;
01157
01158 char call_forward[AST_MAX_EXTENSION];
01159
01160
01161
01162
01163 char mailbox[AST_MAX_EXTENSION];
01164
01165 struct ast_event_sub *mwi_event_sub;
01166
01167 char dialdest[256];
01168 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01169 struct dahdi_vmwi_info mwisend_setting;
01170 unsigned int mwisend_fsk: 1;
01171 unsigned int mwisend_rpas:1;
01172 #endif
01173 int distinctivering;
01174 int dtmfrelax;
01175
01176 int fake_event;
01177
01178
01179
01180
01181 int polarityonanswerdelay;
01182
01183 struct timeval polaritydelaytv;
01184
01185
01186
01187
01188 int sendcalleridafter;
01189
01190 int polarity;
01191
01192 int dsp_features;
01193 #if defined(HAVE_SS7)
01194
01195 struct sig_ss7_linkset *ss7;
01196 #endif
01197 #ifdef HAVE_OPENR2
01198 struct dahdi_mfcr2 *mfcr2;
01199 openr2_chan_t *r2chan;
01200 openr2_calling_party_category_t mfcr2_recvd_category;
01201 openr2_calling_party_category_t mfcr2_category;
01202 int mfcr2_dnis_index;
01203 int mfcr2_ani_index;
01204 int mfcr2call:1;
01205 int mfcr2_answer_pending:1;
01206 int mfcr2_charge_calls:1;
01207 int mfcr2_allow_collect_calls:1;
01208 int mfcr2_forced_release:1;
01209 int mfcr2_dnis_matched:1;
01210 int mfcr2_call_accepted:1;
01211 int mfcr2_progress:1;
01212 int mfcr2_accept_on_offer:1;
01213 #endif
01214
01215 char begindigit;
01216
01217 int muting;
01218 void *sig_pvt;
01219 struct ast_cc_config_params *cc_params;
01220
01221
01222
01223
01224
01225
01226 char dialstring[AST_CHANNEL_NAME];
01227 };
01228
01229 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01230 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01231 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01232 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01233 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01234 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01235 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01236 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01237 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01238 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01239 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01240 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01241 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01242 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01291 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01292 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01293 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01294 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01295 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01296 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01297
01298 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01299
01300 static struct dahdi_pvt *iflist = NULL;
01301 static struct dahdi_pvt *ifend = NULL;
01302
01303 #if defined(HAVE_PRI)
01304 static struct dahdi_parms_pseudo {
01305 int buf_no;
01306 int buf_policy;
01307 int faxbuf_no;
01308 int faxbuf_policy;
01309 } dahdi_pseudo_parms;
01310 #endif
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 struct dahdi_chan_conf {
01323 struct dahdi_pvt chan;
01324 #ifdef HAVE_PRI
01325 struct dahdi_pri pri;
01326 #endif
01327
01328 #if defined(HAVE_SS7)
01329 struct dahdi_ss7 ss7;
01330 #endif
01331
01332 #ifdef HAVE_OPENR2
01333 struct dahdi_mfcr2_conf mfcr2;
01334 #endif
01335 struct dahdi_params timing;
01336 int is_sig_auto;
01337
01338 int ignore_failed_channels;
01339
01340
01341
01342
01343
01344 char smdi_port[SMDI_MAX_FILENAME_LEN];
01345 };
01346
01347
01348 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01349 {
01350
01351
01352
01353 struct dahdi_chan_conf conf = {
01354 #ifdef HAVE_PRI
01355 .pri.pri = {
01356 .nsf = PRI_NSF_NONE,
01357 .switchtype = PRI_SWITCH_NI2,
01358 .dialplan = PRI_UNKNOWN + 1,
01359 .localdialplan = PRI_NATIONAL_ISDN + 1,
01360 .nodetype = PRI_CPE,
01361 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01362
01363 #if defined(HAVE_PRI_CCSS)
01364 .cc_ptmp_recall_mode = 1,
01365 .cc_qsig_signaling_link_req = 1,
01366 .cc_qsig_signaling_link_rsp = 1,
01367 #endif
01368
01369 .minunused = 2,
01370 .idleext = "",
01371 .idledial = "",
01372 .internationalprefix = "",
01373 .nationalprefix = "",
01374 .localprefix = "",
01375 .privateprefix = "",
01376 .unknownprefix = "",
01377 .resetinterval = -1,
01378 },
01379 #endif
01380 #if defined(HAVE_SS7)
01381 .ss7.ss7 = {
01382 .called_nai = SS7_NAI_NATIONAL,
01383 .calling_nai = SS7_NAI_NATIONAL,
01384 .internationalprefix = "",
01385 .nationalprefix = "",
01386 .subscriberprefix = "",
01387 .unknownprefix = ""
01388 },
01389 #endif
01390 #ifdef HAVE_OPENR2
01391 .mfcr2 = {
01392 .variant = OR2_VAR_ITU,
01393 .mfback_timeout = -1,
01394 .metering_pulse_timeout = -1,
01395 .max_ani = 10,
01396 .max_dnis = 4,
01397 .get_ani_first = -1,
01398 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01399 .skip_category_request = -1,
01400 #endif
01401 .call_files = 0,
01402 .allow_collect_calls = 0,
01403 .charge_calls = 1,
01404 .accept_on_offer = 1,
01405 .forced_release = 0,
01406 .double_answer = 0,
01407 .immediate_accept = -1,
01408 .logdir = "",
01409 .r2proto_file = "",
01410 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01411 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01412 },
01413 #endif
01414 .chan = {
01415 .context = "default",
01416 .cid_num = "",
01417 .cid_name = "",
01418 .cid_tag = "",
01419 .mohinterpret = "default",
01420 .mohsuggest = "",
01421 .parkinglot = "",
01422 .transfertobusy = 1,
01423
01424 .cid_signalling = CID_SIG_BELL,
01425 .cid_start = CID_START_RING,
01426 .dahditrcallerid = 0,
01427 .use_callerid = 1,
01428 .sig = -1,
01429 .outsigmod = -1,
01430
01431 .cid_rxgain = +5.0,
01432
01433 .tonezone = -1,
01434
01435 .echocancel.head.tap_length = 1,
01436
01437 .busycount = 3,
01438
01439 .accountcode = "",
01440
01441 .mailbox = "",
01442
01443 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01444 .mwisend_fsk = 1,
01445 #endif
01446 .polarityonanswerdelay = 600,
01447
01448 .sendcalleridafter = DEFAULT_CIDRINGS,
01449
01450 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01451 .buf_no = numbufs,
01452 .usefaxbuffers = 0,
01453 .cc_params = ast_cc_config_params_init(),
01454 },
01455 .timing = {
01456 .prewinktime = -1,
01457 .preflashtime = -1,
01458 .winktime = -1,
01459 .flashtime = -1,
01460 .starttime = -1,
01461 .rxwinktime = -1,
01462 .rxflashtime = -1,
01463 .debouncetime = -1
01464 },
01465 .is_sig_auto = 1,
01466 .smdi_port = "/dev/ttyS0",
01467 };
01468
01469 return conf;
01470 }
01471
01472
01473 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01474 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01475 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01476 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01477 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01478 static int dahdi_hangup(struct ast_channel *ast);
01479 static int dahdi_answer(struct ast_channel *ast);
01480 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01481 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01482 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01483 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01484 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01485 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01486 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01487 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01488 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01489 static int dahdi_devicestate(void *data);
01490 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01491
01492 static const struct ast_channel_tech dahdi_tech = {
01493 .type = "DAHDI",
01494 .description = tdesc,
01495 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01496 .requester = dahdi_request,
01497 .send_digit_begin = dahdi_digit_begin,
01498 .send_digit_end = dahdi_digit_end,
01499 .send_text = dahdi_sendtext,
01500 .call = dahdi_call,
01501 .hangup = dahdi_hangup,
01502 .answer = dahdi_answer,
01503 .read = dahdi_read,
01504 .write = dahdi_write,
01505 .bridge = dahdi_bridge,
01506 .exception = dahdi_exception,
01507 .indicate = dahdi_indicate,
01508 .fixup = dahdi_fixup,
01509 .setoption = dahdi_setoption,
01510 .queryoption = dahdi_queryoption,
01511 .func_channel_read = dahdi_func_read,
01512 .func_channel_write = dahdi_func_write,
01513 .devicestate = dahdi_devicestate,
01514 .cc_callback = dahdi_cc_callback,
01515 };
01516
01517 #define GET_CHANNEL(p) ((p)->channel)
01518
01519 #define SIG_PRI_LIB_HANDLE_CASES \
01520 SIG_PRI: \
01521 case SIG_BRI: \
01522 case SIG_BRI_PTMP
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533 static inline int dahdi_sig_pri_lib_handles(int signaling)
01534 {
01535 int handles;
01536
01537 switch (signaling) {
01538 case SIG_PRI_LIB_HANDLE_CASES:
01539 handles = 1;
01540 break;
01541 default:
01542 handles = 0;
01543 break;
01544 }
01545
01546 return handles;
01547 }
01548
01549 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01550 {
01551 switch (sig) {
01552 case SIG_FXOLS:
01553 return ANALOG_SIG_FXOLS;
01554 case SIG_FXOGS:
01555 return ANALOG_SIG_FXOGS;
01556 case SIG_FXOKS:
01557 return ANALOG_SIG_FXOKS;
01558 case SIG_FXSLS:
01559 return ANALOG_SIG_FXSLS;
01560 case SIG_FXSGS:
01561 return ANALOG_SIG_FXSGS;
01562 case SIG_FXSKS:
01563 return ANALOG_SIG_FXSKS;
01564 case SIG_EMWINK:
01565 return ANALOG_SIG_EMWINK;
01566 case SIG_EM:
01567 return ANALOG_SIG_EM;
01568 case SIG_EM_E1:
01569 return ANALOG_SIG_EM_E1;
01570 case SIG_FEATD:
01571 return ANALOG_SIG_FEATD;
01572 case SIG_FEATDMF:
01573 return ANALOG_SIG_FEATDMF;
01574 case SIG_E911:
01575 return SIG_E911;
01576 case SIG_FGC_CAMA:
01577 return ANALOG_SIG_FGC_CAMA;
01578 case SIG_FGC_CAMAMF:
01579 return ANALOG_SIG_FGC_CAMAMF;
01580 case SIG_FEATB:
01581 return ANALOG_SIG_FEATB;
01582 case SIG_SFWINK:
01583 return ANALOG_SIG_SFWINK;
01584 case SIG_SF:
01585 return ANALOG_SIG_SF;
01586 case SIG_SF_FEATD:
01587 return ANALOG_SIG_SF_FEATD;
01588 case SIG_SF_FEATDMF:
01589 return ANALOG_SIG_SF_FEATDMF;
01590 case SIG_FEATDMF_TA:
01591 return ANALOG_SIG_FEATDMF_TA;
01592 case SIG_SF_FEATB:
01593 return ANALOG_SIG_FEATB;
01594 default:
01595 return -1;
01596 }
01597 }
01598
01599
01600 static int analog_tone_to_dahditone(enum analog_tone tone)
01601 {
01602 switch (tone) {
01603 case ANALOG_TONE_RINGTONE:
01604 return DAHDI_TONE_RINGTONE;
01605 case ANALOG_TONE_STUTTER:
01606 return DAHDI_TONE_STUTTER;
01607 case ANALOG_TONE_CONGESTION:
01608 return DAHDI_TONE_CONGESTION;
01609 case ANALOG_TONE_DIALTONE:
01610 return DAHDI_TONE_DIALTONE;
01611 case ANALOG_TONE_DIALRECALL:
01612 return DAHDI_TONE_DIALRECALL;
01613 case ANALOG_TONE_INFO:
01614 return DAHDI_TONE_INFO;
01615 default:
01616 return -1;
01617 }
01618 }
01619
01620 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01621 {
01622 int index;
01623
01624 switch (analogsub) {
01625 case ANALOG_SUB_REAL:
01626 index = SUB_REAL;
01627 break;
01628 case ANALOG_SUB_CALLWAIT:
01629 index = SUB_CALLWAIT;
01630 break;
01631 case ANALOG_SUB_THREEWAY:
01632 index = SUB_THREEWAY;
01633 break;
01634 default:
01635 ast_log(LOG_ERROR, "Unidentified sub!\n");
01636 index = SUB_REAL;
01637 }
01638
01639 return index;
01640 }
01641
01642 static enum analog_event dahdievent_to_analogevent(int event);
01643 static int bump_gains(struct dahdi_pvt *p);
01644 static int dahdi_setlinear(int dfd, int linear);
01645
01646 static int my_start_cid_detect(void *pvt, int cid_signalling)
01647 {
01648 struct dahdi_pvt *p = pvt;
01649 int index = SUB_REAL;
01650 p->cs = callerid_new(cid_signalling);
01651 if (!p->cs) {
01652 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01653 return -1;
01654 }
01655 bump_gains(p);
01656 dahdi_setlinear(p->subs[index].dfd, 0);
01657
01658 return 0;
01659 }
01660
01661 static int my_stop_cid_detect(void *pvt)
01662 {
01663 struct dahdi_pvt *p = pvt;
01664 int index = SUB_REAL;
01665 if (p->cs)
01666 callerid_free(p->cs);
01667 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01668 return 0;
01669 }
01670
01671 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01672 {
01673 struct dahdi_pvt *p = pvt;
01674 struct analog_pvt *analog_p = p->sig_pvt;
01675 struct pollfd poller;
01676 char *name, *num;
01677 int index = SUB_REAL;
01678 int res;
01679 unsigned char buf[256];
01680 int flags;
01681
01682 poller.fd = p->subs[SUB_REAL].dfd;
01683 poller.events = POLLPRI | POLLIN;
01684 poller.revents = 0;
01685
01686 res = poll(&poller, 1, timeout);
01687
01688 if (poller.revents & POLLPRI) {
01689 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01690 return 1;
01691 }
01692
01693 if (poller.revents & POLLIN) {
01694
01695
01696
01697
01698
01699 res = read(p->subs[index].dfd, buf, sizeof(buf));
01700 if (res < 0) {
01701 if (errno != ELAST) {
01702 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01703 callerid_free(p->cs);
01704 return -1;
01705 }
01706 }
01707
01708 if (analog_p->ringt > 0) {
01709 if (!(--analog_p->ringt)) {
01710
01711 return -1;
01712 }
01713 }
01714
01715 if (p->cid_signalling == CID_SIG_V23_JP) {
01716 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01717 } else {
01718 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01719 }
01720 if (res < 0) {
01721
01722
01723
01724
01725 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01726 return -1;
01727 }
01728
01729 if (res == 1) {
01730 callerid_get(p->cs, &name, &num, &flags);
01731 if (name)
01732 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01733 if (num)
01734 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01735
01736 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01737 return 0;
01738 }
01739 }
01740
01741 *ev = ANALOG_EVENT_NONE;
01742 return 2;
01743 }
01744
01745 static const char *event2str(int event);
01746 static int restore_gains(struct dahdi_pvt *p);
01747
01748 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01749 {
01750 unsigned char buf[256];
01751 int distMatches;
01752 int curRingData[RING_PATTERNS];
01753 int receivedRingT;
01754 int counter1;
01755 int counter;
01756 int i;
01757 int res;
01758 int checkaftercid = 0;
01759
01760 struct dahdi_pvt *p = pvt;
01761 struct analog_pvt *analog_p = p->sig_pvt;
01762
01763 if (ringdata == NULL) {
01764 ringdata = curRingData;
01765 } else {
01766 checkaftercid = 1;
01767 }
01768
01769
01770
01771 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01772
01773 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01774 ringdata[receivedRingT] = 0;
01775 receivedRingT = 0;
01776 if (checkaftercid && distinctiveringaftercid)
01777 ast_verb(3, "Detecting post-CID distinctive ring\n");
01778
01779 else if (strcmp(p->context,p->defcontext) != 0) {
01780 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01781 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01782 }
01783
01784 for (;;) {
01785 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01786 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01787 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01788 ast_hangup(chan);
01789 return 1;
01790 }
01791 if (i & DAHDI_IOMUX_SIGEVENT) {
01792 res = dahdi_get_event(p->subs[idx].dfd);
01793 if (res == DAHDI_EVENT_NOALARM) {
01794 p->inalarm = 0;
01795 analog_p->inalarm = 0;
01796 }
01797 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01798 res = 0;
01799
01800
01801 ringdata[receivedRingT] = analog_p->ringt;
01802
01803 if (analog_p->ringt < analog_p->ringt_base/2)
01804 break;
01805
01806
01807 if (++receivedRingT == RING_PATTERNS)
01808 break;
01809 } else if (i & DAHDI_IOMUX_READ) {
01810 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01811 if (res < 0) {
01812 if (errno != ELAST) {
01813 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01814 ast_hangup(chan);
01815 return 1;
01816 }
01817 break;
01818 }
01819 if (analog_p->ringt > 0) {
01820 if (!(--analog_p->ringt)) {
01821 res = -1;
01822 break;
01823 }
01824 }
01825 }
01826 }
01827 }
01828 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01829
01830 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01831 for (counter = 0; counter < 3; counter++) {
01832
01833 distMatches = 0;
01834
01835 ast_verb(3, "Checking %d,%d,%d\n",
01836 p->drings.ringnum[counter].ring[0],
01837 p->drings.ringnum[counter].ring[1],
01838 p->drings.ringnum[counter].ring[2]);
01839 for (counter1 = 0; counter1 < 3; counter1++) {
01840 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01841 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01842 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01843 ringdata[counter1]);
01844 distMatches++;
01845 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01846 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01847 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01848 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01849 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01850 distMatches++;
01851 }
01852 }
01853
01854 if (distMatches == 3) {
01855
01856 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01857 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01858 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01859 break;
01860 }
01861 }
01862 }
01863
01864 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01865 restore_gains(p);
01866
01867 return 0;
01868 }
01869
01870 static int my_stop_callwait(void *pvt)
01871 {
01872 struct dahdi_pvt *p = pvt;
01873 p->callwaitingrepeat = 0;
01874 p->cidcwexpire = 0;
01875 p->cid_suppress_expire = 0;
01876
01877 return 0;
01878 }
01879
01880 static int send_callerid(struct dahdi_pvt *p);
01881 static int save_conference(struct dahdi_pvt *p);
01882 static int restore_conference(struct dahdi_pvt *p);
01883
01884 static int my_callwait(void *pvt)
01885 {
01886 struct dahdi_pvt *p = pvt;
01887 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01888 if (p->cidspill) {
01889 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01890 ast_free(p->cidspill);
01891 }
01892
01893
01894
01895
01896
01897 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01898 return -1;
01899 save_conference(p);
01900
01901 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01902 if (!p->callwaitrings && p->callwaitingcallerid) {
01903 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01904 p->callwaitcas = 1;
01905 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01906 } else {
01907 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01908 p->callwaitcas = 0;
01909 p->cidlen = 2400 + READ_SIZE * 4;
01910 }
01911 p->cidpos = 0;
01912 send_callerid(p);
01913
01914 return 0;
01915 }
01916
01917 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01918 {
01919 struct dahdi_pvt *p = pvt;
01920
01921 ast_debug(2, "Starting cid spill\n");
01922
01923 if (p->cidspill) {
01924 ast_log(LOG_WARNING, "cidspill already exists??\n");
01925 ast_free(p->cidspill);
01926 }
01927
01928 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01929 if (cwcid == 0) {
01930 p->cidlen = ast_callerid_generate(p->cidspill,
01931 caller->id.name.str,
01932 caller->id.number.str,
01933 AST_LAW(p));
01934 } else {
01935 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01936 caller->id.name.str, caller->id.number.str);
01937 p->callwaitcas = 0;
01938 p->cidcwexpire = 0;
01939 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01940 caller->id.name.str,
01941 caller->id.number.str,
01942 AST_LAW(p));
01943 p->cidlen += READ_SIZE * 4;
01944 }
01945 p->cidpos = 0;
01946 p->cid_suppress_expire = 0;
01947 send_callerid(p);
01948 }
01949 return 0;
01950 }
01951
01952 static int my_dsp_reset_and_flush_digits(void *pvt)
01953 {
01954 struct dahdi_pvt *p = pvt;
01955 if (p->dsp)
01956 ast_dsp_digitreset(p->dsp);
01957
01958 return 0;
01959 }
01960
01961 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01962 {
01963 struct dahdi_pvt *p = pvt;
01964
01965 if (p->channel == CHAN_PSEUDO)
01966 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01967
01968 if (mode == ANALOG_DIGITMODE_DTMF) {
01969
01970 if (p->hardwaredtmf) {
01971 if (p->dsp) {
01972 ast_dsp_free(p->dsp);
01973 p->dsp = NULL;
01974 }
01975 return 0;
01976 }
01977
01978 if (!p->dsp) {
01979 p->dsp = ast_dsp_new();
01980 if (!p->dsp) {
01981 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01982 return -1;
01983 }
01984 }
01985
01986 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01987 } else if (mode == ANALOG_DIGITMODE_MF) {
01988 if (!p->dsp) {
01989 p->dsp = ast_dsp_new();
01990 if (!p->dsp) {
01991 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01992 return -1;
01993 }
01994 }
01995 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01996 }
01997 return 0;
01998 }
01999
02000 static int dahdi_wink(struct dahdi_pvt *p, int index);
02001
02002 static int my_wink(void *pvt, enum analog_sub sub)
02003 {
02004 struct dahdi_pvt *p = pvt;
02005 int index = analogsub_to_dahdisub(sub);
02006 if (index != SUB_REAL) {
02007 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02008 }
02009 return dahdi_wink(p, index);
02010 }
02011
02012 static void wakeup_sub(struct dahdi_pvt *p, int a);
02013
02014 static int reset_conf(struct dahdi_pvt *p);
02015
02016 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02017
02018 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02019 {
02020 struct ast_frame *f = *dest;
02021 struct dahdi_pvt *p = pvt;
02022 int idx = analogsub_to_dahdisub(analog_index);
02023
02024 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02025 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02026 f->subclass.integer, f->subclass.integer, ast->name);
02027
02028 if (f->subclass.integer == 'f') {
02029 if (f->frametype == AST_FRAME_DTMF_END) {
02030
02031 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02032
02033 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02034 struct dahdi_bufferinfo bi = {
02035 .txbufpolicy = p->faxbuf_policy,
02036 .bufsize = p->bufsize,
02037 .numbufs = p->faxbuf_no
02038 };
02039 int res;
02040
02041 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02042 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02043 } else {
02044 p->bufferoverrideinuse = 1;
02045 }
02046 }
02047 p->faxhandled = 1;
02048 if (p->dsp) {
02049 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02050 ast_dsp_set_features(p->dsp, p->dsp_features);
02051 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02052 }
02053 if (strcmp(ast->exten, "fax")) {
02054 const char *target_context = S_OR(ast->macrocontext, ast->context);
02055
02056
02057
02058
02059
02060 ast_mutex_unlock(&p->lock);
02061 ast_channel_unlock(ast);
02062 if (ast_exists_extension(ast, target_context, "fax", 1,
02063 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02064 ast_channel_lock(ast);
02065 ast_mutex_lock(&p->lock);
02066 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02067
02068 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02069 if (ast_async_goto(ast, target_context, "fax", 1))
02070 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02071 } else {
02072 ast_channel_lock(ast);
02073 ast_mutex_lock(&p->lock);
02074 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02075 }
02076 } else {
02077 ast_debug(1, "Already in a fax extension, not redirecting\n");
02078 }
02079 } else {
02080 ast_debug(1, "Fax already handled\n");
02081 }
02082 dahdi_confmute(p, 0);
02083 }
02084 p->subs[idx].f.frametype = AST_FRAME_NULL;
02085 p->subs[idx].f.subclass.integer = 0;
02086 *dest = &p->subs[idx].f;
02087 }
02088 }
02089
02090 static void my_lock_private(void *pvt)
02091 {
02092 struct dahdi_pvt *p = pvt;
02093 ast_mutex_lock(&p->lock);
02094 }
02095
02096 static void my_unlock_private(void *pvt)
02097 {
02098 struct dahdi_pvt *p = pvt;
02099 ast_mutex_unlock(&p->lock);
02100 }
02101
02102 static void my_deadlock_avoidance_private(void *pvt)
02103 {
02104 struct dahdi_pvt *p = pvt;
02105
02106 DEADLOCK_AVOIDANCE(&p->lock);
02107 }
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02120 {
02121 char ch_name[20];
02122
02123 if (p->channel < CHAN_PSEUDO) {
02124
02125 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02126 } else if (p->channel == CHAN_PSEUDO) {
02127
02128 strcpy(ch_name, "pseudo");
02129 } else {
02130
02131 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02132 }
02133 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02134 "Channel: %s\r\n"
02135 "Uniqueid: %s\r\n"
02136 "DAHDISpan: %d\r\n"
02137 "DAHDIChannel: %s\r\n",
02138 chan->name,
02139 chan->uniqueid,
02140 p->span,
02141 ch_name);
02142 }
02143
02144 #ifdef HAVE_PRI
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02156 {
02157 struct dahdi_pvt *p = pvt;
02158
02159 dahdi_ami_channel_event(p, chan);
02160 }
02161 #endif
02162
02163
02164
02165
02166 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02167 {
02168 struct dahdi_pvt *p = pvt;
02169 int oldval;
02170 int idx = analogsub_to_dahdisub(sub);
02171
02172 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02173 oldval = p->subs[idx].linear;
02174 p->subs[idx].linear = linear_mode ? 1 : 0;
02175 return oldval;
02176 }
02177
02178 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02179 {
02180 struct dahdi_pvt *p = pvt;
02181 int idx = analogsub_to_dahdisub(sub);
02182
02183 p->subs[idx].inthreeway = inthreeway;
02184 }
02185
02186 static int get_alarms(struct dahdi_pvt *p);
02187 static void handle_alarms(struct dahdi_pvt *p, int alms);
02188 static void my_get_and_handle_alarms(void *pvt)
02189 {
02190 int res;
02191 struct dahdi_pvt *p = pvt;
02192
02193 res = get_alarms(p);
02194 handle_alarms(p, res);
02195 }
02196
02197 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02198 {
02199 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02200 if (p)
02201 return p->sig_pvt;
02202 else
02203 return NULL;
02204 }
02205
02206 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02207 {
02208 struct dahdi_pvt *p = pvt;
02209 int dahdi_sub = analogsub_to_dahdisub(sub);
02210 return p->subs[dahdi_sub].dfd;
02211 }
02212
02213 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02214 {
02215 struct dahdi_pvt *p = pvt;
02216
02217
02218 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02219 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02220 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02221 *cid_rings = cidrings[p->distinctivering - 1];
02222 } else {
02223 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02224 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02225 *cid_rings = p->sendcalleridafter;
02226 }
02227 }
02228
02229 static void my_set_alarm(void *pvt, int in_alarm)
02230 {
02231 struct dahdi_pvt *p = pvt;
02232
02233 p->inalarm = in_alarm;
02234 }
02235
02236 static void my_set_dialing(void *pvt, int is_dialing)
02237 {
02238 struct dahdi_pvt *p = pvt;
02239
02240 p->dialing = is_dialing;
02241 }
02242
02243 static void my_set_outgoing(void *pvt, int is_outgoing)
02244 {
02245 struct dahdi_pvt *p = pvt;
02246
02247 p->outgoing = is_outgoing;
02248 }
02249
02250 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02251 static void my_set_digital(void *pvt, int is_digital)
02252 {
02253 struct dahdi_pvt *p = pvt;
02254
02255 p->digital = is_digital;
02256 }
02257 #endif
02258
02259 #if defined(HAVE_SS7)
02260 static void my_set_inservice(void *pvt, int is_inservice)
02261 {
02262 struct dahdi_pvt *p = pvt;
02263
02264 p->inservice = is_inservice;
02265 }
02266 #endif
02267
02268 #if defined(HAVE_SS7)
02269 static void my_set_locallyblocked(void *pvt, int is_blocked)
02270 {
02271 struct dahdi_pvt *p = pvt;
02272
02273 p->locallyblocked = is_blocked;
02274 }
02275 #endif
02276
02277 #if defined(HAVE_SS7)
02278 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02279 {
02280 struct dahdi_pvt *p = pvt;
02281
02282 p->remotelyblocked = is_blocked;
02283 }
02284 #endif
02285
02286 static void my_set_ringtimeout(void *pvt, int ringt)
02287 {
02288 struct dahdi_pvt *p = pvt;
02289 p->ringt = ringt;
02290 }
02291
02292 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02293 {
02294 struct dahdi_pvt *p = pvt;
02295
02296 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02297 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02298 gettimeofday(&p->waitingfordt, NULL);
02299 ast_setstate(ast, AST_STATE_OFFHOOK);
02300 }
02301 }
02302
02303 static int my_check_waitingfordt(void *pvt)
02304 {
02305 struct dahdi_pvt *p = pvt;
02306
02307 if (p->waitingfordt.tv_usec) {
02308 return 1;
02309 }
02310
02311 return 0;
02312 }
02313
02314 static void my_set_confirmanswer(void *pvt, int flag)
02315 {
02316 struct dahdi_pvt *p = pvt;
02317 p->confirmanswer = flag;
02318 }
02319
02320 static int my_check_confirmanswer(void *pvt)
02321 {
02322 struct dahdi_pvt *p = pvt;
02323 if (p->confirmanswer) {
02324 return 1;
02325 }
02326
02327 return 0;
02328 }
02329
02330 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02331 {
02332 struct dahdi_pvt *p = pvt;
02333
02334 p->callwaiting = callwaiting_enable;
02335 }
02336
02337 static void my_cancel_cidspill(void *pvt)
02338 {
02339 struct dahdi_pvt *p = pvt;
02340
02341 ast_free(p->cidspill);
02342 p->cidspill = NULL;
02343 restore_conference(p);
02344 }
02345
02346 static int my_confmute(void *pvt, int mute)
02347 {
02348 struct dahdi_pvt *p = pvt;
02349 return dahdi_confmute(p, mute);
02350 }
02351
02352 static void my_set_pulsedial(void *pvt, int flag)
02353 {
02354 struct dahdi_pvt *p = pvt;
02355 p->pulsedial = flag;
02356 }
02357
02358 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02359 {
02360 struct dahdi_pvt *p = pvt;
02361
02362 p->owner = new_owner;
02363 }
02364
02365 static const char *my_get_orig_dialstring(void *pvt)
02366 {
02367 struct dahdi_pvt *p = pvt;
02368
02369 return p->dialstring;
02370 }
02371
02372 static void my_increase_ss_count(void)
02373 {
02374 ast_mutex_lock(&ss_thread_lock);
02375 ss_thread_count++;
02376 ast_mutex_unlock(&ss_thread_lock);
02377 }
02378
02379 static void my_decrease_ss_count(void)
02380 {
02381 ast_mutex_lock(&ss_thread_lock);
02382 ss_thread_count--;
02383 ast_cond_signal(&ss_thread_complete);
02384 ast_mutex_unlock(&ss_thread_lock);
02385 }
02386
02387 static void my_all_subchannels_hungup(void *pvt)
02388 {
02389 struct dahdi_pvt *p = pvt;
02390 int res, law;
02391
02392 p->faxhandled = 0;
02393 p->didtdd = 0;
02394
02395 if (p->dsp) {
02396 ast_dsp_free(p->dsp);
02397 p->dsp = NULL;
02398 }
02399
02400 p->law = p->law_default;
02401 law = p->law_default;
02402 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02403 if (res < 0)
02404 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02405
02406 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02407
02408 #if 1
02409 {
02410 int i;
02411 p->owner = NULL;
02412
02413 for (i = 0; i < 3; i++) {
02414 p->subs[i].owner = NULL;
02415 }
02416 }
02417 #endif
02418
02419 reset_conf(p);
02420 if (num_restart_pending == 0) {
02421 restart_monitor();
02422 }
02423 }
02424
02425 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02426
02427 static int my_conf_del(void *pvt, enum analog_sub sub)
02428 {
02429 struct dahdi_pvt *p = pvt;
02430 int x = analogsub_to_dahdisub(sub);
02431
02432 return conf_del(p, &p->subs[x], x);
02433 }
02434
02435 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02436
02437 static int my_conf_add(void *pvt, enum analog_sub sub)
02438 {
02439 struct dahdi_pvt *p = pvt;
02440 int x = analogsub_to_dahdisub(sub);
02441
02442 return conf_add(p, &p->subs[x], x, 0);
02443 }
02444
02445 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02446
02447 static int my_complete_conference_update(void *pvt, int needconference)
02448 {
02449 struct dahdi_pvt *p = pvt;
02450 int needconf = needconference;
02451 int x;
02452 int useslavenative;
02453 struct dahdi_pvt *slave = NULL;
02454
02455 useslavenative = isslavenative(p, &slave);
02456
02457
02458
02459 for (x = 0; x < MAX_SLAVES; x++) {
02460 if (p->slaves[x]) {
02461 if (useslavenative)
02462 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02463 else {
02464 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02465 needconf++;
02466 }
02467 }
02468 }
02469
02470 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02471 if (useslavenative)
02472 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02473 else {
02474 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02475 needconf++;
02476 }
02477 }
02478
02479 if (p->master) {
02480 if (isslavenative(p->master, NULL)) {
02481 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02482 } else {
02483 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02484 }
02485 }
02486 if (!needconf) {
02487
02488
02489 p->confno = -1;
02490 }
02491
02492 return 0;
02493 }
02494
02495 static int check_for_conference(struct dahdi_pvt *p);
02496
02497 static int my_check_for_conference(void *pvt)
02498 {
02499 struct dahdi_pvt *p = pvt;
02500 return check_for_conference(p);
02501 }
02502
02503 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)
02504 {
02505 struct dahdi_pvt *p = pvt;
02506 int da, db;
02507 int tchan;
02508 int tinthreeway;
02509
02510 da = analogsub_to_dahdisub(a);
02511 db = analogsub_to_dahdisub(b);
02512
02513 tchan = p->subs[da].chan;
02514 p->subs[da].chan = p->subs[db].chan;
02515 p->subs[db].chan = tchan;
02516
02517 tinthreeway = p->subs[da].inthreeway;
02518 p->subs[da].inthreeway = p->subs[db].inthreeway;
02519 p->subs[db].inthreeway = tinthreeway;
02520
02521 p->subs[da].owner = ast_a;
02522 p->subs[db].owner = ast_b;
02523
02524 if (ast_a)
02525 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02526 if (ast_b)
02527 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02528
02529 wakeup_sub(p, a);
02530 wakeup_sub(p, b);
02531
02532 return;
02533 }
02534
02535 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02536
02537 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02538 {
02539 struct dahdi_pvt *p = pvt;
02540 int dsub = analogsub_to_dahdisub(sub);
02541
02542 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02543 }
02544
02545 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02546 static int dahdi_setlaw(int dfd, int law)
02547 {
02548 int res;
02549 res = ioctl(dfd, DAHDI_SETLAW, &law);
02550 if (res)
02551 return res;
02552 return 0;
02553 }
02554 #endif
02555
02556 #if defined(HAVE_PRI)
02557 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)
02558 {
02559 struct dahdi_pvt *p = pvt;
02560 int audio;
02561 int newlaw = -1;
02562
02563 switch (p->sig) {
02564 case SIG_PRI_LIB_HANDLE_CASES:
02565 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02566
02567 break;
02568 }
02569
02570 default:
02571
02572 audio = 1;
02573 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02574 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02575 p->channel, audio, strerror(errno));
02576 }
02577 break;
02578 }
02579
02580 if (law != SIG_PRI_DEFLAW) {
02581 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02582 }
02583
02584 ast_copy_string(p->exten, exten, sizeof(p->exten));
02585
02586 switch (law) {
02587 case SIG_PRI_DEFLAW:
02588 newlaw = 0;
02589 break;
02590 case SIG_PRI_ALAW:
02591 newlaw = DAHDI_LAW_ALAW;
02592 break;
02593 case SIG_PRI_ULAW:
02594 newlaw = DAHDI_LAW_MULAW;
02595 break;
02596 }
02597 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02598 }
02599 #endif
02600
02601 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02602
02603 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613 static void my_pri_ss7_open_media(void *p)
02614 {
02615 struct dahdi_pvt *pvt = p;
02616 int res;
02617 int dfd;
02618 int set_val;
02619
02620 dfd = pvt->subs[SUB_REAL].dfd;
02621
02622
02623 set_val = 1;
02624 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02625 if (res < 0) {
02626 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02627 pvt->channel, strerror(errno));
02628 }
02629
02630
02631 res = dahdi_setlaw(dfd, pvt->law);
02632 if (res < 0) {
02633 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02634 }
02635
02636
02637 if (pvt->digital) {
02638 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02639 } else {
02640 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02641 pvt->law);
02642 }
02643 if (res < 0) {
02644 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02645 }
02646
02647 if (pvt->dsp_features && pvt->dsp) {
02648 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02649 pvt->dsp_features = 0;
02650 }
02651 }
02652 #endif
02653
02654 #if defined(HAVE_PRI)
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667 static void my_pri_dial_digits(void *p, const char *dial_string)
02668 {
02669 struct dahdi_dialoperation zo = {
02670 .op = DAHDI_DIAL_OP_APPEND,
02671 };
02672 struct dahdi_pvt *pvt = p;
02673 int res;
02674
02675 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02676 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02677 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02678 if (res) {
02679 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02680 pvt->channel, dial_string, strerror(errno));
02681 } else {
02682 pvt->dialing = 1;
02683 }
02684 }
02685 #endif
02686
02687 static int unalloc_sub(struct dahdi_pvt *p, int x);
02688
02689 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02690 {
02691 struct dahdi_pvt *p = pvt;
02692
02693 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02694 }
02695
02696 static int alloc_sub(struct dahdi_pvt *p, int x);
02697
02698 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02699 {
02700 struct dahdi_pvt *p = pvt;
02701
02702 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02703 }
02704
02705 static int has_voicemail(struct dahdi_pvt *p);
02706
02707 static int my_has_voicemail(void *pvt)
02708 {
02709 struct dahdi_pvt *p = pvt;
02710
02711 return has_voicemail(p);
02712 }
02713
02714 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02715 {
02716 struct dahdi_pvt *p = pvt;
02717 int index;
02718
02719 index = analogsub_to_dahdisub(sub);
02720
02721 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02722 }
02723
02724 static enum analog_event dahdievent_to_analogevent(int event)
02725 {
02726 enum analog_event res;
02727
02728 switch (event) {
02729 case DAHDI_EVENT_ONHOOK:
02730 res = ANALOG_EVENT_ONHOOK;
02731 break;
02732 case DAHDI_EVENT_RINGOFFHOOK:
02733 res = ANALOG_EVENT_RINGOFFHOOK;
02734 break;
02735 case DAHDI_EVENT_WINKFLASH:
02736 res = ANALOG_EVENT_WINKFLASH;
02737 break;
02738 case DAHDI_EVENT_ALARM:
02739 res = ANALOG_EVENT_ALARM;
02740 break;
02741 case DAHDI_EVENT_NOALARM:
02742 res = ANALOG_EVENT_NOALARM;
02743 break;
02744 case DAHDI_EVENT_DIALCOMPLETE:
02745 res = ANALOG_EVENT_DIALCOMPLETE;
02746 break;
02747 case DAHDI_EVENT_RINGERON:
02748 res = ANALOG_EVENT_RINGERON;
02749 break;
02750 case DAHDI_EVENT_RINGEROFF:
02751 res = ANALOG_EVENT_RINGEROFF;
02752 break;
02753 case DAHDI_EVENT_HOOKCOMPLETE:
02754 res = ANALOG_EVENT_HOOKCOMPLETE;
02755 break;
02756 case DAHDI_EVENT_PULSE_START:
02757 res = ANALOG_EVENT_PULSE_START;
02758 break;
02759 case DAHDI_EVENT_POLARITY:
02760 res = ANALOG_EVENT_POLARITY;
02761 break;
02762 case DAHDI_EVENT_RINGBEGIN:
02763 res = ANALOG_EVENT_RINGBEGIN;
02764 break;
02765 case DAHDI_EVENT_EC_DISABLED:
02766 res = ANALOG_EVENT_EC_DISABLED;
02767 break;
02768 case DAHDI_EVENT_REMOVED:
02769 res = ANALOG_EVENT_REMOVED;
02770 break;
02771 case DAHDI_EVENT_NEONMWI_ACTIVE:
02772 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02773 break;
02774 case DAHDI_EVENT_NEONMWI_INACTIVE:
02775 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02776 break;
02777 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02778 case DAHDI_EVENT_TX_CED_DETECTED:
02779 res = ANALOG_EVENT_TX_CED_DETECTED;
02780 break;
02781 case DAHDI_EVENT_RX_CED_DETECTED:
02782 res = ANALOG_EVENT_RX_CED_DETECTED;
02783 break;
02784 case DAHDI_EVENT_EC_NLP_DISABLED:
02785 res = ANALOG_EVENT_EC_NLP_DISABLED;
02786 break;
02787 case DAHDI_EVENT_EC_NLP_ENABLED:
02788 res = ANALOG_EVENT_EC_NLP_ENABLED;
02789 break;
02790 #endif
02791 case DAHDI_EVENT_PULSEDIGIT:
02792 res = ANALOG_EVENT_PULSEDIGIT;
02793 break;
02794 case DAHDI_EVENT_DTMFDOWN:
02795 res = ANALOG_EVENT_DTMFDOWN;
02796 break;
02797 case DAHDI_EVENT_DTMFUP:
02798 res = ANALOG_EVENT_DTMFUP;
02799 break;
02800 default:
02801 switch(event & 0xFFFF0000) {
02802 case DAHDI_EVENT_PULSEDIGIT:
02803 case DAHDI_EVENT_DTMFDOWN:
02804 case DAHDI_EVENT_DTMFUP:
02805
02806
02807
02808
02809 return event;
02810 }
02811
02812 res = ANALOG_EVENT_ERROR;
02813 break;
02814 }
02815
02816 return res;
02817 }
02818
02819 static inline int dahdi_wait_event(int fd);
02820
02821 static int my_wait_event(void *pvt)
02822 {
02823 struct dahdi_pvt *p = pvt;
02824
02825 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02826 }
02827
02828 static int my_get_event(void *pvt)
02829 {
02830 struct dahdi_pvt *p = pvt;
02831 int res;
02832
02833 if (p->fake_event) {
02834 res = p->fake_event;
02835 p->fake_event = 0;
02836 } else
02837 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02838
02839 return dahdievent_to_analogevent(res);
02840 }
02841
02842 static int my_is_off_hook(void *pvt)
02843 {
02844 struct dahdi_pvt *p = pvt;
02845 int res;
02846 struct dahdi_params par;
02847
02848 memset(&par, 0, sizeof(par));
02849
02850 if (p->subs[SUB_REAL].dfd > -1)
02851 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02852 else {
02853
02854 res = 0;
02855 par.rxisoffhook = 0;
02856 }
02857 if (res) {
02858 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02859 }
02860
02861 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02862
02863
02864
02865 return (par.rxbits > -1) || par.rxisoffhook;
02866 }
02867
02868 return par.rxisoffhook;
02869 }
02870
02871 static void dahdi_enable_ec(struct dahdi_pvt *p);
02872 static void dahdi_disable_ec(struct dahdi_pvt *p);
02873
02874 static int my_set_echocanceller(void *pvt, int enable)
02875 {
02876 struct dahdi_pvt *p = pvt;
02877
02878 if (enable)
02879 dahdi_enable_ec(p);
02880 else
02881 dahdi_disable_ec(p);
02882
02883 return 0;
02884 }
02885
02886 static int dahdi_ring_phone(struct dahdi_pvt *p);
02887
02888 static int my_ring(void *pvt)
02889 {
02890 struct dahdi_pvt *p = pvt;
02891
02892 return dahdi_ring_phone(p);
02893 }
02894
02895 static int my_flash(void *pvt)
02896 {
02897 struct dahdi_pvt *p = pvt;
02898 int func = DAHDI_FLASH;
02899 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02900 }
02901
02902 static inline int dahdi_set_hook(int fd, int hs);
02903
02904 static int my_off_hook(void *pvt)
02905 {
02906 struct dahdi_pvt *p = pvt;
02907 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02908 }
02909
02910 static void my_set_needringing(void *pvt, int value)
02911 {
02912 struct dahdi_pvt *p = pvt;
02913 p->subs[SUB_REAL].needringing = value;
02914 }
02915
02916 static void my_set_polarity(void *pvt, int value)
02917 {
02918 struct dahdi_pvt *p = pvt;
02919
02920 if (p->channel == CHAN_PSEUDO) {
02921 return;
02922 }
02923 p->polarity = value;
02924 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02925 }
02926
02927 static void my_start_polarityswitch(void *pvt)
02928 {
02929 struct dahdi_pvt *p = pvt;
02930
02931 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02932 my_set_polarity(pvt, 0);
02933 }
02934 }
02935
02936 static void my_answer_polarityswitch(void *pvt)
02937 {
02938 struct dahdi_pvt *p = pvt;
02939
02940 if (!p->answeronpolarityswitch) {
02941 return;
02942 }
02943
02944 my_set_polarity(pvt, 1);
02945 }
02946
02947 static void my_hangup_polarityswitch(void *pvt)
02948 {
02949 struct dahdi_pvt *p = pvt;
02950
02951 if (!p->hanguponpolarityswitch) {
02952 return;
02953 }
02954
02955 if (p->answeronpolarityswitch) {
02956 my_set_polarity(pvt, 0);
02957 } else {
02958 my_set_polarity(pvt, 1);
02959 }
02960 }
02961
02962 static int my_start(void *pvt)
02963 {
02964 struct dahdi_pvt *p = pvt;
02965 int x = DAHDI_START;
02966
02967 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02968 }
02969
02970 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02971 {
02972 int index = analogsub_to_dahdisub(sub);
02973 int res;
02974 struct dahdi_pvt *p = pvt;
02975 struct dahdi_dialoperation ddop;
02976
02977 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02978 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02979 return -1;
02980 }
02981
02982 if (sub != ANALOG_SUB_REAL) {
02983 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
02984 dop->dialstr, p->channel, sub);
02985 return -1;
02986 }
02987
02988 ddop.op = DAHDI_DIAL_OP_REPLACE;
02989 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02990
02991 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
02992
02993 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02994 if (res == -1) {
02995 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02996 }
02997
02998 return res;
02999 }
03000
03001 static void dahdi_train_ec(struct dahdi_pvt *p);
03002
03003 static int my_train_echocanceller(void *pvt)
03004 {
03005 struct dahdi_pvt *p = pvt;
03006
03007 dahdi_train_ec(p);
03008
03009 return 0;
03010 }
03011
03012 static int my_is_dialing(void *pvt, enum analog_sub sub)
03013 {
03014 struct dahdi_pvt *p = pvt;
03015 int index;
03016 int x;
03017
03018 index = analogsub_to_dahdisub(sub);
03019
03020 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03021 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03022 return -1;
03023 }
03024
03025 return x;
03026 }
03027
03028 static int my_on_hook(void *pvt)
03029 {
03030 struct dahdi_pvt *p = pvt;
03031 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03032 }
03033
03034 #if defined(HAVE_PRI)
03035 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03036 {
03037 struct dahdi_pvt *old_chan = chan_old;
03038 struct dahdi_pvt *new_chan = chan_new;
03039
03040 new_chan->owner = old_chan->owner;
03041 old_chan->owner = NULL;
03042 if (new_chan->owner) {
03043 new_chan->owner->tech_pvt = new_chan;
03044 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03045 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03046 old_chan->subs[SUB_REAL].owner = NULL;
03047 }
03048
03049 new_chan->dsp = old_chan->dsp;
03050 new_chan->dsp_features = old_chan->dsp_features;
03051 old_chan->dsp = NULL;
03052 old_chan->dsp_features = 0;
03053
03054
03055 new_chan->dialing = old_chan->dialing;
03056 new_chan->digital = old_chan->digital;
03057 new_chan->outgoing = old_chan->outgoing;
03058 old_chan->dialing = 0;
03059 old_chan->digital = 0;
03060 old_chan->outgoing = 0;
03061
03062
03063 new_chan->law = old_chan->law;
03064 strcpy(new_chan->dialstring, old_chan->dialstring);
03065 }
03066 #endif
03067
03068 #if defined(HAVE_PRI)
03069 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03070 {
03071 switch (tone) {
03072 case SIG_PRI_TONE_RINGTONE:
03073 return DAHDI_TONE_RINGTONE;
03074 case SIG_PRI_TONE_STUTTER:
03075 return DAHDI_TONE_STUTTER;
03076 case SIG_PRI_TONE_CONGESTION:
03077 return DAHDI_TONE_CONGESTION;
03078 case SIG_PRI_TONE_DIALTONE:
03079 return DAHDI_TONE_DIALTONE;
03080 case SIG_PRI_TONE_DIALRECALL:
03081 return DAHDI_TONE_DIALRECALL;
03082 case SIG_PRI_TONE_INFO:
03083 return DAHDI_TONE_INFO;
03084 case SIG_PRI_TONE_BUSY:
03085 return DAHDI_TONE_BUSY;
03086 default:
03087 return -1;
03088 }
03089 }
03090 #endif
03091
03092 #if defined(HAVE_PRI)
03093 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03094 {
03095 int x;
03096
03097 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03098 if (x) {
03099 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03100 }
03101
03102 switch (x) {
03103 case DAHDI_EVENT_ALARM:
03104 pri_event_alarm(pri, index, 0);
03105 break;
03106 case DAHDI_EVENT_NOALARM:
03107 pri_event_noalarm(pri, index, 0);
03108 break;
03109 default:
03110 break;
03111 }
03112 }
03113 #endif
03114
03115 #if defined(HAVE_PRI)
03116 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03117 {
03118 struct dahdi_pvt *p = pvt;
03119
03120 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03121 }
03122 #endif
03123
03124 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03136 {
03137 struct dahdi_pvt *p = pvt;
03138
03139 ast_copy_string(p->cid_num,
03140 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03141 sizeof(p->cid_num));
03142 ast_copy_string(p->cid_name,
03143 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03144 sizeof(p->cid_name));
03145 ast_copy_string(p->cid_subaddr,
03146 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03147 sizeof(p->cid_subaddr));
03148 p->cid_ton = caller->id.number.plan;
03149 p->callingpres = ast_party_id_presentation(&caller->id);
03150 if (caller->id.tag) {
03151 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03152 }
03153 ast_copy_string(p->cid_ani,
03154 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03155 sizeof(p->cid_ani));
03156 p->cid_ani2 = caller->ani2;
03157 }
03158 #endif
03159
03160 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171 static void my_set_dnid(void *pvt, const char *dnid)
03172 {
03173 struct dahdi_pvt *p = pvt;
03174
03175 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03176 }
03177 #endif
03178
03179 #if defined(HAVE_PRI)
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190 static void my_set_rdnis(void *pvt, const char *rdnis)
03191 {
03192 struct dahdi_pvt *p = pvt;
03193
03194 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03195 }
03196 #endif
03197
03198 #if defined(HAVE_PRI)
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03224 {
03225 char *dial;
03226 struct dahdi_pvt *pvt;
03227 AST_DECLARE_APP_ARGS(args,
03228 AST_APP_ARG(tech);
03229 AST_APP_ARG(group);
03230
03231
03232
03233 );
03234
03235 pvt = priv;
03236 dial = ast_strdupa(pvt->dialstring);
03237 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03238 if (!args.tech) {
03239 ast_copy_string(buf, pvt->dialstring, buf_size);
03240 return;
03241 }
03242 if (!args.group) {
03243
03244 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03245 return;
03246 }
03247 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03248
03249
03250 ast_copy_string(buf, pvt->dialstring, buf_size);
03251 return;
03252 }
03253
03254 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03255 }
03256 #endif
03257
03258 #if defined(HAVE_PRI)
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03271 {
03272 unsigned idx;
03273 unsigned num_b_chans;
03274 unsigned in_use;
03275 unsigned in_alarm;
03276 enum ast_device_state new_state;
03277
03278
03279 num_b_chans = 0;
03280 in_use = 0;
03281 in_alarm = 1;
03282 for (idx = pri->numchans; idx--;) {
03283 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03284
03285 ++num_b_chans;
03286 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03287 ++in_use;
03288 }
03289 if (!pri->pvts[idx]->inalarm) {
03290
03291 in_alarm = 0;
03292 }
03293 }
03294 }
03295
03296
03297 if (in_alarm) {
03298 new_state = AST_DEVICE_UNAVAILABLE;
03299 } else {
03300 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03301 }
03302 if (pri->congestion_devstate != new_state) {
03303 pri->congestion_devstate = new_state;
03304 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03305 }
03306 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03307
03308 if (in_alarm) {
03309 new_state = AST_DEVICE_UNAVAILABLE;
03310 } else if (!in_use) {
03311 new_state = AST_DEVICE_NOT_INUSE;
03312 } else if (!pri->user_busy_threshold) {
03313 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03314 } else {
03315 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03316 : AST_DEVICE_BUSY;
03317 }
03318 if (pri->threshold_devstate != new_state) {
03319 pri->threshold_devstate = new_state;
03320 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03321 }
03322 #endif
03323 }
03324 #endif
03325
03326 #if defined(HAVE_PRI)
03327
03328
03329
03330
03331
03332
03333
03334 static void my_module_ref(void)
03335 {
03336 ast_module_ref(ast_module_info->self);
03337 }
03338 #endif
03339
03340 #if defined(HAVE_PRI)
03341
03342
03343
03344
03345
03346
03347
03348 static void my_module_unref(void)
03349 {
03350 ast_module_unref(ast_module_info->self);
03351 }
03352 #endif
03353
03354 #if defined(HAVE_PRI)
03355 #if defined(HAVE_PRI_CALL_WAITING)
03356 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03357 #endif
03358 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03359
03360 static struct sig_pri_callback dahdi_pri_callbacks =
03361 {
03362 .handle_dchan_exception = my_handle_dchan_exception,
03363 .play_tone = my_pri_play_tone,
03364 .set_echocanceller = my_set_echocanceller,
03365 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03366 .lock_private = my_lock_private,
03367 .unlock_private = my_unlock_private,
03368 .new_ast_channel = my_new_pri_ast_channel,
03369 .fixup_chans = my_pri_fixup_chans,
03370 .set_alarm = my_set_alarm,
03371 .set_dialing = my_set_dialing,
03372 .set_outgoing = my_set_outgoing,
03373 .set_digital = my_set_digital,
03374 .set_callerid = my_set_callerid,
03375 .set_dnid = my_set_dnid,
03376 .set_rdnis = my_set_rdnis,
03377 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03378 #if defined(HAVE_PRI_CALL_WAITING)
03379 .init_config = my_pri_init_config,
03380 #endif
03381 .get_orig_dialstring = my_get_orig_dialstring,
03382 .make_cc_dialstring = my_pri_make_cc_dialstring,
03383 .update_span_devstate = dahdi_pri_update_span_devstate,
03384 .module_ref = my_module_ref,
03385 .module_unref = my_module_unref,
03386 .dial_digits = my_pri_dial_digits,
03387 .open_media = my_pri_ss7_open_media,
03388 .ami_channel_event = my_ami_channel_event,
03389 };
03390 #endif
03391
03392 #if defined(HAVE_SS7)
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03404 {
03405 int event;
03406
03407 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03408 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03409 linkset->span, which);
03410 return;
03411 }
03412 switch (event) {
03413 case DAHDI_EVENT_NONE:
03414 break;
03415 case DAHDI_EVENT_ALARM:
03416 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03417 event2str(event), event, linkset->span, which);
03418 sig_ss7_link_alarm(linkset, which);
03419 break;
03420 case DAHDI_EVENT_NOALARM:
03421 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03422 event2str(event), event, linkset->span, which);
03423 sig_ss7_link_noalarm(linkset, which);
03424 break;
03425 default:
03426 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03427 event2str(event), event, linkset->span, which);
03428 break;
03429 }
03430 }
03431 #endif
03432
03433 #if defined(HAVE_SS7)
03434 static void my_ss7_set_loopback(void *pvt, int enable)
03435 {
03436 struct dahdi_pvt *p = pvt;
03437
03438 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03439 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03440 strerror(errno));
03441 }
03442 }
03443 #endif
03444
03445 #if defined(HAVE_SS7)
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460 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)
03461 {
03462 struct dahdi_pvt *p = pvt;
03463 int audio;
03464 int newlaw;
03465
03466
03467 audio = 1;
03468 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03469 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03470 p->channel, audio, strerror(errno));
03471
03472 if (law != SIG_SS7_DEFLAW) {
03473 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03474 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03475 }
03476
03477 ast_copy_string(p->exten, exten, sizeof(p->exten));
03478
03479 newlaw = -1;
03480 switch (law) {
03481 case SIG_SS7_DEFLAW:
03482 newlaw = 0;
03483 break;
03484 case SIG_SS7_ALAW:
03485 newlaw = DAHDI_LAW_ALAW;
03486 break;
03487 case SIG_SS7_ULAW:
03488 newlaw = DAHDI_LAW_MULAW;
03489 break;
03490 }
03491 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03492 }
03493 #endif
03494
03495 #if defined(HAVE_SS7)
03496 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03497 {
03498 switch (tone) {
03499 case SIG_SS7_TONE_RINGTONE:
03500 return DAHDI_TONE_RINGTONE;
03501 case SIG_SS7_TONE_STUTTER:
03502 return DAHDI_TONE_STUTTER;
03503 case SIG_SS7_TONE_CONGESTION:
03504 return DAHDI_TONE_CONGESTION;
03505 case SIG_SS7_TONE_DIALTONE:
03506 return DAHDI_TONE_DIALTONE;
03507 case SIG_SS7_TONE_DIALRECALL:
03508 return DAHDI_TONE_DIALRECALL;
03509 case SIG_SS7_TONE_INFO:
03510 return DAHDI_TONE_INFO;
03511 case SIG_SS7_TONE_BUSY:
03512 return DAHDI_TONE_BUSY;
03513 default:
03514 return -1;
03515 }
03516 }
03517 #endif
03518
03519 #if defined(HAVE_SS7)
03520 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03521 {
03522 struct dahdi_pvt *p = pvt;
03523
03524 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03525 }
03526 #endif
03527
03528 #if defined(HAVE_SS7)
03529 static struct sig_ss7_callback dahdi_ss7_callbacks =
03530 {
03531 .lock_private = my_lock_private,
03532 .unlock_private = my_unlock_private,
03533
03534 .set_echocanceller = my_set_echocanceller,
03535 .set_loopback = my_ss7_set_loopback,
03536
03537 .new_ast_channel = my_new_ss7_ast_channel,
03538 .play_tone = my_ss7_play_tone,
03539
03540 .handle_link_exception = my_handle_link_exception,
03541 .set_alarm = my_set_alarm,
03542 .set_dialing = my_set_dialing,
03543 .set_outgoing = my_set_outgoing,
03544 .set_digital = my_set_digital,
03545 .set_inservice = my_set_inservice,
03546 .set_locallyblocked = my_set_locallyblocked,
03547 .set_remotelyblocked = my_set_remotelyblocked,
03548 .set_callerid = my_set_callerid,
03549 .set_dnid = my_set_dnid,
03550 .open_media = my_pri_ss7_open_media,
03551 };
03552 #endif
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572 static void notify_message(char *mailbox_full, int thereornot)
03573 {
03574 char s[sizeof(mwimonitornotify) + 80];
03575 struct ast_event *event;
03576 char *mailbox, *context;
03577
03578
03579 context = mailbox = ast_strdupa(mailbox_full);
03580 strsep(&context, "@");
03581 if (ast_strlen_zero(context))
03582 context = "default";
03583
03584 if (!(event = ast_event_new(AST_EVENT_MWI,
03585 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03586 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03587 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03588 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03589 AST_EVENT_IE_END))) {
03590 return;
03591 }
03592
03593 ast_event_queue_and_cache(event);
03594
03595 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03596 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03597 ast_safe_system(s);
03598 }
03599 }
03600
03601 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03602 {
03603 struct dahdi_pvt *p = pvt;
03604
03605 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03606 return;
03607
03608 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03609 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03610 notify_message(p->mailbox, 1);
03611 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03612 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03613 notify_message(p->mailbox, 0);
03614 }
03615
03616
03617 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03618 ast_hangup(chan);
03619 return;
03620 }
03621 }
03622
03623 static int my_have_progressdetect(void *pvt)
03624 {
03625 struct dahdi_pvt *p = pvt;
03626
03627 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03628 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03629 return 1;
03630 } else {
03631
03632 return 0;
03633 }
03634 }
03635
03636 static struct analog_callback dahdi_analog_callbacks =
03637 {
03638 .play_tone = my_play_tone,
03639 .get_event = my_get_event,
03640 .wait_event = my_wait_event,
03641 .is_off_hook = my_is_off_hook,
03642 .set_echocanceller = my_set_echocanceller,
03643 .ring = my_ring,
03644 .flash = my_flash,
03645 .off_hook = my_off_hook,
03646 .dial_digits = my_dial_digits,
03647 .train_echocanceller = my_train_echocanceller,
03648 .on_hook = my_on_hook,
03649 .is_dialing = my_is_dialing,
03650 .allocate_sub = my_allocate_sub,
03651 .unallocate_sub = my_unallocate_sub,
03652 .swap_subs = my_swap_subchannels,
03653 .has_voicemail = my_has_voicemail,
03654 .check_for_conference = my_check_for_conference,
03655 .conf_add = my_conf_add,
03656 .conf_del = my_conf_del,
03657 .complete_conference_update = my_complete_conference_update,
03658 .start = my_start,
03659 .all_subchannels_hungup = my_all_subchannels_hungup,
03660 .lock_private = my_lock_private,
03661 .unlock_private = my_unlock_private,
03662 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03663 .handle_dtmf = my_handle_dtmf,
03664 .wink = my_wink,
03665 .new_ast_channel = my_new_analog_ast_channel,
03666 .dsp_set_digitmode = my_dsp_set_digitmode,
03667 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03668 .send_callerid = my_send_callerid,
03669 .callwait = my_callwait,
03670 .stop_callwait = my_stop_callwait,
03671 .get_callerid = my_get_callerid,
03672 .start_cid_detect = my_start_cid_detect,
03673 .stop_cid_detect = my_stop_cid_detect,
03674 .handle_notify_message = my_handle_notify_message,
03675 .increase_ss_count = my_increase_ss_count,
03676 .decrease_ss_count = my_decrease_ss_count,
03677 .distinctive_ring = my_distinctive_ring,
03678 .set_linear_mode = my_set_linear_mode,
03679 .set_inthreeway = my_set_inthreeway,
03680 .get_and_handle_alarms = my_get_and_handle_alarms,
03681 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03682 .get_sub_fd = my_get_sub_fd,
03683 .set_cadence = my_set_cadence,
03684 .set_alarm = my_set_alarm,
03685 .set_dialing = my_set_dialing,
03686 .set_outgoing = my_set_outgoing,
03687 .set_ringtimeout = my_set_ringtimeout,
03688 .set_waitingfordt = my_set_waitingfordt,
03689 .check_waitingfordt = my_check_waitingfordt,
03690 .set_confirmanswer = my_set_confirmanswer,
03691 .check_confirmanswer = my_check_confirmanswer,
03692 .set_callwaiting = my_set_callwaiting,
03693 .cancel_cidspill = my_cancel_cidspill,
03694 .confmute = my_confmute,
03695 .set_pulsedial = my_set_pulsedial,
03696 .set_new_owner = my_set_new_owner,
03697 .get_orig_dialstring = my_get_orig_dialstring,
03698 .set_needringing = my_set_needringing,
03699 .set_polarity = my_set_polarity,
03700 .start_polarityswitch = my_start_polarityswitch,
03701 .answer_polarityswitch = my_answer_polarityswitch,
03702 .hangup_polarityswitch = my_hangup_polarityswitch,
03703 .have_progressdetect = my_have_progressdetect,
03704 };
03705
03706
03707 static struct dahdi_pvt *round_robin[32];
03708
03709 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03710 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03711 {
03712 int res;
03713 if (p->subs[SUB_REAL].owner == ast)
03714 res = 0;
03715 else if (p->subs[SUB_CALLWAIT].owner == ast)
03716 res = 1;
03717 else if (p->subs[SUB_THREEWAY].owner == ast)
03718 res = 2;
03719 else {
03720 res = -1;
03721 if (!nullok)
03722 ast_log(LOG_WARNING,
03723 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03724 ast ? ast->name : "", p->channel, fname, line);
03725 }
03726 return res;
03727 }
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03745 {
03746 for (;;) {
03747 if (!pvt->subs[sub_idx].owner) {
03748
03749 break;
03750 }
03751 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03752
03753 break;
03754 }
03755
03756 DEADLOCK_AVOIDANCE(&pvt->lock);
03757 }
03758 }
03759
03760 static void wakeup_sub(struct dahdi_pvt *p, int a)
03761 {
03762 dahdi_lock_sub_owner(p, a);
03763 if (p->subs[a].owner) {
03764 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03765 ast_channel_unlock(p->subs[a].owner);
03766 }
03767 }
03768
03769 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03770 {
03771 for (;;) {
03772 if (p->owner) {
03773 if (ast_channel_trylock(p->owner)) {
03774 DEADLOCK_AVOIDANCE(&p->lock);
03775 } else {
03776 ast_queue_frame(p->owner, f);
03777 ast_channel_unlock(p->owner);
03778 break;
03779 }
03780 } else
03781 break;
03782 }
03783 }
03784
03785 static void handle_clear_alarms(struct dahdi_pvt *p)
03786 {
03787 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03788 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03789 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03790 }
03791 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03792 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03793 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03794 }
03795 }
03796
03797 #ifdef HAVE_OPENR2
03798
03799 static int dahdi_r2_answer(struct dahdi_pvt *p)
03800 {
03801 int res = 0;
03802
03803
03804
03805 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03806 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03807 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03808 if (!double_answer) {
03809
03810
03811 res = openr2_chan_answer_call(p->r2chan);
03812 } else if (wants_double_answer) {
03813 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03814 } else {
03815 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03816 }
03817 #else
03818 res = openr2_chan_answer_call(p->r2chan);
03819 #endif
03820 return res;
03821 }
03822
03823
03824
03825
03826 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03827 {
03828 openr2_calling_party_category_t cat;
03829 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03830 struct dahdi_pvt *p = c->tech_pvt;
03831 if (ast_strlen_zero(catstr)) {
03832 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03833 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03834 return p->mfcr2_category;
03835 }
03836 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03837 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03838 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03839 return p->mfcr2_category;
03840 }
03841 ast_debug(1, "Using category %s\n", catstr);
03842 return cat;
03843 }
03844
03845 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03846 {
03847 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03848 ast_mutex_lock(&p->lock);
03849 if (p->mfcr2call) {
03850 ast_mutex_unlock(&p->lock);
03851
03852
03853
03854
03855
03856 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03857 return;
03858 }
03859 p->mfcr2call = 1;
03860
03861 p->cid_name[0] = '\0';
03862 p->cid_num[0] = '\0';
03863 p->cid_subaddr[0] = '\0';
03864 p->rdnis[0] = '\0';
03865 p->exten[0] = '\0';
03866 p->mfcr2_ani_index = '\0';
03867 p->mfcr2_dnis_index = '\0';
03868 p->mfcr2_dnis_matched = 0;
03869 p->mfcr2_answer_pending = 0;
03870 p->mfcr2_call_accepted = 0;
03871 ast_mutex_unlock(&p->lock);
03872 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03873 }
03874
03875 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03876 {
03877 int res;
03878 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03879 ast_mutex_lock(&p->lock);
03880 p->inalarm = alarm ? 1 : 0;
03881 if (p->inalarm) {
03882 res = get_alarms(p);
03883 handle_alarms(p, res);
03884 } else {
03885 handle_clear_alarms(p);
03886 }
03887 ast_mutex_unlock(&p->lock);
03888 }
03889
03890 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03891 {
03892 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03893 }
03894
03895 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03896 {
03897 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03898 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03899 if (p->owner) {
03900 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03901 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03902 }
03903 ast_mutex_lock(&p->lock);
03904 p->mfcr2call = 0;
03905 ast_mutex_unlock(&p->lock);
03906 }
03907
03908 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03909 {
03910 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03911 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03912 p->channel, openr2_proto_get_disconnect_string(cause));
03913
03914 openr2_chan_set_idle(p->r2chan);
03915 ast_mutex_lock(&p->lock);
03916 p->mfcr2call = 0;
03917 ast_mutex_unlock(&p->lock);
03918 }
03919 }
03920
03921 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03922 {
03923 struct dahdi_pvt *p;
03924 struct ast_channel *c;
03925 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03926 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03927 openr2_proto_get_category_string(category));
03928 p = openr2_chan_get_client_data(r2chan);
03929
03930 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03931 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03932 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03933 return;
03934 }
03935 ast_mutex_lock(&p->lock);
03936 p->mfcr2_recvd_category = category;
03937
03938 if (!p->use_callerid) {
03939 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03940 p->cid_num[0] = 0;
03941 p->cid_name[0] = 0;
03942 }
03943
03944 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03945 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03946 p->exten[0] = 's';
03947 p->exten[1] = 0;
03948 }
03949 ast_mutex_unlock(&p->lock);
03950 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03951 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03952 p->channel, p->exten, p->context);
03953 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03954 return;
03955 }
03956 if (!p->mfcr2_accept_on_offer) {
03957
03958 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03959 if (c) {
03960
03961
03962
03963 return;
03964 }
03965 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03966 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03967 } else if (p->mfcr2_charge_calls) {
03968 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03969 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03970 } else {
03971 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03972 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03973 }
03974 }
03975
03976 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03977 {
03978 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03979 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03980 ast_mutex_lock(&p->lock);
03981 p->mfcr2call = 0;
03982 ast_mutex_unlock(&p->lock);
03983 }
03984
03985 static void dahdi_enable_ec(struct dahdi_pvt *p);
03986 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03987 {
03988 struct dahdi_pvt *p = NULL;
03989 struct ast_channel *c = NULL;
03990 p = openr2_chan_get_client_data(r2chan);
03991 dahdi_enable_ec(p);
03992 p->mfcr2_call_accepted = 1;
03993
03994 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03995 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03996
03997
03998
03999
04000 if (!p->mfcr2_accept_on_offer) {
04001 openr2_chan_disable_read(r2chan);
04002 if (p->mfcr2_answer_pending) {
04003 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04004 dahdi_r2_answer(p);
04005 }
04006 return;
04007 }
04008 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04009 if (c) {
04010
04011
04012 openr2_chan_disable_read(r2chan);
04013 return;
04014 }
04015 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04016
04017 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04018 return;
04019 }
04020
04021 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04022 p->subs[SUB_REAL].needringing = 1;
04023 p->dialing = 0;
04024
04025 openr2_chan_disable_read(r2chan);
04026 }
04027
04028 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04029 {
04030 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04031 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04032 p->subs[SUB_REAL].needanswer = 1;
04033 }
04034
04035 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04036 {
04037
04038 }
04039
04040 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04041 {
04042 switch (cause) {
04043 case OR2_CAUSE_BUSY_NUMBER:
04044 return AST_CAUSE_BUSY;
04045 case OR2_CAUSE_NETWORK_CONGESTION:
04046 return AST_CAUSE_CONGESTION;
04047 case OR2_CAUSE_OUT_OF_ORDER:
04048 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04049 case OR2_CAUSE_UNALLOCATED_NUMBER:
04050 return AST_CAUSE_UNREGISTERED;
04051 case OR2_CAUSE_NO_ANSWER:
04052 return AST_CAUSE_NO_ANSWER;
04053 case OR2_CAUSE_NORMAL_CLEARING:
04054 return AST_CAUSE_NORMAL_CLEARING;
04055 case OR2_CAUSE_UNSPECIFIED:
04056 default:
04057 return AST_CAUSE_NOTDEFINED;
04058 }
04059 }
04060
04061 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04062 {
04063 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04064 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04065 ast_mutex_lock(&p->lock);
04066 if (!p->owner) {
04067 ast_mutex_unlock(&p->lock);
04068
04069 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04070 return;
04071 }
04072
04073
04074 if (p->owner->_state == AST_STATE_UP) {
04075 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04076 ast_mutex_unlock(&p->lock);
04077 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04078
04079 switch (cause) {
04080 case OR2_CAUSE_BUSY_NUMBER:
04081 p->subs[SUB_REAL].needbusy = 1;
04082 break;
04083 case OR2_CAUSE_NETWORK_CONGESTION:
04084 case OR2_CAUSE_OUT_OF_ORDER:
04085 case OR2_CAUSE_UNALLOCATED_NUMBER:
04086 case OR2_CAUSE_NO_ANSWER:
04087 case OR2_CAUSE_UNSPECIFIED:
04088 case OR2_CAUSE_NORMAL_CLEARING:
04089 p->subs[SUB_REAL].needcongestion = 1;
04090 break;
04091 default:
04092 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04093 }
04094 ast_mutex_unlock(&p->lock);
04095 } else {
04096 ast_mutex_unlock(&p->lock);
04097
04098
04099 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04100 }
04101 }
04102
04103 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04104 {
04105 switch (level) {
04106 case OR2_LOG_NOTICE:
04107 ast_verbose("%s", logmessage);
04108 break;
04109 case OR2_LOG_WARNING:
04110 ast_log(LOG_WARNING, "%s", logmessage);
04111 break;
04112 case OR2_LOG_ERROR:
04113 ast_log(LOG_ERROR, "%s", logmessage);
04114 break;
04115 case OR2_LOG_STACK_TRACE:
04116 case OR2_LOG_MF_TRACE:
04117 case OR2_LOG_CAS_TRACE:
04118 case OR2_LOG_DEBUG:
04119 case OR2_LOG_EX_DEBUG:
04120 ast_log(LOG_DEBUG, "%s", logmessage);
04121 break;
04122 default:
04123 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04124 ast_log(LOG_DEBUG, "%s", logmessage);
04125 break;
04126 }
04127 }
04128
04129 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04130 {
04131 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04132 ast_mutex_lock(&p->lock);
04133 p->remotelyblocked = 1;
04134 ast_mutex_unlock(&p->lock);
04135 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04136 }
04137
04138 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04139 {
04140 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04141 ast_mutex_lock(&p->lock);
04142 p->remotelyblocked = 0;
04143 ast_mutex_unlock(&p->lock);
04144 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04145 }
04146
04147 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04148 __attribute__((format (printf, 3, 0)));
04149 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04150 {
04151 #define CONTEXT_TAG "Context - "
04152 char logmsg[256];
04153 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04154 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04155 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04156 dahdi_r2_write_log(level, completemsg);
04157 #undef CONTEXT_TAG
04158 }
04159
04160 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04161 __attribute__((format (printf, 3, 0)));
04162 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04163 {
04164 #define CHAN_TAG "Chan "
04165 char logmsg[256];
04166 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04167 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04168 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04169 dahdi_r2_write_log(level, completemsg);
04170 }
04171
04172 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04173 {
04174 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04175
04176 if (p->immediate) {
04177 return 0;
04178 }
04179 p->exten[p->mfcr2_dnis_index] = digit;
04180 p->rdnis[p->mfcr2_dnis_index] = digit;
04181 p->mfcr2_dnis_index++;
04182 p->exten[p->mfcr2_dnis_index] = 0;
04183 p->rdnis[p->mfcr2_dnis_index] = 0;
04184
04185 if ((p->mfcr2_dnis_matched ||
04186 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04187 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04188 return 0;
04189 }
04190
04191 return 1;
04192 }
04193
04194 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04195 {
04196 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04197 p->cid_num[p->mfcr2_ani_index] = digit;
04198 p->cid_name[p->mfcr2_ani_index] = digit;
04199 p->mfcr2_ani_index++;
04200 p->cid_num[p->mfcr2_ani_index] = 0;
04201 p->cid_name[p->mfcr2_ani_index] = 0;
04202 }
04203
04204 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04205 {
04206 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04207 }
04208
04209 static openr2_event_interface_t dahdi_r2_event_iface = {
04210 .on_call_init = dahdi_r2_on_call_init,
04211 .on_call_offered = dahdi_r2_on_call_offered,
04212 .on_call_accepted = dahdi_r2_on_call_accepted,
04213 .on_call_answered = dahdi_r2_on_call_answered,
04214 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04215 .on_call_end = dahdi_r2_on_call_end,
04216 .on_call_read = dahdi_r2_on_call_read,
04217 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04218 .on_os_error = dahdi_r2_on_os_error,
04219 .on_protocol_error = dahdi_r2_on_protocol_error,
04220 .on_line_blocked = dahdi_r2_on_line_blocked,
04221 .on_line_idle = dahdi_r2_on_line_idle,
04222
04223 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04224 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04225 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04226
04227 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04228 };
04229
04230 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04231 {
04232 return AST_ALAW(sample);
04233 }
04234
04235 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04236 {
04237 return AST_LIN2A(sample);
04238 }
04239
04240 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04241 dahdi_r2_alaw_to_linear,
04242 dahdi_r2_linear_to_alaw
04243 };
04244
04245 #endif
04246
04247 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04248 {
04249 int tchan;
04250 int tinthreeway;
04251 struct ast_channel *towner;
04252
04253 ast_debug(1, "Swapping %d and %d\n", a, b);
04254
04255 tchan = p->subs[a].chan;
04256 towner = p->subs[a].owner;
04257 tinthreeway = p->subs[a].inthreeway;
04258
04259 p->subs[a].chan = p->subs[b].chan;
04260 p->subs[a].owner = p->subs[b].owner;
04261 p->subs[a].inthreeway = p->subs[b].inthreeway;
04262
04263 p->subs[b].chan = tchan;
04264 p->subs[b].owner = towner;
04265 p->subs[b].inthreeway = tinthreeway;
04266
04267 if (p->subs[a].owner)
04268 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04269 if (p->subs[b].owner)
04270 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04271 wakeup_sub(p, a);
04272 wakeup_sub(p, b);
04273 }
04274
04275 static int dahdi_open(char *fn)
04276 {
04277 int fd;
04278 int isnum;
04279 int chan = 0;
04280 int bs;
04281 int x;
04282 isnum = 1;
04283 for (x = 0; x < strlen(fn); x++) {
04284 if (!isdigit(fn[x])) {
04285 isnum = 0;
04286 break;
04287 }
04288 }
04289 if (isnum) {
04290 chan = atoi(fn);
04291 if (chan < 1) {
04292 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04293 return -1;
04294 }
04295 fn = "/dev/dahdi/channel";
04296 }
04297 fd = open(fn, O_RDWR | O_NONBLOCK);
04298 if (fd < 0) {
04299 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04300 return -1;
04301 }
04302 if (chan) {
04303 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04304 x = errno;
04305 close(fd);
04306 errno = x;
04307 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04308 return -1;
04309 }
04310 }
04311 bs = READ_SIZE;
04312 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04313 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04314 x = errno;
04315 close(fd);
04316 errno = x;
04317 return -1;
04318 }
04319 return fd;
04320 }
04321
04322 static void dahdi_close(int fd)
04323 {
04324 if (fd > 0)
04325 close(fd);
04326 }
04327
04328 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04329 {
04330 dahdi_close(chan_pvt->subs[sub_num].dfd);
04331 chan_pvt->subs[sub_num].dfd = -1;
04332 }
04333
04334 #if defined(HAVE_PRI)
04335 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04336 {
04337 dahdi_close(pri->pri.fds[fd_num]);
04338 pri->pri.fds[fd_num] = -1;
04339 }
04340 #endif
04341
04342 #if defined(HAVE_SS7)
04343 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04344 {
04345 dahdi_close(ss7->ss7.fds[fd_num]);
04346 ss7->ss7.fds[fd_num] = -1;
04347 }
04348 #endif
04349
04350 static int dahdi_setlinear(int dfd, int linear)
04351 {
04352 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04353 }
04354
04355
04356 static int alloc_sub(struct dahdi_pvt *p, int x)
04357 {
04358 struct dahdi_bufferinfo bi;
04359 int res;
04360 if (p->subs[x].dfd >= 0) {
04361 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04362 return -1;
04363 }
04364
04365 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04366 if (p->subs[x].dfd <= -1) {
04367 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04368 return -1;
04369 }
04370
04371 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04372 if (!res) {
04373 bi.txbufpolicy = p->buf_policy;
04374 bi.rxbufpolicy = p->buf_policy;
04375 bi.numbufs = p->buf_no;
04376 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04377 if (res < 0) {
04378 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04379 }
04380 } else
04381 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04382
04383 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04384 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04385 dahdi_close_sub(p, x);
04386 p->subs[x].dfd = -1;
04387 return -1;
04388 }
04389 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04390 return 0;
04391 }
04392
04393 static int unalloc_sub(struct dahdi_pvt *p, int x)
04394 {
04395 if (!x) {
04396 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04397 return -1;
04398 }
04399 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04400 dahdi_close_sub(p, x);
04401 p->subs[x].linear = 0;
04402 p->subs[x].chan = 0;
04403 p->subs[x].owner = NULL;
04404 p->subs[x].inthreeway = 0;
04405 p->polarity = POLARITY_IDLE;
04406 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04407 return 0;
04408 }
04409
04410 static int digit_to_dtmfindex(char digit)
04411 {
04412 if (isdigit(digit))
04413 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04414 else if (digit >= 'A' && digit <= 'D')
04415 return DAHDI_TONE_DTMF_A + (digit - 'A');
04416 else if (digit >= 'a' && digit <= 'd')
04417 return DAHDI_TONE_DTMF_A + (digit - 'a');
04418 else if (digit == '*')
04419 return DAHDI_TONE_DTMF_s;
04420 else if (digit == '#')
04421 return DAHDI_TONE_DTMF_p;
04422 else
04423 return -1;
04424 }
04425
04426 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04427 {
04428 struct dahdi_pvt *pvt;
04429 int idx;
04430 int dtmf = -1;
04431 int res;
04432
04433 pvt = chan->tech_pvt;
04434
04435 ast_mutex_lock(&pvt->lock);
04436
04437 idx = dahdi_get_index(chan, pvt, 0);
04438
04439 if ((idx != SUB_REAL) || !pvt->owner)
04440 goto out;
04441
04442 #ifdef HAVE_PRI
04443 switch (pvt->sig) {
04444 case SIG_PRI_LIB_HANDLE_CASES:
04445 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04446 if (!res)
04447 goto out;
04448 break;
04449 default:
04450 break;
04451 }
04452 #endif
04453 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04454 goto out;
04455
04456 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04457 struct dahdi_dialoperation zo = {
04458 .op = DAHDI_DIAL_OP_APPEND,
04459 };
04460
04461 zo.dialstr[0] = 'T';
04462 zo.dialstr[1] = digit;
04463 zo.dialstr[2] = '\0';
04464 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04465 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04466 chan->name, digit, strerror(errno));
04467 else
04468 pvt->dialing = 1;
04469 } else {
04470 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04471 chan->name, digit);
04472 pvt->dialing = 1;
04473 pvt->begindigit = digit;
04474 }
04475
04476 out:
04477 ast_mutex_unlock(&pvt->lock);
04478
04479 return 0;
04480 }
04481
04482 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04483 {
04484 struct dahdi_pvt *pvt;
04485 int res = 0;
04486 int idx;
04487 int x;
04488
04489 pvt = chan->tech_pvt;
04490
04491 ast_mutex_lock(&pvt->lock);
04492
04493 idx = dahdi_get_index(chan, pvt, 0);
04494
04495 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04496 goto out;
04497
04498 #ifdef HAVE_PRI
04499
04500 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04501 goto out;
04502 }
04503 #endif
04504
04505 if (pvt->begindigit) {
04506 x = -1;
04507 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04508 chan->name, digit);
04509 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04510 pvt->dialing = 0;
04511 pvt->begindigit = 0;
04512 }
04513
04514 out:
04515 ast_mutex_unlock(&pvt->lock);
04516
04517 return res;
04518 }
04519
04520 static const char * const events[] = {
04521 "No event",
04522 "On hook",
04523 "Ring/Answered",
04524 "Wink/Flash",
04525 "Alarm",
04526 "No more alarm",
04527 "HDLC Abort",
04528 "HDLC Overrun",
04529 "HDLC Bad FCS",
04530 "Dial Complete",
04531 "Ringer On",
04532 "Ringer Off",
04533 "Hook Transition Complete",
04534 "Bits Changed",
04535 "Pulse Start",
04536 "Timer Expired",
04537 "Timer Ping",
04538 "Polarity Reversal",
04539 "Ring Begin",
04540 };
04541
04542 static struct {
04543 int alarm;
04544 char *name;
04545 } alarms[] = {
04546 { DAHDI_ALARM_RED, "Red Alarm" },
04547 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04548 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04549 { DAHDI_ALARM_RECOVER, "Recovering" },
04550 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04551 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04552 { DAHDI_ALARM_NONE, "None" },
04553 };
04554
04555 static char *alarm2str(int alm)
04556 {
04557 int x;
04558 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04559 if (alarms[x].alarm & alm)
04560 return alarms[x].name;
04561 }
04562 return alm ? "Unknown Alarm" : "No Alarm";
04563 }
04564
04565 static const char *event2str(int event)
04566 {
04567 static char buf[256];
04568 if ((event < (ARRAY_LEN(events))) && (event > -1))
04569 return events[event];
04570 sprintf(buf, "Event %d", event);
04571 return buf;
04572 }
04573
04574 static char *dahdi_sig2str(int sig)
04575 {
04576 static char buf[256];
04577 switch (sig) {
04578 case SIG_EM:
04579 return "E & M Immediate";
04580 case SIG_EMWINK:
04581 return "E & M Wink";
04582 case SIG_EM_E1:
04583 return "E & M E1";
04584 case SIG_FEATD:
04585 return "Feature Group D (DTMF)";
04586 case SIG_FEATDMF:
04587 return "Feature Group D (MF)";
04588 case SIG_FEATDMF_TA:
04589 return "Feature Groud D (MF) Tandem Access";
04590 case SIG_FEATB:
04591 return "Feature Group B (MF)";
04592 case SIG_E911:
04593 return "E911 (MF)";
04594 case SIG_FGC_CAMA:
04595 return "FGC/CAMA (Dialpulse)";
04596 case SIG_FGC_CAMAMF:
04597 return "FGC/CAMA (MF)";
04598 case SIG_FXSLS:
04599 return "FXS Loopstart";
04600 case SIG_FXSGS:
04601 return "FXS Groundstart";
04602 case SIG_FXSKS:
04603 return "FXS Kewlstart";
04604 case SIG_FXOLS:
04605 return "FXO Loopstart";
04606 case SIG_FXOGS:
04607 return "FXO Groundstart";
04608 case SIG_FXOKS:
04609 return "FXO Kewlstart";
04610 case SIG_PRI:
04611 return "ISDN PRI";
04612 case SIG_BRI:
04613 return "ISDN BRI Point to Point";
04614 case SIG_BRI_PTMP:
04615 return "ISDN BRI Point to MultiPoint";
04616 case SIG_SS7:
04617 return "SS7";
04618 case SIG_MFCR2:
04619 return "MFC/R2";
04620 case SIG_SF:
04621 return "SF (Tone) Immediate";
04622 case SIG_SFWINK:
04623 return "SF (Tone) Wink";
04624 case SIG_SF_FEATD:
04625 return "SF (Tone) with Feature Group D (DTMF)";
04626 case SIG_SF_FEATDMF:
04627 return "SF (Tone) with Feature Group D (MF)";
04628 case SIG_SF_FEATB:
04629 return "SF (Tone) with Feature Group B (MF)";
04630 case 0:
04631 return "Pseudo";
04632 default:
04633 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04634 return buf;
04635 }
04636 }
04637
04638 #define sig2str dahdi_sig2str
04639
04640 static int analog_lib_handles(int signalling, int radio, int oprmode)
04641 {
04642 switch (signalling) {
04643 case SIG_FXOLS:
04644 case SIG_FXOGS:
04645 case SIG_FXOKS:
04646 case SIG_FXSLS:
04647 case SIG_FXSGS:
04648 case SIG_FXSKS:
04649 case SIG_EMWINK:
04650 case SIG_EM:
04651 case SIG_EM_E1:
04652 case SIG_FEATD:
04653 case SIG_FEATDMF:
04654 case SIG_E911:
04655 case SIG_FGC_CAMA:
04656 case SIG_FGC_CAMAMF:
04657 case SIG_FEATB:
04658 case SIG_SFWINK:
04659 case SIG_SF:
04660 case SIG_SF_FEATD:
04661 case SIG_SF_FEATDMF:
04662 case SIG_FEATDMF_TA:
04663 case SIG_SF_FEATB:
04664 break;
04665 default:
04666
04667 return 0;
04668 }
04669
04670 if (radio)
04671 return 0;
04672
04673 if (oprmode)
04674 return 0;
04675
04676 return 1;
04677 }
04678
04679 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04680 {
04681
04682
04683 struct dahdi_confinfo zi;
04684
04685 memset(&zi, 0, sizeof(zi));
04686 zi.chan = 0;
04687
04688 if (slavechannel > 0) {
04689
04690 zi.confmode = DAHDI_CONF_DIGITALMON;
04691 zi.confno = slavechannel;
04692 } else {
04693 if (!idx) {
04694
04695 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04696 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04697 } else
04698 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04699 zi.confno = p->confno;
04700 }
04701 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04702 return 0;
04703 if (c->dfd < 0)
04704 return 0;
04705 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04706 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04707 return -1;
04708 }
04709 if (slavechannel < 1) {
04710 p->confno = zi.confno;
04711 }
04712 c->curconf = zi;
04713 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04714 return 0;
04715 }
04716
04717 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04718 {
04719
04720 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04721 return 1;
04722
04723 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04724 return 1;
04725 return 0;
04726 }
04727
04728 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04729 {
04730 struct dahdi_confinfo zi;
04731 if (
04732 (c->dfd < 0) ||
04733
04734 !isourconf(p, c)
04735
04736 ) return 0;
04737 memset(&zi, 0, sizeof(zi));
04738 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04739 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04740 return -1;
04741 }
04742 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04743 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04744 return 0;
04745 }
04746
04747 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04748 {
04749 int x;
04750 int useslavenative;
04751 struct dahdi_pvt *slave = NULL;
04752
04753 useslavenative = 1;
04754
04755 for (x = 0; x < 3; x++) {
04756
04757
04758 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04759 useslavenative = 0;
04760 }
04761
04762
04763 if (useslavenative) {
04764 for (x = 0; x < MAX_SLAVES; x++) {
04765 if (p->slaves[x]) {
04766 if (slave) {
04767
04768
04769 slave = NULL;
04770 useslavenative = 0;
04771 break;
04772 } else {
04773
04774 slave = p->slaves[x];
04775 }
04776 }
04777 }
04778 }
04779
04780 if (!slave)
04781 useslavenative = 0;
04782 else if (slave->law != p->law) {
04783 useslavenative = 0;
04784 slave = NULL;
04785 }
04786 if (out)
04787 *out = slave;
04788 return useslavenative;
04789 }
04790
04791 static int reset_conf(struct dahdi_pvt *p)
04792 {
04793 p->confno = -1;
04794 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04795 if (p->subs[SUB_REAL].dfd > -1) {
04796 struct dahdi_confinfo zi;
04797
04798 memset(&zi, 0, sizeof(zi));
04799 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04800 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04801 }
04802 return 0;
04803 }
04804
04805 static int update_conf(struct dahdi_pvt *p)
04806 {
04807 int needconf = 0;
04808 int x;
04809 int useslavenative;
04810 struct dahdi_pvt *slave = NULL;
04811
04812 useslavenative = isslavenative(p, &slave);
04813
04814 for (x = 0; x < 3; x++) {
04815
04816 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04817 conf_add(p, &p->subs[x], x, 0);
04818 needconf++;
04819 } else {
04820 conf_del(p, &p->subs[x], x);
04821 }
04822 }
04823
04824
04825 for (x = 0; x < MAX_SLAVES; x++) {
04826 if (p->slaves[x]) {
04827 if (useslavenative)
04828 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04829 else {
04830 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04831 needconf++;
04832 }
04833 }
04834 }
04835
04836 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04837 if (useslavenative)
04838 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04839 else {
04840 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04841 needconf++;
04842 }
04843 }
04844
04845 if (p->master) {
04846 if (isslavenative(p->master, NULL)) {
04847 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04848 } else {
04849 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04850 }
04851 }
04852 if (!needconf) {
04853
04854
04855 p->confno = -1;
04856 }
04857 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04858 return 0;
04859 }
04860
04861 static void dahdi_enable_ec(struct dahdi_pvt *p)
04862 {
04863 int res;
04864 if (!p)
04865 return;
04866 if (p->echocanon) {
04867 ast_debug(1, "Echo cancellation already on\n");
04868 return;
04869 }
04870 if (p->digital) {
04871 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04872 return;
04873 }
04874 if (p->echocancel.head.tap_length) {
04875 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04876 switch (p->sig) {
04877 #if defined(HAVE_PRI)
04878 case SIG_PRI_LIB_HANDLE_CASES:
04879 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04880
04881
04882
04883
04884 return;
04885 }
04886
04887 #endif
04888 #if defined(HAVE_SS7)
04889 case SIG_SS7:
04890 #endif
04891 {
04892 int x = 1;
04893
04894 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04895 if (res)
04896 ast_log(LOG_WARNING,
04897 "Unable to enable audio mode on channel %d (%s)\n",
04898 p->channel, strerror(errno));
04899 }
04900 break;
04901 default:
04902 break;
04903 }
04904 #endif
04905 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04906 if (res) {
04907 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04908 } else {
04909 p->echocanon = 1;
04910 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04911 }
04912 } else
04913 ast_debug(1, "No echo cancellation requested\n");
04914 }
04915
04916 static void dahdi_train_ec(struct dahdi_pvt *p)
04917 {
04918 int x;
04919 int res;
04920
04921 if (p && p->echocanon && p->echotraining) {
04922 x = p->echotraining;
04923 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04924 if (res)
04925 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04926 else
04927 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04928 } else {
04929 ast_debug(1, "No echo training requested\n");
04930 }
04931 }
04932
04933 static void dahdi_disable_ec(struct dahdi_pvt *p)
04934 {
04935 int res;
04936
04937 if (p->echocanon) {
04938 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04939
04940 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04941
04942 if (res)
04943 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04944 else
04945 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04946 }
04947
04948 p->echocanon = 0;
04949 }
04950
04951
04952 static int drc_sample(int sample, float drc)
04953 {
04954 float neg;
04955 float shallow, steep;
04956 float max = SHRT_MAX;
04957
04958 neg = (sample < 0 ? -1 : 1);
04959 steep = drc*sample;
04960 shallow = neg*(max-max/drc)+(float)sample/drc;
04961 if (abs(steep) < abs(shallow)) {
04962 sample = steep;
04963 }
04964 else {
04965 sample = shallow;
04966 }
04967
04968 return sample;
04969 }
04970
04971
04972 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04973 {
04974 int j;
04975 int k;
04976
04977 float linear_gain = pow(10.0, gain / 20.0);
04978
04979 switch (law) {
04980 case DAHDI_LAW_ALAW:
04981 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04982 if (gain || drc) {
04983 k = AST_ALAW(j);
04984 if (drc) {
04985 k = drc_sample(k, drc);
04986 }
04987 k = (float)k*linear_gain;
04988 if (k > 32767) k = 32767;
04989 if (k < -32767) k = -32767;
04990 g->txgain[j] = AST_LIN2A(k);
04991 } else {
04992 g->txgain[j] = j;
04993 }
04994 }
04995 break;
04996 case DAHDI_LAW_MULAW:
04997 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04998 if (gain || drc) {
04999 k = AST_MULAW(j);
05000 if (drc) {
05001 k = drc_sample(k, drc);
05002 }
05003 k = (float)k*linear_gain;
05004 if (k > 32767) k = 32767;
05005 if (k < -32767) k = -32767;
05006 g->txgain[j] = AST_LIN2MU(k);
05007
05008 } else {
05009 g->txgain[j] = j;
05010 }
05011 }
05012 break;
05013 }
05014 }
05015
05016 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05017 {
05018 int j;
05019 int k;
05020 float linear_gain = pow(10.0, gain / 20.0);
05021
05022 switch (law) {
05023 case DAHDI_LAW_ALAW:
05024 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05025 if (gain || drc) {
05026 k = AST_ALAW(j);
05027 if (drc) {
05028 k = drc_sample(k, drc);
05029 }
05030 k = (float)k*linear_gain;
05031 if (k > 32767) k = 32767;
05032 if (k < -32767) k = -32767;
05033 g->rxgain[j] = AST_LIN2A(k);
05034 } else {
05035 g->rxgain[j] = j;
05036 }
05037 }
05038 break;
05039 case DAHDI_LAW_MULAW:
05040 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05041 if (gain || drc) {
05042 k = AST_MULAW(j);
05043 if (drc) {
05044 k = drc_sample(k, drc);
05045 }
05046 k = (float)k*linear_gain;
05047 if (k > 32767) k = 32767;
05048 if (k < -32767) k = -32767;
05049 g->rxgain[j] = AST_LIN2MU(k);
05050 } else {
05051 g->rxgain[j] = j;
05052 }
05053 }
05054 break;
05055 }
05056 }
05057
05058 static int set_actual_txgain(int fd, float gain, float drc, int law)
05059 {
05060 struct dahdi_gains g;
05061 int res;
05062
05063 memset(&g, 0, sizeof(g));
05064 res = ioctl(fd, DAHDI_GETGAINS, &g);
05065 if (res) {
05066 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05067 return res;
05068 }
05069
05070 fill_txgain(&g, gain, drc, law);
05071
05072 return ioctl(fd, DAHDI_SETGAINS, &g);
05073 }
05074
05075 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05076 {
05077 struct dahdi_gains g;
05078 int res;
05079
05080 memset(&g, 0, sizeof(g));
05081 res = ioctl(fd, DAHDI_GETGAINS, &g);
05082 if (res) {
05083 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05084 return res;
05085 }
05086
05087 fill_rxgain(&g, gain, drc, law);
05088
05089 return ioctl(fd, DAHDI_SETGAINS, &g);
05090 }
05091
05092 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05093 {
05094 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05095 }
05096
05097 static int bump_gains(struct dahdi_pvt *p)
05098 {
05099 int res;
05100
05101
05102 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05103 if (res) {
05104 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05105 return -1;
05106 }
05107
05108 return 0;
05109 }
05110
05111 static int restore_gains(struct dahdi_pvt *p)
05112 {
05113 int res;
05114
05115 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05116 if (res) {
05117 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05118 return -1;
05119 }
05120
05121 return 0;
05122 }
05123
05124 static inline int dahdi_set_hook(int fd, int hs)
05125 {
05126 int x, res;
05127
05128 x = hs;
05129 res = ioctl(fd, DAHDI_HOOK, &x);
05130
05131 if (res < 0) {
05132 if (errno == EINPROGRESS)
05133 return 0;
05134 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05135
05136 }
05137
05138 return res;
05139 }
05140
05141 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05142 {
05143 int x, res;
05144
05145 x = muted;
05146 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05147 switch (p->sig) {
05148 #if defined(HAVE_PRI)
05149 case SIG_PRI_LIB_HANDLE_CASES:
05150 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05151
05152 break;
05153 }
05154
05155 #endif
05156 #if defined(HAVE_SS7)
05157 case SIG_SS7:
05158 #endif
05159 {
05160 int y = 1;
05161
05162 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05163 if (res)
05164 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05165 p->channel, strerror(errno));
05166 }
05167 break;
05168 default:
05169 break;
05170 }
05171 #endif
05172 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05173 if (res < 0)
05174 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05175 return res;
05176 }
05177
05178 static int save_conference(struct dahdi_pvt *p)
05179 {
05180 struct dahdi_confinfo c;
05181 int res;
05182 if (p->saveconf.confmode) {
05183 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05184 return -1;
05185 }
05186 p->saveconf.chan = 0;
05187 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05188 if (res) {
05189 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05190 p->saveconf.confmode = 0;
05191 return -1;
05192 }
05193 memset(&c, 0, sizeof(c));
05194 c.confmode = DAHDI_CONF_NORMAL;
05195 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05196 if (res) {
05197 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05198 return -1;
05199 }
05200 ast_debug(1, "Disabled conferencing\n");
05201 return 0;
05202 }
05203
05204 static int restore_conference(struct dahdi_pvt *p)
05205 {
05206 int res;
05207 if (p->saveconf.confmode) {
05208 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05209 p->saveconf.confmode = 0;
05210 if (res) {
05211 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05212 return -1;
05213 }
05214 ast_debug(1, "Restored conferencing\n");
05215 }
05216 return 0;
05217 }
05218
05219 static int send_cwcidspill(struct dahdi_pvt *p)
05220 {
05221 p->callwaitcas = 0;
05222 p->cidcwexpire = 0;
05223 p->cid_suppress_expire = 0;
05224 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05225 return -1;
05226 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05227
05228 p->cidlen += READ_SIZE * 4;
05229 p->cidpos = 0;
05230 send_callerid(p);
05231 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05232 return 0;
05233 }
05234
05235 static int has_voicemail(struct dahdi_pvt *p)
05236 {
05237 int new_msgs;
05238 struct ast_event *event;
05239 char *mailbox, *context;
05240
05241 mailbox = context = ast_strdupa(p->mailbox);
05242 strsep(&context, "@");
05243 if (ast_strlen_zero(context))
05244 context = "default";
05245
05246 event = ast_event_get_cached(AST_EVENT_MWI,
05247 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05248 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05249 AST_EVENT_IE_END);
05250
05251 if (event) {
05252 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05253 ast_event_destroy(event);
05254 } else
05255 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05256
05257 return new_msgs;
05258 }
05259
05260
05261
05262 static int send_callerid(struct dahdi_pvt *p)
05263 {
05264
05265 int res;
05266
05267 if (p->subs[SUB_REAL].linear) {
05268 p->subs[SUB_REAL].linear = 0;
05269 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05270 }
05271 while (p->cidpos < p->cidlen) {
05272 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05273 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05274 if (res < 0) {
05275 if (errno == EAGAIN)
05276 return 0;
05277 else {
05278 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05279 return -1;
05280 }
05281 }
05282 if (!res)
05283 return 0;
05284 p->cidpos += res;
05285 }
05286 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05287 ast_free(p->cidspill);
05288 p->cidspill = NULL;
05289 if (p->callwaitcas) {
05290
05291 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05292 p->cid_suppress_expire = p->cidcwexpire;
05293 } else
05294 restore_conference(p);
05295 return 0;
05296 }
05297
05298 static int dahdi_callwait(struct ast_channel *ast)
05299 {
05300 struct dahdi_pvt *p = ast->tech_pvt;
05301 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05302 if (p->cidspill) {
05303 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05304 ast_free(p->cidspill);
05305 }
05306
05307
05308
05309
05310
05311 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05312 return -1;
05313 save_conference(p);
05314
05315 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05316 if (!p->callwaitrings && p->callwaitingcallerid) {
05317 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05318 p->callwaitcas = 1;
05319 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05320 } else {
05321 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05322 p->callwaitcas = 0;
05323 p->cidlen = 2400 + READ_SIZE * 4;
05324 }
05325 p->cidpos = 0;
05326 send_callerid(p);
05327
05328 return 0;
05329 }
05330
05331 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05332 {
05333 struct dahdi_pvt *p = ast->tech_pvt;
05334 int x, res, mysig;
05335 char dest[256];
05336
05337 ast_mutex_lock(&p->lock);
05338 ast_copy_string(dest, rdest, sizeof(dest));
05339 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05340 if ((ast->_state == AST_STATE_BUSY)) {
05341 p->subs[SUB_REAL].needbusy = 1;
05342 ast_mutex_unlock(&p->lock);
05343 return 0;
05344 }
05345 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05346 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05347 ast_mutex_unlock(&p->lock);
05348 return -1;
05349 }
05350 p->waitingfordt.tv_sec = 0;
05351 p->dialednone = 0;
05352 if ((p->radio || (p->oprmode < 0)))
05353 {
05354
05355 ast_setstate(ast, AST_STATE_UP);
05356 ast_mutex_unlock(&p->lock);
05357 return 0;
05358 }
05359 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05360 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05361 if (res)
05362 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05363 p->outgoing = 1;
05364
05365 if (IS_DIGITAL(ast->transfercapability)){
05366 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05367 } else {
05368 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05369 }
05370
05371 #ifdef HAVE_PRI
05372 if (dahdi_sig_pri_lib_handles(p->sig)) {
05373 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05374 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05375 ast_mutex_unlock(&p->lock);
05376 return res;
05377 }
05378 #endif
05379
05380 #if defined(HAVE_SS7)
05381 if (p->sig == SIG_SS7) {
05382 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05383 ast_mutex_unlock(&p->lock);
05384 return res;
05385 }
05386 #endif
05387
05388
05389 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05390 p->callwaitrings = 0;
05391 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05392 ast_mutex_unlock(&p->lock);
05393 return res;
05394 }
05395
05396 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05397 switch (mysig) {
05398 case 0:
05399
05400 ast_setstate(ast, AST_STATE_UP);
05401 break;
05402 case SIG_MFCR2:
05403 break;
05404 default:
05405 ast_debug(1, "not yet implemented\n");
05406 ast_mutex_unlock(&p->lock);
05407 return -1;
05408 }
05409
05410 #ifdef HAVE_OPENR2
05411 if (p->mfcr2) {
05412 openr2_calling_party_category_t chancat;
05413 int callres = 0;
05414 char *c, *l;
05415
05416
05417 p->dialdest[0] = '\0';
05418
05419 c = strchr(dest, '/');
05420 if (c) {
05421 c++;
05422 } else {
05423 c = "";
05424 }
05425 if (!p->hidecallerid) {
05426 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05427 } else {
05428 l = NULL;
05429 }
05430 if (strlen(c) < p->stripmsd) {
05431 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05432 ast_mutex_unlock(&p->lock);
05433 return -1;
05434 }
05435 p->dialing = 1;
05436 chancat = dahdi_r2_get_channel_category(ast);
05437 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05438 if (-1 == callres) {
05439 ast_mutex_unlock(&p->lock);
05440 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05441 return -1;
05442 }
05443 p->mfcr2_call_accepted = 0;
05444 p->mfcr2_progress = 0;
05445 ast_setstate(ast, AST_STATE_DIALING);
05446 }
05447 #endif
05448 ast_mutex_unlock(&p->lock);
05449 return 0;
05450 }
05451
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05468 {
05469 struct dahdi_pvt *cur;
05470
05471 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05472
05473
05474 for (cur = iflist; cur; cur = cur->next) {
05475 if (pvt->channel < cur->channel) {
05476
05477 pvt->prev = cur->prev;
05478 pvt->next = cur;
05479 if (cur->prev) {
05480
05481 cur->prev->next = pvt;
05482 } else {
05483
05484 iflist = pvt;
05485 }
05486 cur->prev = pvt;
05487 return;
05488 }
05489 }
05490
05491
05492 pvt->prev = ifend;
05493 pvt->next = NULL;
05494 if (ifend) {
05495 ifend->next = pvt;
05496 }
05497 ifend = pvt;
05498 if (!iflist) {
05499
05500 iflist = pvt;
05501 }
05502 }
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516
05517 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05518 {
05519
05520 if (pvt->prev) {
05521 pvt->prev->next = pvt->next;
05522 } else if (iflist == pvt) {
05523
05524 iflist = pvt->next;
05525 }
05526
05527
05528 if (pvt->next) {
05529 pvt->next->prev = pvt->prev;
05530 } else if (ifend == pvt) {
05531
05532 ifend = pvt->prev;
05533 }
05534
05535
05536 pvt->which_iflist = DAHDI_IFLIST_NONE;
05537 pvt->prev = NULL;
05538 pvt->next = NULL;
05539 }
05540
05541 #if defined(HAVE_PRI)
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05559 {
05560 struct dahdi_pvt *cur;
05561
05562 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05563
05564
05565 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05566 if (pvt->channel < cur->channel) {
05567
05568 pvt->prev = cur->prev;
05569 pvt->next = cur;
05570 if (cur->prev) {
05571
05572 cur->prev->next = pvt;
05573 } else {
05574
05575 pri->no_b_chan_iflist = pvt;
05576 }
05577 cur->prev = pvt;
05578 return;
05579 }
05580 }
05581
05582
05583 pvt->prev = pri->no_b_chan_end;
05584 pvt->next = NULL;
05585 if (pri->no_b_chan_end) {
05586 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05587 }
05588 pri->no_b_chan_end = pvt;
05589 if (!pri->no_b_chan_iflist) {
05590
05591 pri->no_b_chan_iflist = pvt;
05592 }
05593 }
05594 #endif
05595
05596 #if defined(HAVE_PRI)
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05612 {
05613
05614 if (pvt->prev) {
05615 pvt->prev->next = pvt->next;
05616 } else if (pri->no_b_chan_iflist == pvt) {
05617
05618 pri->no_b_chan_iflist = pvt->next;
05619 }
05620
05621
05622 if (pvt->next) {
05623 pvt->next->prev = pvt->prev;
05624 } else if (pri->no_b_chan_end == pvt) {
05625
05626 pri->no_b_chan_end = pvt->prev;
05627 }
05628
05629
05630 pvt->which_iflist = DAHDI_IFLIST_NONE;
05631 pvt->prev = NULL;
05632 pvt->next = NULL;
05633 }
05634 #endif
05635
05636 #if defined(HAVE_PRI)
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05647 {
05648 unsigned idx;
05649 struct sig_pri_span *pri;
05650
05651 pri = pvt->pri;
05652 if (!pri) {
05653
05654 return;
05655 }
05656 ast_mutex_lock(&pri->lock);
05657 for (idx = 0; idx < pri->numchans; ++idx) {
05658 if (pri->pvts[idx] == pvt->sig_pvt) {
05659 pri->pvts[idx] = NULL;
05660 ast_mutex_unlock(&pri->lock);
05661 return;
05662 }
05663 }
05664 ast_mutex_unlock(&pri->lock);
05665 }
05666 #endif
05667
05668 #if defined(HAVE_SS7)
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05679 {
05680 unsigned idx;
05681 struct sig_ss7_linkset *ss7;
05682
05683 ss7 = pvt->ss7;
05684 if (!ss7) {
05685
05686 return;
05687 }
05688 ast_mutex_lock(&ss7->lock);
05689 for (idx = 0; idx < ss7->numchans; ++idx) {
05690 if (ss7->pvts[idx] == pvt->sig_pvt) {
05691 ss7->pvts[idx] = NULL;
05692 ast_mutex_unlock(&ss7->lock);
05693 return;
05694 }
05695 }
05696 ast_mutex_unlock(&ss7->lock);
05697 }
05698 #endif
05699
05700 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05701 {
05702 if (cur->next && cur->next->span == cur->span) {
05703 return cur->next;
05704 } else if (cur->prev && cur->prev->span == cur->span) {
05705 return cur->prev;
05706 }
05707
05708 return NULL;
05709 }
05710
05711 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05712 {
05713 struct dahdi_pvt *p = pvt;
05714
05715 if (p->manages_span_alarms) {
05716 struct dahdi_pvt *next = find_next_iface_in_span(p);
05717 if (next) {
05718 next->manages_span_alarms = 1;
05719 }
05720 }
05721
05722
05723 #if defined(HAVE_PRI)
05724 dahdi_unlink_pri_pvt(p);
05725 #endif
05726 #if defined(HAVE_SS7)
05727 dahdi_unlink_ss7_pvt(p);
05728 #endif
05729 switch (pvt->which_iflist) {
05730 case DAHDI_IFLIST_NONE:
05731 break;
05732 case DAHDI_IFLIST_MAIN:
05733 dahdi_iflist_extract(p);
05734 break;
05735 #if defined(HAVE_PRI)
05736 case DAHDI_IFLIST_NO_B_CHAN:
05737 if (p->pri) {
05738 dahdi_nobch_extract(p->pri, p);
05739 }
05740 break;
05741 #endif
05742 }
05743
05744 if (p->sig_pvt) {
05745 if (analog_lib_handles(p->sig, 0, 0)) {
05746 analog_delete(p->sig_pvt);
05747 }
05748 switch (p->sig) {
05749 #if defined(HAVE_PRI)
05750 case SIG_PRI_LIB_HANDLE_CASES:
05751 sig_pri_chan_delete(p->sig_pvt);
05752 break;
05753 #endif
05754 #if defined(HAVE_SS7)
05755 case SIG_SS7:
05756 sig_ss7_chan_delete(p->sig_pvt);
05757 break;
05758 #endif
05759 default:
05760 break;
05761 }
05762 }
05763 ast_free(p->cidspill);
05764 if (p->use_smdi)
05765 ast_smdi_interface_unref(p->smdi_iface);
05766 if (p->mwi_event_sub)
05767 ast_event_unsubscribe(p->mwi_event_sub);
05768 if (p->vars) {
05769 ast_variables_destroy(p->vars);
05770 }
05771 if (p->cc_params) {
05772 ast_cc_config_params_destroy(p->cc_params);
05773 }
05774 ast_mutex_destroy(&p->lock);
05775 dahdi_close_sub(p, SUB_REAL);
05776 if (p->owner)
05777 p->owner->tech_pvt = NULL;
05778 ast_free(p);
05779 }
05780
05781 static void destroy_channel(struct dahdi_pvt *cur, int now)
05782 {
05783 int i;
05784
05785 if (!now) {
05786
05787 if (cur->owner) {
05788 return;
05789 }
05790 for (i = 0; i < 3; i++) {
05791 if (cur->subs[i].owner) {
05792 return;
05793 }
05794 }
05795 }
05796 destroy_dahdi_pvt(cur);
05797 }
05798
05799 static void destroy_all_channels(void)
05800 {
05801 int chan;
05802 #if defined(HAVE_PRI)
05803 unsigned span;
05804 struct sig_pri_span *pri;
05805 #endif
05806 struct dahdi_pvt *p;
05807
05808 while (num_restart_pending) {
05809 usleep(1);
05810 }
05811
05812 ast_mutex_lock(&iflock);
05813
05814 while (iflist) {
05815 p = iflist;
05816
05817 chan = p->channel;
05818 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05819 {
05820 char db_chan_name[20];
05821 char db_answer[5];
05822 char state;
05823 int why = -1;
05824
05825 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05826 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05827 sscanf(db_answer, "%1c:%30d", &state, &why);
05828 }
05829 if (!why) {
05830
05831 ast_db_del(db_chan_name, SRVST_DBKEY);
05832 }
05833 }
05834 #endif
05835
05836 destroy_dahdi_pvt(p);
05837 ast_verb(3, "Unregistered channel %d\n", chan);
05838 }
05839 ifcount = 0;
05840 ast_mutex_unlock(&iflock);
05841
05842 #if defined(HAVE_PRI)
05843
05844 for (span = 0; span < NUM_SPANS; ++span) {
05845 if (!pris[span].dchannels[0]) {
05846 break;
05847 }
05848 pri = &pris[span].pri;
05849 ast_mutex_lock(&pri->lock);
05850 while (pri->no_b_chan_iflist) {
05851 p = pri->no_b_chan_iflist;
05852
05853
05854 destroy_dahdi_pvt(p);
05855 }
05856 ast_mutex_unlock(&pri->lock);
05857 }
05858 #endif
05859 }
05860
05861 #if defined(HAVE_PRI)
05862 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05863
05864 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05865 {
05866
05867 struct dahdi_pvt *p;
05868
05869 if (ast_strlen_zero(digits)) {
05870 ast_debug(1, "No digit string sent to application!\n");
05871 return -1;
05872 }
05873
05874 p = (struct dahdi_pvt *)chan->tech_pvt;
05875
05876 if (!p) {
05877 ast_debug(1, "Unable to find technology private\n");
05878 return -1;
05879 }
05880
05881 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05882
05883 return 0;
05884 }
05885 #endif
05886
05887 #if defined(HAVE_PRI)
05888 #if defined(HAVE_PRI_PROG_W_CAUSE)
05889 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05890
05891 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05892 {
05893
05894 struct dahdi_pvt *pvt;
05895 char *parse;
05896 int res = -1;
05897 AST_DECLARE_APP_ARGS(args,
05898 AST_APP_ARG(destination);
05899 AST_APP_ARG(original);
05900 AST_APP_ARG(reason);
05901 );
05902
05903 if (ast_strlen_zero(data)) {
05904 ast_log(LOG_DEBUG, "No data sent to application!\n");
05905 return -1;
05906 }
05907 if (chan->tech != &dahdi_tech) {
05908 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05909 return -1;
05910 }
05911 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05912 if (!pvt) {
05913 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05914 return -1;
05915 }
05916 switch (pvt->sig) {
05917 case SIG_PRI_LIB_HANDLE_CASES:
05918 break;
05919 default:
05920 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05921 chan->name);
05922 return -1;
05923 }
05924
05925 parse = ast_strdupa(data);
05926 AST_STANDARD_APP_ARGS(args, parse);
05927
05928 if (ast_strlen_zero(args.destination)) {
05929 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05930 return -1;
05931 }
05932
05933 if (ast_strlen_zero(args.original)) {
05934 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05935 args.original = NULL;
05936 }
05937
05938 if (ast_strlen_zero(args.reason)) {
05939 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05940 args.reason = NULL;
05941 }
05942
05943 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05944 args.original, args.reason);
05945
05946 return res;
05947 }
05948 #endif
05949 #endif
05950
05951 #if defined(HAVE_OPENR2)
05952 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05953
05954 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05955 {
05956
05957 openr2_call_mode_t accept_mode;
05958 int res, timeout, maxloops;
05959 struct ast_frame *f;
05960 struct dahdi_pvt *p;
05961 char *parse;
05962 AST_DECLARE_APP_ARGS(args,
05963 AST_APP_ARG(charge);
05964 );
05965
05966 if (ast_strlen_zero(data)) {
05967 ast_log(LOG_DEBUG, "No data sent to application!\n");
05968 return -1;
05969 }
05970
05971 if (chan->tech != &dahdi_tech) {
05972 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05973 return -1;
05974 }
05975
05976 p = (struct dahdi_pvt *)chan->tech_pvt;
05977 if (!p) {
05978 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05979 return -1;
05980 }
05981
05982 parse = ast_strdupa(data);
05983 AST_STANDARD_APP_ARGS(args, parse);
05984
05985 if (ast_strlen_zero(args.charge)) {
05986 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05987 return -1;
05988 }
05989
05990 ast_mutex_lock(&p->lock);
05991 if (!p->mfcr2 || !p->mfcr2call) {
05992 ast_mutex_unlock(&p->lock);
05993 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05994 return -1;
05995 }
05996
05997 if (p->mfcr2_call_accepted) {
05998 ast_mutex_unlock(&p->lock);
05999 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06000 return 0;
06001 }
06002 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06003 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06004 ast_mutex_unlock(&p->lock);
06005 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06006 return -1;
06007 }
06008 ast_mutex_unlock(&p->lock);
06009
06010 res = 0;
06011 timeout = 100;
06012 maxloops = 50;
06013
06014 while (maxloops > 0) {
06015 maxloops--;
06016 if (ast_check_hangup(chan)) {
06017 break;
06018 }
06019 res = ast_waitfor(chan, timeout);
06020 if (res < 0) {
06021 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06022 res = -1;
06023 break;
06024 }
06025 if (res == 0) {
06026 continue;
06027 }
06028 f = ast_read(chan);
06029 if (!f) {
06030 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06031 res = -1;
06032 break;
06033 }
06034 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06035 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06036 ast_frfree(f);
06037 res = -1;
06038 break;
06039 }
06040 ast_frfree(f);
06041 ast_mutex_lock(&p->lock);
06042 if (p->mfcr2_call_accepted) {
06043 ast_mutex_unlock(&p->lock);
06044 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06045 break;
06046 }
06047 ast_mutex_unlock(&p->lock);
06048 }
06049 if (res == -1) {
06050 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06051 }
06052 return res;
06053 }
06054
06055 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06056 {
06057 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06058 switch (cause) {
06059 case AST_CAUSE_USER_BUSY:
06060 case AST_CAUSE_CALL_REJECTED:
06061 case AST_CAUSE_INTERWORKING:
06062 r2cause = OR2_CAUSE_BUSY_NUMBER;
06063 break;
06064
06065 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06066 case AST_CAUSE_SWITCH_CONGESTION:
06067 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06068 break;
06069
06070 case AST_CAUSE_UNALLOCATED:
06071 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06072 break;
06073
06074 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06075 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06076 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06077 break;
06078
06079 case AST_CAUSE_NO_ANSWER:
06080 case AST_CAUSE_NO_USER_RESPONSE:
06081 r2cause = OR2_CAUSE_NO_ANSWER;
06082 break;
06083
06084 default:
06085 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06086 break;
06087 }
06088 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06089 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06090 return r2cause;
06091 }
06092 #endif
06093
06094 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06095 {
06096 if (p->bufferoverrideinuse) {
06097
06098 struct dahdi_bufferinfo bi = {
06099 .txbufpolicy = p->buf_policy,
06100 .rxbufpolicy = p->buf_policy,
06101 .bufsize = p->bufsize,
06102 .numbufs = p->buf_no
06103 };
06104 int bpres;
06105
06106 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06107 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06108 }
06109 p->bufferoverrideinuse = 0;
06110 return bpres;
06111 }
06112
06113 return -1;
06114 }
06115
06116 static int dahdi_hangup(struct ast_channel *ast)
06117 {
06118 int res = 0;
06119 int idx,x;
06120 int law;
06121
06122 struct dahdi_pvt *p = ast->tech_pvt;
06123 struct dahdi_params par;
06124
06125 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06126 if (!ast->tech_pvt) {
06127 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06128 return 0;
06129 }
06130
06131 ast_mutex_lock(&p->lock);
06132 p->exten[0] = '\0';
06133 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06134 dahdi_confmute(p, 0);
06135 restore_gains(p);
06136 p->ignoredtmf = 0;
06137 p->waitingfordt.tv_sec = 0;
06138
06139 res = analog_hangup(p->sig_pvt, ast);
06140 revert_fax_buffers(p, ast);
06141
06142 goto hangup_out;
06143 } else {
06144 p->cid_num[0] = '\0';
06145 p->cid_name[0] = '\0';
06146 p->cid_subaddr[0] = '\0';
06147 }
06148
06149 #if defined(HAVE_PRI)
06150 if (dahdi_sig_pri_lib_handles(p->sig)) {
06151 x = 1;
06152 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06153
06154 dahdi_confmute(p, 0);
06155 p->muting = 0;
06156 restore_gains(p);
06157 if (p->dsp) {
06158 ast_dsp_free(p->dsp);
06159 p->dsp = NULL;
06160 }
06161 p->ignoredtmf = 0;
06162
06163
06164 p->subs[SUB_REAL].owner = NULL;
06165 p->subs[SUB_REAL].needbusy = 0;
06166 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06167
06168 p->owner = NULL;
06169 p->cid_tag[0] = '\0';
06170 p->ringt = 0;
06171 p->distinctivering = 0;
06172 p->confirmanswer = 0;
06173 p->outgoing = 0;
06174 p->digital = 0;
06175 p->faxhandled = 0;
06176 p->pulsedial = 0;
06177
06178 revert_fax_buffers(p, ast);
06179
06180 p->law = p->law_default;
06181 law = p->law_default;
06182 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06183 if (res < 0) {
06184 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06185 p->channel, strerror(errno));
06186 }
06187
06188 sig_pri_hangup(p->sig_pvt, ast);
06189
06190 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06191 dahdi_disable_ec(p);
06192
06193 x = 0;
06194 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06195 p->didtdd = 0;
06196
06197 p->rdnis[0] = '\0';
06198 update_conf(p);
06199 reset_conf(p);
06200
06201
06202 x = 0;
06203 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06204
06205 if (num_restart_pending == 0) {
06206 restart_monitor();
06207 }
06208 goto hangup_out;
06209 }
06210 #endif
06211
06212 #if defined(HAVE_SS7)
06213 if (p->sig == SIG_SS7) {
06214 x = 1;
06215 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06216
06217 dahdi_confmute(p, 0);
06218 p->muting = 0;
06219 restore_gains(p);
06220 if (p->dsp) {
06221 ast_dsp_free(p->dsp);
06222 p->dsp = NULL;
06223 }
06224 p->ignoredtmf = 0;
06225
06226
06227 p->subs[SUB_REAL].owner = NULL;
06228 p->subs[SUB_REAL].needbusy = 0;
06229 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06230
06231 p->owner = NULL;
06232 p->ringt = 0;
06233 p->distinctivering = 0;
06234 p->confirmanswer = 0;
06235 p->outgoing = 0;
06236 p->digital = 0;
06237 p->faxhandled = 0;
06238 p->pulsedial = 0;
06239
06240 revert_fax_buffers(p, ast);
06241
06242 p->law = p->law_default;
06243 law = p->law_default;
06244 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06245 if (res < 0) {
06246 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06247 p->channel, strerror(errno));
06248 }
06249
06250 sig_ss7_hangup(p->sig_pvt, ast);
06251
06252 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06253 dahdi_disable_ec(p);
06254
06255 x = 0;
06256 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06257 p->didtdd = 0;
06258
06259 update_conf(p);
06260 reset_conf(p);
06261
06262
06263 x = 0;
06264 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06265
06266 if (num_restart_pending == 0) {
06267 restart_monitor();
06268 }
06269 goto hangup_out;
06270 }
06271 #endif
06272
06273 idx = dahdi_get_index(ast, p, 1);
06274
06275 dahdi_confmute(p, 0);
06276 p->muting = 0;
06277 restore_gains(p);
06278 if (p->origcid_num) {
06279 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06280 ast_free(p->origcid_num);
06281 p->origcid_num = NULL;
06282 }
06283 if (p->origcid_name) {
06284 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06285 ast_free(p->origcid_name);
06286 p->origcid_name = NULL;
06287 }
06288 if (p->dsp)
06289 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06290
06291 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06292 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06293 p->ignoredtmf = 0;
06294
06295 if (idx > -1) {
06296
06297 p->subs[idx].owner = NULL;
06298 p->subs[idx].needanswer = 0;
06299 p->subs[idx].needflash = 0;
06300 p->subs[idx].needringing = 0;
06301 p->subs[idx].needbusy = 0;
06302 p->subs[idx].needcongestion = 0;
06303 p->subs[idx].linear = 0;
06304 p->polarity = POLARITY_IDLE;
06305 dahdi_setlinear(p->subs[idx].dfd, 0);
06306 if (idx == SUB_REAL) {
06307 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06308 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06309 if (p->subs[SUB_CALLWAIT].inthreeway) {
06310
06311 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06312
06313 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06314 unalloc_sub(p, SUB_CALLWAIT);
06315 p->owner = NULL;
06316 } else {
06317
06318 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06319 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06320 unalloc_sub(p, SUB_THREEWAY);
06321 if (p->subs[SUB_REAL].inthreeway) {
06322
06323
06324 ast_debug(1, "Call was complete, setting owner to former third call\n");
06325 p->owner = p->subs[SUB_REAL].owner;
06326 } else {
06327
06328 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06329 p->owner = NULL;
06330 }
06331 p->subs[SUB_REAL].inthreeway = 0;
06332 }
06333 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06334
06335 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06336 unalloc_sub(p, SUB_CALLWAIT);
06337 p->owner = p->subs[SUB_REAL].owner;
06338 if (p->owner->_state != AST_STATE_UP)
06339 p->subs[SUB_REAL].needanswer = 1;
06340 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06341 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06342 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06343 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06344 unalloc_sub(p, SUB_THREEWAY);
06345 if (p->subs[SUB_REAL].inthreeway) {
06346
06347
06348 ast_debug(1, "Call was complete, setting owner to former third call\n");
06349 p->owner = p->subs[SUB_REAL].owner;
06350 } else {
06351
06352 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06353 p->owner = NULL;
06354 }
06355 p->subs[SUB_REAL].inthreeway = 0;
06356 }
06357 } else if (idx == SUB_CALLWAIT) {
06358
06359 if (p->subs[SUB_CALLWAIT].inthreeway) {
06360
06361
06362 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06363 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06364 S_OR(p->mohsuggest, NULL),
06365 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06366 }
06367 p->subs[SUB_THREEWAY].inthreeway = 0;
06368
06369 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06370 unalloc_sub(p, SUB_THREEWAY);
06371 } else
06372 unalloc_sub(p, SUB_CALLWAIT);
06373 } else if (idx == SUB_THREEWAY) {
06374 if (p->subs[SUB_CALLWAIT].inthreeway) {
06375
06376
06377 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06378 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06379 S_OR(p->mohsuggest, NULL),
06380 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06381 }
06382 p->subs[SUB_CALLWAIT].inthreeway = 0;
06383 }
06384 p->subs[SUB_REAL].inthreeway = 0;
06385
06386
06387 unalloc_sub(p, SUB_THREEWAY);
06388 } else {
06389
06390 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06391 }
06392 }
06393
06394 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06395 p->owner = NULL;
06396 p->ringt = 0;
06397 p->distinctivering = 0;
06398 p->confirmanswer = 0;
06399 p->outgoing = 0;
06400 p->digital = 0;
06401 p->faxhandled = 0;
06402 p->pulsedial = 0;
06403 if (p->dsp) {
06404 ast_dsp_free(p->dsp);
06405 p->dsp = NULL;
06406 }
06407
06408 revert_fax_buffers(p, ast);
06409
06410 p->law = p->law_default;
06411 law = p->law_default;
06412 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06413 if (res < 0)
06414 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06415
06416 #ifdef HAVE_OPENR2
06417 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06418 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06419
06420 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06421 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06422 } else {
06423 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06424 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06425 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06426 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06427 dahdi_r2_disconnect_call(p, r2cause);
06428 }
06429 } else if (p->mfcr2call) {
06430 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06431
06432
06433
06434
06435 p->mfcr2call = 0;
06436 }
06437 #endif
06438 switch (p->sig) {
06439 case SIG_SS7:
06440 case SIG_MFCR2:
06441 case SIG_PRI_LIB_HANDLE_CASES:
06442 case 0:
06443 break;
06444 default:
06445 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06446 break;
06447 }
06448 if (res < 0) {
06449 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06450 }
06451 switch (p->sig) {
06452 case SIG_FXOGS:
06453 case SIG_FXOLS:
06454 case SIG_FXOKS:
06455 memset(&par, 0, sizeof(par));
06456 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06457 if (!res) {
06458 struct analog_pvt *analog_p = p->sig_pvt;
06459 #if 0
06460 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06461 #endif
06462
06463 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06464 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06465 else
06466 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06467 analog_p->fxsoffhookstate = par.rxisoffhook;
06468 }
06469 break;
06470 case SIG_FXSGS:
06471 case SIG_FXSLS:
06472 case SIG_FXSKS:
06473
06474
06475 if (ast->_state != AST_STATE_RESERVED) {
06476 time(&p->guardtime);
06477 p->guardtime += 2;
06478 }
06479 break;
06480 default:
06481 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06482 break;
06483 }
06484 if (p->sig)
06485 dahdi_disable_ec(p);
06486 x = 0;
06487 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06488 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06489 p->didtdd = 0;
06490 p->callwaitcas = 0;
06491 p->callwaiting = p->permcallwaiting;
06492 p->hidecallerid = p->permhidecallerid;
06493 p->waitingfordt.tv_sec = 0;
06494 p->dialing = 0;
06495 p->rdnis[0] = '\0';
06496 update_conf(p);
06497 reset_conf(p);
06498
06499 switch (p->sig) {
06500 case SIG_PRI_LIB_HANDLE_CASES:
06501 case SIG_SS7:
06502 x = 0;
06503 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06504 break;
06505 default:
06506 break;
06507 }
06508 if (num_restart_pending == 0)
06509 restart_monitor();
06510 }
06511
06512 p->callwaitingrepeat = 0;
06513 p->cidcwexpire = 0;
06514 p->cid_suppress_expire = 0;
06515 p->oprmode = 0;
06516 hangup_out:
06517 ast->tech_pvt = NULL;
06518 ast_free(p->cidspill);
06519 p->cidspill = NULL;
06520
06521 ast_mutex_unlock(&p->lock);
06522 ast_verb(3, "Hungup '%s'\n", ast->name);
06523
06524 ast_mutex_lock(&iflock);
06525 if (p->restartpending) {
06526 num_restart_pending--;
06527 }
06528
06529 if (p->destroy) {
06530 destroy_channel(p, 0);
06531 }
06532 ast_mutex_unlock(&iflock);
06533
06534 ast_module_unref(ast_module_info->self);
06535 return 0;
06536 }
06537
06538 static int dahdi_answer(struct ast_channel *ast)
06539 {
06540 struct dahdi_pvt *p = ast->tech_pvt;
06541 int res = 0;
06542 int idx;
06543 ast_setstate(ast, AST_STATE_UP);
06544 ast_mutex_lock(&p->lock);
06545 idx = dahdi_get_index(ast, p, 0);
06546 if (idx < 0)
06547 idx = SUB_REAL;
06548
06549 if ((p->radio || (p->oprmode < 0))) {
06550 ast_mutex_unlock(&p->lock);
06551 return 0;
06552 }
06553
06554 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06555 res = analog_answer(p->sig_pvt, ast);
06556 ast_mutex_unlock(&p->lock);
06557 return res;
06558 }
06559
06560 switch (p->sig) {
06561 #if defined(HAVE_PRI)
06562 case SIG_PRI_LIB_HANDLE_CASES:
06563 res = sig_pri_answer(p->sig_pvt, ast);
06564 break;
06565 #endif
06566 #if defined(HAVE_SS7)
06567 case SIG_SS7:
06568 res = sig_ss7_answer(p->sig_pvt, ast);
06569 break;
06570 #endif
06571 #ifdef HAVE_OPENR2
06572 case SIG_MFCR2:
06573 if (!p->mfcr2_call_accepted) {
06574
06575
06576 p->mfcr2_answer_pending = 1;
06577 if (p->mfcr2_charge_calls) {
06578 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06579 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06580 } else {
06581 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06582 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06583 }
06584 } else {
06585 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06586 dahdi_r2_answer(p);
06587 }
06588 break;
06589 #endif
06590 case 0:
06591 ast_mutex_unlock(&p->lock);
06592 return 0;
06593 default:
06594 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06595 res = -1;
06596 break;
06597 }
06598 ast_mutex_unlock(&p->lock);
06599 return res;
06600 }
06601
06602 static void disable_dtmf_detect(struct dahdi_pvt *p)
06603 {
06604 int val = 0;
06605
06606 p->ignoredtmf = 1;
06607
06608 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06609
06610 if (!p->hardwaredtmf && p->dsp) {
06611 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06612 ast_dsp_set_features(p->dsp, p->dsp_features);
06613 }
06614 }
06615
06616 static void enable_dtmf_detect(struct dahdi_pvt *p)
06617 {
06618 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06619
06620 if (p->channel == CHAN_PSEUDO)
06621 return;
06622
06623 p->ignoredtmf = 0;
06624
06625 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06626
06627 if (!p->hardwaredtmf && p->dsp) {
06628 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06629 ast_dsp_set_features(p->dsp, p->dsp_features);
06630 }
06631 }
06632
06633 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06634 {
06635 char *cp;
06636 struct dahdi_pvt *p = chan->tech_pvt;
06637
06638
06639 if (!p || !data || (*datalen < 1)) {
06640 errno = EINVAL;
06641 return -1;
06642 }
06643
06644 switch (option) {
06645 case AST_OPTION_DIGIT_DETECT:
06646 cp = (char *) data;
06647 *cp = p->ignoredtmf ? 0 : 1;
06648 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06649 break;
06650 case AST_OPTION_FAX_DETECT:
06651 cp = (char *) data;
06652 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06653 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06654 break;
06655 case AST_OPTION_CC_AGENT_TYPE:
06656 #if defined(HAVE_PRI)
06657 #if defined(HAVE_PRI_CCSS)
06658 if (dahdi_sig_pri_lib_handles(p->sig)) {
06659 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06660 break;
06661 }
06662 #endif
06663 #endif
06664 return -1;
06665 default:
06666 return -1;
06667 }
06668
06669 errno = 0;
06670
06671 return 0;
06672 }
06673
06674 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06675 {
06676 char *cp;
06677 signed char *scp;
06678 int x;
06679 int idx;
06680 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06681 struct oprmode *oprmode;
06682
06683
06684
06685 if (!p || !data || (datalen < 1)) {
06686 errno = EINVAL;
06687 return -1;
06688 }
06689
06690 switch (option) {
06691 case AST_OPTION_TXGAIN:
06692 scp = (signed char *) data;
06693 idx = dahdi_get_index(chan, p, 0);
06694 if (idx < 0) {
06695 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06696 return -1;
06697 }
06698 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06699 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06700 case AST_OPTION_RXGAIN:
06701 scp = (signed char *) data;
06702 idx = dahdi_get_index(chan, p, 0);
06703 if (idx < 0) {
06704 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06705 return -1;
06706 }
06707 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06708 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06709 case AST_OPTION_TONE_VERIFY:
06710 if (!p->dsp)
06711 break;
06712 cp = (char *) data;
06713 switch (*cp) {
06714 case 1:
06715 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06716 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06717 break;
06718 case 2:
06719 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06720 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06721 break;
06722 default:
06723 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06724 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06725 break;
06726 }
06727 break;
06728 case AST_OPTION_TDD:
06729
06730 cp = (char *) data;
06731 p->mate = 0;
06732 if (!*cp) {
06733 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06734 if (p->tdd)
06735 tdd_free(p->tdd);
06736 p->tdd = 0;
06737 break;
06738 }
06739 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06740 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06741 dahdi_disable_ec(p);
06742
06743 if (!p->didtdd) {
06744 unsigned char mybuf[41000];
06745 unsigned char *buf;
06746 int size, res, fd, len;
06747 struct pollfd fds[1];
06748
06749 buf = mybuf;
06750 memset(buf, 0x7f, sizeof(mybuf));
06751 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06752 len = 40000;
06753 idx = dahdi_get_index(chan, p, 0);
06754 if (idx < 0) {
06755 ast_log(LOG_WARNING, "No index in TDD?\n");
06756 return -1;
06757 }
06758 fd = p->subs[idx].dfd;
06759 while (len) {
06760 if (ast_check_hangup(chan))
06761 return -1;
06762 size = len;
06763 if (size > READ_SIZE)
06764 size = READ_SIZE;
06765 fds[0].fd = fd;
06766 fds[0].events = POLLPRI | POLLOUT;
06767 fds[0].revents = 0;
06768 res = poll(fds, 1, -1);
06769 if (!res) {
06770 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06771 continue;
06772 }
06773
06774 if (fds[0].revents & POLLPRI)
06775 return -1;
06776 if (!(fds[0].revents & POLLOUT)) {
06777 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06778 continue;
06779 }
06780 res = write(fd, buf, size);
06781 if (res != size) {
06782 if (res == -1) return -1;
06783 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06784 break;
06785 }
06786 len -= size;
06787 buf += size;
06788 }
06789 p->didtdd = 1;
06790 }
06791 if (*cp == 2) {
06792 if (p->tdd)
06793 tdd_free(p->tdd);
06794 p->tdd = 0;
06795 p->mate = 1;
06796 break;
06797 }
06798 if (!p->tdd) {
06799 p->tdd = tdd_new();
06800 }
06801 break;
06802 case AST_OPTION_RELAXDTMF:
06803 if (!p->dsp)
06804 break;
06805 cp = (char *) data;
06806 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06807 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06808 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06809 break;
06810 case AST_OPTION_AUDIO_MODE:
06811 #if defined(HAVE_PRI)
06812 if (dahdi_sig_pri_lib_handles(p->sig)
06813 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06814
06815 break;
06816 }
06817 #endif
06818
06819 cp = (char *) data;
06820 if (!*cp) {
06821 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06822 x = 0;
06823 dahdi_disable_ec(p);
06824 } else {
06825 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06826 x = 1;
06827 }
06828 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06829 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06830 break;
06831 case AST_OPTION_OPRMODE:
06832 oprmode = (struct oprmode *) data;
06833
06834 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06835 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06836 chan->tech->type, oprmode->peer->tech->type);
06837 errno = EINVAL;
06838 return -1;
06839 }
06840 pp = oprmode->peer->tech_pvt;
06841 p->oprmode = pp->oprmode = 0;
06842
06843 p->oprpeer = pp;
06844 pp->oprpeer = p;
06845
06846 if (oprmode->mode)
06847 {
06848 pp->oprmode = oprmode->mode;
06849 p->oprmode = -oprmode->mode;
06850 }
06851 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06852 oprmode->mode, chan->name,oprmode->peer->name);
06853 break;
06854 case AST_OPTION_ECHOCAN:
06855 cp = (char *) data;
06856 if (*cp) {
06857 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06858 dahdi_enable_ec(p);
06859 } else {
06860 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06861 dahdi_disable_ec(p);
06862 }
06863 break;
06864 case AST_OPTION_DIGIT_DETECT:
06865 cp = (char *) data;
06866 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06867 if (*cp) {
06868 enable_dtmf_detect(p);
06869 } else {
06870 disable_dtmf_detect(p);
06871 }
06872 break;
06873 case AST_OPTION_FAX_DETECT:
06874 cp = (char *) data;
06875 if (p->dsp) {
06876 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06877 if (*cp) {
06878 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06879 } else {
06880 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06881 }
06882 ast_dsp_set_features(p->dsp, p->dsp_features);
06883 }
06884 break;
06885 default:
06886 return -1;
06887 }
06888 errno = 0;
06889
06890 return 0;
06891 }
06892
06893 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06894 {
06895 struct dahdi_pvt *p = chan->tech_pvt;
06896 int res = 0;
06897
06898 if (!p) {
06899
06900 *buf = '\0';
06901 return -1;
06902 }
06903
06904 if (!strcasecmp(data, "rxgain")) {
06905 ast_mutex_lock(&p->lock);
06906 snprintf(buf, len, "%f", p->rxgain);
06907 ast_mutex_unlock(&p->lock);
06908 } else if (!strcasecmp(data, "txgain")) {
06909 ast_mutex_lock(&p->lock);
06910 snprintf(buf, len, "%f", p->txgain);
06911 ast_mutex_unlock(&p->lock);
06912 } else if (!strcasecmp(data, "dahdi_channel")) {
06913 ast_mutex_lock(&p->lock);
06914 snprintf(buf, len, "%d", p->channel);
06915 ast_mutex_unlock(&p->lock);
06916 } else if (!strcasecmp(data, "dahdi_span")) {
06917 ast_mutex_lock(&p->lock);
06918 snprintf(buf, len, "%d", p->span);
06919 ast_mutex_unlock(&p->lock);
06920 } else if (!strcasecmp(data, "dahdi_type")) {
06921 ast_mutex_lock(&p->lock);
06922 switch (p->sig) {
06923 #if defined(HAVE_OPENR2)
06924 case SIG_MFCR2:
06925 ast_copy_string(buf, "mfc/r2", len);
06926 break;
06927 #endif
06928 #if defined(HAVE_PRI)
06929 case SIG_PRI_LIB_HANDLE_CASES:
06930 ast_copy_string(buf, "pri", len);
06931 break;
06932 #endif
06933 case 0:
06934 ast_copy_string(buf, "pseudo", len);
06935 break;
06936 #if defined(HAVE_SS7)
06937 case SIG_SS7:
06938 ast_copy_string(buf, "ss7", len);
06939 break;
06940 #endif
06941 default:
06942
06943 ast_copy_string(buf, "analog", len);
06944 break;
06945 }
06946 ast_mutex_unlock(&p->lock);
06947 #if defined(HAVE_PRI)
06948 #if defined(HAVE_PRI_REVERSE_CHARGE)
06949 } else if (!strcasecmp(data, "reversecharge")) {
06950 ast_mutex_lock(&p->lock);
06951 switch (p->sig) {
06952 case SIG_PRI_LIB_HANDLE_CASES:
06953 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06954 break;
06955 default:
06956 *buf = '\0';
06957 res = -1;
06958 break;
06959 }
06960 ast_mutex_unlock(&p->lock);
06961 #endif
06962 #if defined(HAVE_PRI_SETUP_KEYPAD)
06963 } else if (!strcasecmp(data, "keypad_digits")) {
06964 ast_mutex_lock(&p->lock);
06965 switch (p->sig) {
06966 case SIG_PRI_LIB_HANDLE_CASES:
06967 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06968 len);
06969 break;
06970 default:
06971 *buf = '\0';
06972 res = -1;
06973 break;
06974 }
06975 ast_mutex_unlock(&p->lock);
06976 #endif
06977 } else if (!strcasecmp(data, "no_media_path")) {
06978 ast_mutex_lock(&p->lock);
06979 switch (p->sig) {
06980 case SIG_PRI_LIB_HANDLE_CASES:
06981
06982
06983
06984
06985 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06986 break;
06987 default:
06988 *buf = '\0';
06989 res = -1;
06990 break;
06991 }
06992 ast_mutex_unlock(&p->lock);
06993 #endif
06994 } else {
06995 *buf = '\0';
06996 res = -1;
06997 }
06998
06999 return res;
07000 }
07001
07002
07003 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07004 {
07005 int res;
07006 char policy_str[21] = "";
07007
07008 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07009 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07010 return 1;
07011 }
07012 if (*num_buffers < 0) {
07013 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07014 return -1;
07015 }
07016 if (!strcasecmp(policy_str, "full")) {
07017 *policy = DAHDI_POLICY_WHEN_FULL;
07018 } else if (!strcasecmp(policy_str, "immediate")) {
07019 *policy = DAHDI_POLICY_IMMEDIATE;
07020 #if defined(HAVE_DAHDI_HALF_FULL)
07021 } else if (!strcasecmp(policy_str, "half")) {
07022 *policy = DAHDI_POLICY_HALF_FULL;
07023 #endif
07024 } else {
07025 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07026 return -1;
07027 }
07028
07029 return 0;
07030 }
07031
07032 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07033 {
07034 struct dahdi_pvt *p = chan->tech_pvt;
07035 int res = 0;
07036
07037 if (!p) {
07038
07039 return -1;
07040 }
07041
07042 if (!strcasecmp(data, "buffers")) {
07043 int num_bufs, policy;
07044
07045 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07046 struct dahdi_bufferinfo bi = {
07047 .txbufpolicy = policy,
07048 .rxbufpolicy = policy,
07049 .bufsize = p->bufsize,
07050 .numbufs = num_bufs,
07051 };
07052 int bpres;
07053
07054 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07055 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07056 } else {
07057 p->bufferoverrideinuse = 1;
07058 }
07059 } else {
07060 res = -1;
07061 }
07062 } else if (!strcasecmp(data, "echocan_mode")) {
07063 if (!strcasecmp(value, "on")) {
07064 ast_mutex_lock(&p->lock);
07065 dahdi_enable_ec(p);
07066 ast_mutex_unlock(&p->lock);
07067 } else if (!strcasecmp(value, "off")) {
07068 ast_mutex_lock(&p->lock);
07069 dahdi_disable_ec(p);
07070 ast_mutex_unlock(&p->lock);
07071 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07072 } else if (!strcasecmp(value, "fax")) {
07073 int blah = 1;
07074
07075 ast_mutex_lock(&p->lock);
07076 if (!p->echocanon) {
07077 dahdi_enable_ec(p);
07078 }
07079 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07080 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07081 }
07082 ast_mutex_unlock(&p->lock);
07083 } else if (!strcasecmp(value, "voice")) {
07084 int blah = 0;
07085
07086 ast_mutex_lock(&p->lock);
07087 if (!p->echocanon) {
07088 dahdi_enable_ec(p);
07089 }
07090 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07091 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07092 }
07093 ast_mutex_unlock(&p->lock);
07094 #endif
07095 } else {
07096 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07097 res = -1;
07098 }
07099 } else {
07100 res = -1;
07101 }
07102
07103 return res;
07104 }
07105
07106 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07107 {
07108
07109 int x;
07110 int hasslaves;
07111 if (!master)
07112 return;
07113 if (needlock) {
07114 ast_mutex_lock(&master->lock);
07115 if (slave) {
07116 while (ast_mutex_trylock(&slave->lock)) {
07117 DEADLOCK_AVOIDANCE(&master->lock);
07118 }
07119 }
07120 }
07121 hasslaves = 0;
07122 for (x = 0; x < MAX_SLAVES; x++) {
07123 if (master->slaves[x]) {
07124 if (!slave || (master->slaves[x] == slave)) {
07125
07126 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07127 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07128 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07129 master->slaves[x]->master = NULL;
07130 master->slaves[x] = NULL;
07131 } else
07132 hasslaves = 1;
07133 }
07134 if (!hasslaves)
07135 master->inconference = 0;
07136 }
07137 if (!slave) {
07138 if (master->master) {
07139
07140 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07141 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07142 hasslaves = 0;
07143 for (x = 0; x < MAX_SLAVES; x++) {
07144 if (master->master->slaves[x] == master)
07145 master->master->slaves[x] = NULL;
07146 else if (master->master->slaves[x])
07147 hasslaves = 1;
07148 }
07149 if (!hasslaves)
07150 master->master->inconference = 0;
07151 }
07152 master->master = NULL;
07153 }
07154 update_conf(master);
07155 if (needlock) {
07156 if (slave)
07157 ast_mutex_unlock(&slave->lock);
07158 ast_mutex_unlock(&master->lock);
07159 }
07160 }
07161
07162 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07163 int x;
07164 if (!slave || !master) {
07165 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07166 return;
07167 }
07168 for (x = 0; x < MAX_SLAVES; x++) {
07169 if (!master->slaves[x]) {
07170 master->slaves[x] = slave;
07171 break;
07172 }
07173 }
07174 if (x >= MAX_SLAVES) {
07175 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07176 master->slaves[MAX_SLAVES - 1] = slave;
07177 }
07178 if (slave->master)
07179 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07180 slave->master = master;
07181
07182 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07183 }
07184
07185 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)
07186 {
07187 struct ast_channel *who;
07188 struct dahdi_pvt *p0, *p1, *op0, *op1;
07189 struct dahdi_pvt *master = NULL, *slave = NULL;
07190 struct ast_frame *f;
07191 int inconf = 0;
07192 int nothingok = 1;
07193 int ofd0, ofd1;
07194 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07195 int os0 = -1, os1 = -1;
07196 int priority = 0;
07197 struct ast_channel *oc0, *oc1;
07198 enum ast_bridge_result res;
07199 #ifdef PRI_2BCT
07200 int triedtopribridge = 0;
07201 q931_call *q931c0;
07202 q931_call *q931c1;
07203 #endif
07204
07205
07206
07207
07208
07209
07210 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07211 return AST_BRIDGE_FAILED_NOWARN;
07212
07213 ast_channel_lock(c0);
07214 while (ast_channel_trylock(c1)) {
07215 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07216 }
07217
07218 p0 = c0->tech_pvt;
07219 p1 = c1->tech_pvt;
07220
07221 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07222 ast_channel_unlock(c0);
07223 ast_channel_unlock(c1);
07224 return AST_BRIDGE_FAILED_NOWARN;
07225 }
07226
07227 oi0 = dahdi_get_index(c0, p0, 0);
07228 oi1 = dahdi_get_index(c1, p1, 0);
07229 if ((oi0 < 0) || (oi1 < 0)) {
07230 ast_channel_unlock(c0);
07231 ast_channel_unlock(c1);
07232 return AST_BRIDGE_FAILED;
07233 }
07234
07235 op0 = p0 = c0->tech_pvt;
07236 op1 = p1 = c1->tech_pvt;
07237 ofd0 = c0->fds[0];
07238 ofd1 = c1->fds[0];
07239 oc0 = p0->owner;
07240 oc1 = p1->owner;
07241
07242 if (ast_mutex_trylock(&p0->lock)) {
07243
07244 ast_channel_unlock(c0);
07245 ast_channel_unlock(c1);
07246 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07247 return AST_BRIDGE_RETRY;
07248 }
07249 if (ast_mutex_trylock(&p1->lock)) {
07250
07251 ast_mutex_unlock(&p0->lock);
07252 ast_channel_unlock(c0);
07253 ast_channel_unlock(c1);
07254 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07255 return AST_BRIDGE_RETRY;
07256 }
07257
07258 if ((p0->callwaiting && p0->callwaitingcallerid)
07259 || (p1->callwaiting && p1->callwaitingcallerid)) {
07260
07261
07262
07263
07264
07265
07266
07267
07268
07269 ast_mutex_unlock(&p0->lock);
07270 ast_mutex_unlock(&p1->lock);
07271 ast_channel_unlock(c0);
07272 ast_channel_unlock(c1);
07273 return AST_BRIDGE_FAILED_NOWARN;
07274 }
07275
07276 #if defined(HAVE_PRI)
07277 if ((dahdi_sig_pri_lib_handles(p0->sig)
07278 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07279 || (dahdi_sig_pri_lib_handles(p1->sig)
07280 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07281
07282
07283
07284
07285 ast_mutex_unlock(&p0->lock);
07286 ast_mutex_unlock(&p1->lock);
07287 ast_channel_unlock(c0);
07288 ast_channel_unlock(c1);
07289 return AST_BRIDGE_FAILED_NOWARN;
07290 }
07291 #endif
07292
07293 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07294 if (p0->owner && p1->owner) {
07295
07296 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07297 master = p0;
07298 slave = p1;
07299 inconf = 1;
07300 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07301 master = p1;
07302 slave = p0;
07303 inconf = 1;
07304 } else {
07305 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07306 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07307 p0->channel,
07308 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07309 p0->subs[SUB_REAL].inthreeway, p0->channel,
07310 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07311 p1->subs[SUB_REAL].inthreeway);
07312 }
07313 nothingok = 0;
07314 }
07315 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07316 if (p1->subs[SUB_THREEWAY].inthreeway) {
07317 master = p1;
07318 slave = p0;
07319 nothingok = 0;
07320 }
07321 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07322 if (p0->subs[SUB_THREEWAY].inthreeway) {
07323 master = p0;
07324 slave = p1;
07325 nothingok = 0;
07326 }
07327 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07328
07329
07330 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07331 master = p1;
07332 slave = p0;
07333 nothingok = 0;
07334 }
07335 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07336
07337 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07338 master = p0;
07339 slave = p1;
07340 nothingok = 0;
07341 }
07342 }
07343 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07344 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07345 if (master && slave) {
07346
07347
07348
07349 if ((oi1 == SUB_THREEWAY) &&
07350 p1->subs[SUB_THREEWAY].inthreeway &&
07351 p1->subs[SUB_REAL].owner &&
07352 p1->subs[SUB_REAL].inthreeway &&
07353 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07354 ast_debug(1,
07355 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07356 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07357 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07358 os1 = p1->subs[SUB_REAL].owner->_state;
07359 } else {
07360 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07361 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07362 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07363 }
07364 if ((oi0 == SUB_THREEWAY) &&
07365 p0->subs[SUB_THREEWAY].inthreeway &&
07366 p0->subs[SUB_REAL].owner &&
07367 p0->subs[SUB_REAL].inthreeway &&
07368 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07369 ast_debug(1,
07370 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07371 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07372 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07373 os0 = p0->subs[SUB_REAL].owner->_state;
07374 } else {
07375 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07376 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07377 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07378 }
07379 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07380 if (!p0->echocanbridged || !p1->echocanbridged) {
07381
07382 dahdi_disable_ec(p0);
07383 dahdi_disable_ec(p1);
07384 }
07385 }
07386 dahdi_link(slave, master);
07387 master->inconference = inconf;
07388 } else if (!nothingok)
07389 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07390
07391 update_conf(p0);
07392 update_conf(p1);
07393 t0 = p0->subs[SUB_REAL].inthreeway;
07394 t1 = p1->subs[SUB_REAL].inthreeway;
07395
07396 ast_mutex_unlock(&p0->lock);
07397 ast_mutex_unlock(&p1->lock);
07398
07399 ast_channel_unlock(c0);
07400 ast_channel_unlock(c1);
07401
07402
07403 if ((!master || !slave) && !nothingok) {
07404 dahdi_enable_ec(p0);
07405 dahdi_enable_ec(p1);
07406 return AST_BRIDGE_FAILED;
07407 }
07408
07409 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07410
07411 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07412 disable_dtmf_detect(op0);
07413
07414 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07415 disable_dtmf_detect(op1);
07416
07417 for (;;) {
07418 struct ast_channel *c0_priority[2] = {c0, c1};
07419 struct ast_channel *c1_priority[2] = {c1, c0};
07420
07421
07422
07423
07424 ast_channel_lock(c0);
07425 while (ast_channel_trylock(c1)) {
07426 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07427 }
07428
07429 p0 = c0->tech_pvt;
07430 p1 = c1->tech_pvt;
07431
07432 if (op0 == p0)
07433 i0 = dahdi_get_index(c0, p0, 1);
07434 if (op1 == p1)
07435 i1 = dahdi_get_index(c1, p1, 1);
07436
07437 ast_channel_unlock(c0);
07438 ast_channel_unlock(c1);
07439
07440 if (!timeoutms ||
07441 (op0 != p0) ||
07442 (op1 != p1) ||
07443 (ofd0 != c0->fds[0]) ||
07444 (ofd1 != c1->fds[0]) ||
07445 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07446 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07447 (oc0 != p0->owner) ||
07448 (oc1 != p1->owner) ||
07449 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07450 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07451 (oi0 != i0) ||
07452 (oi1 != i1)) {
07453 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07454 op0->channel, oi0, op1->channel, oi1);
07455 res = AST_BRIDGE_RETRY;
07456 goto return_from_bridge;
07457 }
07458
07459 #ifdef PRI_2BCT
07460 if (!triedtopribridge) {
07461 triedtopribridge = 1;
07462 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07463 ast_mutex_lock(&p0->pri->lock);
07464 switch (p0->sig) {
07465 case SIG_PRI_LIB_HANDLE_CASES:
07466 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07467 break;
07468 default:
07469 q931c0 = NULL;
07470 break;
07471 }
07472 switch (p1->sig) {
07473 case SIG_PRI_LIB_HANDLE_CASES:
07474 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07475 break;
07476 default:
07477 q931c1 = NULL;
07478 break;
07479 }
07480 if (q931c0 && q931c1) {
07481 pri_channel_bridge(q931c0, q931c1);
07482 }
07483 ast_mutex_unlock(&p0->pri->lock);
07484 }
07485 }
07486 #endif
07487
07488 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07489 if (!who) {
07490 ast_debug(1, "Ooh, empty read...\n");
07491 continue;
07492 }
07493 f = ast_read(who);
07494 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07495 *fo = f;
07496 *rc = who;
07497 res = AST_BRIDGE_COMPLETE;
07498 goto return_from_bridge;
07499 }
07500 if (f->frametype == AST_FRAME_DTMF) {
07501 if ((who == c0) && p0->pulsedial) {
07502 ast_write(c1, f);
07503 } else if ((who == c1) && p1->pulsedial) {
07504 ast_write(c0, f);
07505 } else {
07506 *fo = f;
07507 *rc = who;
07508 res = AST_BRIDGE_COMPLETE;
07509 goto return_from_bridge;
07510 }
07511 }
07512 ast_frfree(f);
07513
07514
07515 priority = !priority;
07516 }
07517
07518 return_from_bridge:
07519 if (op0 == p0)
07520 dahdi_enable_ec(p0);
07521
07522 if (op1 == p1)
07523 dahdi_enable_ec(p1);
07524
07525 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07526 enable_dtmf_detect(op0);
07527
07528 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07529 enable_dtmf_detect(op1);
07530
07531 dahdi_unlink(slave, master, 1);
07532
07533 return res;
07534 }
07535
07536 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07537 {
07538 struct dahdi_pvt *p = newchan->tech_pvt;
07539 int x;
07540
07541 ast_mutex_lock(&p->lock);
07542
07543 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07544 if (p->owner == oldchan) {
07545 p->owner = newchan;
07546 }
07547 for (x = 0; x < 3; x++) {
07548 if (p->subs[x].owner == oldchan) {
07549 if (!x) {
07550 dahdi_unlink(NULL, p, 0);
07551 }
07552 p->subs[x].owner = newchan;
07553 }
07554 }
07555 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07556 analog_fixup(oldchan, newchan, p->sig_pvt);
07557 #if defined(HAVE_PRI)
07558 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07559 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07560 #endif
07561 #if defined(HAVE_SS7)
07562 } else if (p->sig == SIG_SS7) {
07563 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07564 #endif
07565 }
07566 update_conf(p);
07567
07568 ast_mutex_unlock(&p->lock);
07569
07570 if (newchan->_state == AST_STATE_RINGING) {
07571 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07572 }
07573 return 0;
07574 }
07575
07576 static int dahdi_ring_phone(struct dahdi_pvt *p)
07577 {
07578 int x;
07579 int res;
07580
07581 x = 0;
07582 x = DAHDI_ONHOOK;
07583 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07584 do {
07585 x = DAHDI_RING;
07586 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07587 if (res) {
07588 switch (errno) {
07589 case EBUSY:
07590 case EINTR:
07591
07592 usleep(10000);
07593 continue;
07594 case EINPROGRESS:
07595 res = 0;
07596 break;
07597 default:
07598 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07599 res = 0;
07600 }
07601 }
07602 } while (res);
07603 return res;
07604 }
07605
07606 static void *analog_ss_thread(void *data);
07607
07608 static int attempt_transfer(struct dahdi_pvt *p)
07609 {
07610
07611
07612
07613 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07614
07615
07616 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07617 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07618 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07619 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07620 }
07621 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07622 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07623 }
07624 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07625 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07626 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07627 return -1;
07628 }
07629
07630 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07631 unalloc_sub(p, SUB_THREEWAY);
07632 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07633 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07634 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07635 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07636 }
07637 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07638 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07639 }
07640 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07641 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07642 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07643 return -1;
07644 }
07645
07646 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07647 ast_channel_unlock(p->subs[SUB_REAL].owner);
07648 unalloc_sub(p, SUB_THREEWAY);
07649
07650 return 1;
07651 } else {
07652 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07653 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07654 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07655 return -1;
07656 }
07657 return 0;
07658 }
07659
07660 static int check_for_conference(struct dahdi_pvt *p)
07661 {
07662 struct dahdi_confinfo ci;
07663
07664 if (p->master || (p->confno > -1))
07665 return 0;
07666 memset(&ci, 0, sizeof(ci));
07667 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07668 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07669 return 0;
07670 }
07671
07672
07673
07674 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07675 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07676 return 1;
07677 }
07678 return 0;
07679 }
07680
07681
07682
07683
07684
07685
07686 static int get_alarms(struct dahdi_pvt *p)
07687 {
07688 int res;
07689 struct dahdi_spaninfo zi;
07690 struct dahdi_params params;
07691
07692 memset(&zi, 0, sizeof(zi));
07693 zi.spanno = p->span;
07694
07695 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07696 if (zi.alarms != DAHDI_ALARM_NONE)
07697 return zi.alarms;
07698 } else {
07699 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07700 return 0;
07701 }
07702
07703
07704 memset(¶ms, 0, sizeof(params));
07705 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07706 return params.chan_alarms;
07707
07708 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07709
07710 return DAHDI_ALARM_NONE;
07711 }
07712
07713 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07714 {
07715 struct dahdi_pvt *p = ast->tech_pvt;
07716 struct ast_frame *f = *dest;
07717
07718 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07719 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07720 f->subclass.integer, f->subclass.integer, ast->name);
07721
07722 if (p->confirmanswer) {
07723 if (f->frametype == AST_FRAME_DTMF_END) {
07724 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07725
07726
07727 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07728 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07729
07730 p->confirmanswer = 0;
07731 } else {
07732 p->subs[idx].f.frametype = AST_FRAME_NULL;
07733 p->subs[idx].f.subclass.integer = 0;
07734 }
07735 *dest = &p->subs[idx].f;
07736 } else if (p->callwaitcas) {
07737 if (f->frametype == AST_FRAME_DTMF_END) {
07738 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07739 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07740 ast_free(p->cidspill);
07741 p->cidspill = NULL;
07742 send_cwcidspill(p);
07743 }
07744 p->callwaitcas = 0;
07745 }
07746 p->subs[idx].f.frametype = AST_FRAME_NULL;
07747 p->subs[idx].f.subclass.integer = 0;
07748 *dest = &p->subs[idx].f;
07749 } else if (f->subclass.integer == 'f') {
07750 if (f->frametype == AST_FRAME_DTMF_END) {
07751
07752 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07753
07754 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07755 struct dahdi_bufferinfo bi = {
07756 .txbufpolicy = p->faxbuf_policy,
07757 .bufsize = p->bufsize,
07758 .numbufs = p->faxbuf_no
07759 };
07760 int res;
07761
07762 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07763 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07764 } else {
07765 p->bufferoverrideinuse = 1;
07766 }
07767 }
07768 p->faxhandled = 1;
07769 if (p->dsp) {
07770 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07771 ast_dsp_set_features(p->dsp, p->dsp_features);
07772 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07773 }
07774 if (strcmp(ast->exten, "fax")) {
07775 const char *target_context = S_OR(ast->macrocontext, ast->context);
07776
07777
07778
07779
07780
07781 ast_mutex_unlock(&p->lock);
07782 ast_channel_unlock(ast);
07783 if (ast_exists_extension(ast, target_context, "fax", 1,
07784 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07785 ast_channel_lock(ast);
07786 ast_mutex_lock(&p->lock);
07787 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07788
07789 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07790 if (ast_async_goto(ast, target_context, "fax", 1))
07791 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07792 } else {
07793 ast_channel_lock(ast);
07794 ast_mutex_lock(&p->lock);
07795 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07796 }
07797 } else {
07798 ast_debug(1, "Already in a fax extension, not redirecting\n");
07799 }
07800 } else {
07801 ast_debug(1, "Fax already handled\n");
07802 }
07803 dahdi_confmute(p, 0);
07804 }
07805 p->subs[idx].f.frametype = AST_FRAME_NULL;
07806 p->subs[idx].f.subclass.integer = 0;
07807 *dest = &p->subs[idx].f;
07808 }
07809 }
07810
07811 static void handle_alarms(struct dahdi_pvt *p, int alms)
07812 {
07813 const char *alarm_str = alarm2str(alms);
07814
07815 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07816 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07817 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07818 "Alarm: %s\r\n"
07819 "Channel: %d\r\n",
07820 alarm_str, p->channel);
07821 }
07822
07823 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07824 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07825 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07826 "Alarm: %s\r\n"
07827 "Span: %d\r\n",
07828 alarm_str, p->span);
07829 }
07830 }
07831
07832 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07833 {
07834 int res, x;
07835 int idx, mysig;
07836 char *c;
07837 struct dahdi_pvt *p = ast->tech_pvt;
07838 pthread_t threadid;
07839 struct ast_channel *chan;
07840 struct ast_frame *f;
07841
07842 idx = dahdi_get_index(ast, p, 0);
07843 mysig = p->sig;
07844 if (p->outsigmod > -1)
07845 mysig = p->outsigmod;
07846 p->subs[idx].f.frametype = AST_FRAME_NULL;
07847 p->subs[idx].f.subclass.integer = 0;
07848 p->subs[idx].f.datalen = 0;
07849 p->subs[idx].f.samples = 0;
07850 p->subs[idx].f.mallocd = 0;
07851 p->subs[idx].f.offset = 0;
07852 p->subs[idx].f.src = "dahdi_handle_event";
07853 p->subs[idx].f.data.ptr = NULL;
07854 f = &p->subs[idx].f;
07855
07856 if (idx < 0)
07857 return &p->subs[idx].f;
07858 if (p->fake_event) {
07859 res = p->fake_event;
07860 p->fake_event = 0;
07861 } else
07862 res = dahdi_get_event(p->subs[idx].dfd);
07863
07864 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07865
07866 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07867 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07868 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07869 #if defined(HAVE_PRI)
07870 if (dahdi_sig_pri_lib_handles(p->sig)
07871 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07872 && p->pri
07873 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07874
07875 } else
07876 #endif
07877 {
07878
07879 dahdi_confmute(p, 0);
07880 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07881 p->subs[idx].f.subclass.integer = res & 0xff;
07882 dahdi_handle_dtmf(ast, idx, &f);
07883 }
07884 return f;
07885 }
07886
07887 if (res & DAHDI_EVENT_DTMFDOWN) {
07888 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07889 #if defined(HAVE_PRI)
07890 if (dahdi_sig_pri_lib_handles(p->sig)
07891 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07892 && p->pri
07893 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07894
07895 } else
07896 #endif
07897 {
07898
07899 dahdi_confmute(p, 1);
07900 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07901 p->subs[idx].f.subclass.integer = res & 0xff;
07902 dahdi_handle_dtmf(ast, idx, &f);
07903 }
07904 return &p->subs[idx].f;
07905 }
07906
07907 switch (res) {
07908 case DAHDI_EVENT_EC_DISABLED:
07909 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07910 p->echocanon = 0;
07911 break;
07912 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07913 case DAHDI_EVENT_TX_CED_DETECTED:
07914 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07915 break;
07916 case DAHDI_EVENT_RX_CED_DETECTED:
07917 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07918 break;
07919 case DAHDI_EVENT_EC_NLP_DISABLED:
07920 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07921 break;
07922 case DAHDI_EVENT_EC_NLP_ENABLED:
07923 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07924 break;
07925 #endif
07926 case DAHDI_EVENT_BITSCHANGED:
07927 #ifdef HAVE_OPENR2
07928 if (p->sig != SIG_MFCR2) {
07929 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07930 } else {
07931 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07932 openr2_chan_handle_cas(p->r2chan);
07933 }
07934 #else
07935 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07936 #endif
07937 case DAHDI_EVENT_PULSE_START:
07938
07939 if (!ast->pbx)
07940 tone_zone_play_tone(p->subs[idx].dfd, -1);
07941 break;
07942 case DAHDI_EVENT_DIALCOMPLETE:
07943
07944 #if defined(HAVE_PRI)
07945 if (dahdi_sig_pri_lib_handles(p->sig)) {
07946 if (p->inalarm) {
07947 break;
07948 }
07949 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
07950 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
07951 strerror(errno));
07952 return NULL;
07953 }
07954 if (x) {
07955
07956 break;
07957 }
07958
07959
07960
07961
07962 sig_pri_dial_complete(p->sig_pvt, ast);
07963 break;
07964 }
07965 #endif
07966 #ifdef HAVE_OPENR2
07967 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07968
07969
07970 break;
07971 }
07972 #endif
07973 if (p->inalarm) break;
07974 if ((p->radio || (p->oprmode < 0))) break;
07975 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07976 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07977 return NULL;
07978 }
07979 if (!x) {
07980 dahdi_enable_ec(p);
07981 if (p->echobreak) {
07982 dahdi_train_ec(p);
07983 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07984 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07985 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07986 p->echobreak = 0;
07987 } else {
07988 p->dialing = 0;
07989 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07990
07991 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07992 ast_setstate(ast, AST_STATE_UP);
07993 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07994 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07995 break;
07996 } else {
07997
07998 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07999 }
08000 }
08001 if (ast->_state == AST_STATE_DIALING) {
08002 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08003 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08004 } else if (p->confirmanswer || (!p->dialednone
08005 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08006 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08007 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08008 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08009 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08010 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08011 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08012 || (mysig == SIG_SF_FEATB)))) {
08013 ast_setstate(ast, AST_STATE_RINGING);
08014 } else if (!p->answeronpolarityswitch) {
08015 ast_setstate(ast, AST_STATE_UP);
08016 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08017 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08018
08019 p->polarity = POLARITY_REV;
08020 } else {
08021
08022 p->polarity = POLARITY_IDLE;
08023 }
08024 }
08025 }
08026 }
08027 break;
08028 case DAHDI_EVENT_ALARM:
08029 switch (p->sig) {
08030 #if defined(HAVE_PRI)
08031 case SIG_PRI_LIB_HANDLE_CASES:
08032 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08033 break;
08034 #endif
08035 #if defined(HAVE_SS7)
08036 case SIG_SS7:
08037 sig_ss7_set_alarm(p->sig_pvt, 1);
08038 break;
08039 #endif
08040 default:
08041 p->inalarm = 1;
08042 break;
08043 }
08044 res = get_alarms(p);
08045 handle_alarms(p, res);
08046 #ifdef HAVE_PRI
08047 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08048
08049 } else {
08050 break;
08051 }
08052 #endif
08053 #if defined(HAVE_SS7)
08054 if (p->sig == SIG_SS7)
08055 break;
08056 #endif
08057 #ifdef HAVE_OPENR2
08058 if (p->sig == SIG_MFCR2)
08059 break;
08060 #endif
08061 case DAHDI_EVENT_ONHOOK:
08062 if (p->radio) {
08063 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08064 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08065 break;
08066 }
08067 if (p->oprmode < 0)
08068 {
08069 if (p->oprmode != -1) break;
08070 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08071 {
08072
08073 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08074 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08075 save_conference(p->oprpeer);
08076 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08077 }
08078 break;
08079 }
08080 switch (p->sig) {
08081 case SIG_FXOLS:
08082 case SIG_FXOGS:
08083 case SIG_FXOKS:
08084
08085 if (idx == SUB_REAL) {
08086
08087 if (p->subs[SUB_CALLWAIT].owner) {
08088
08089 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08090 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08091 unalloc_sub(p, SUB_CALLWAIT);
08092 #if 0
08093 p->subs[idx].needanswer = 0;
08094 p->subs[idx].needringing = 0;
08095 #endif
08096 p->callwaitingrepeat = 0;
08097 p->cidcwexpire = 0;
08098 p->cid_suppress_expire = 0;
08099 p->owner = NULL;
08100
08101 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08102 p->dialing = 1;
08103 dahdi_ring_phone(p);
08104 } else if (p->subs[SUB_THREEWAY].owner) {
08105 unsigned int mssinceflash;
08106
08107
08108 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08109
08110 DLA_UNLOCK(&p->lock);
08111 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08112
08113
08114
08115 DLA_LOCK(&p->lock);
08116 if (p->owner != ast) {
08117 ast_log(LOG_WARNING, "This isn't good...\n");
08118 return NULL;
08119 }
08120 }
08121 if (!p->subs[SUB_THREEWAY].owner) {
08122 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08123 return NULL;
08124 }
08125 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08126 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08127 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08128
08129
08130 if (p->subs[SUB_THREEWAY].owner)
08131 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08132 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08133 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08134 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08135 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08136 if (p->transfer) {
08137
08138 p->subs[SUB_REAL].inthreeway = 0;
08139 p->subs[SUB_THREEWAY].inthreeway = 0;
08140
08141 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08142 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08143
08144 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08145 p->owner = NULL;
08146
08147 dahdi_ring_phone(p);
08148 } else {
08149 if ((res = attempt_transfer(p)) < 0) {
08150 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08151 if (p->subs[SUB_THREEWAY].owner)
08152 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08153 } else if (res) {
08154
08155 if (p->subs[SUB_THREEWAY].owner)
08156 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08157 break;
08158 }
08159 }
08160 } else {
08161 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08162 if (p->subs[SUB_THREEWAY].owner)
08163 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08164 }
08165 } else {
08166 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08167
08168 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08169 p->owner = NULL;
08170
08171 dahdi_ring_phone(p);
08172 }
08173 }
08174 } else {
08175 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08176 }
08177
08178 default:
08179 dahdi_disable_ec(p);
08180 return NULL;
08181 }
08182 break;
08183 case DAHDI_EVENT_RINGOFFHOOK:
08184 if (p->inalarm) break;
08185 if (p->oprmode < 0)
08186 {
08187 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08188 {
08189
08190 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08191 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08192 restore_conference(p->oprpeer);
08193 }
08194 break;
08195 }
08196 if (p->radio)
08197 {
08198 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08199 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08200 break;
08201 }
08202
08203
08204 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08205 c = strchr(p->dialdest, '/');
08206 if (c)
08207 c++;
08208 else
08209 c = p->dialdest;
08210 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08211 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08212 if (strlen(p->dop.dialstr) > 4) {
08213 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08214 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08215 p->echorest[sizeof(p->echorest) - 1] = '\0';
08216 p->echobreak = 1;
08217 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08218 } else
08219 p->echobreak = 0;
08220 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08221 int saveerr = errno;
08222
08223 x = DAHDI_ONHOOK;
08224 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08225 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08226 return NULL;
08227 }
08228 p->dialing = 1;
08229 return &p->subs[idx].f;
08230 }
08231 switch (p->sig) {
08232 case SIG_FXOLS:
08233 case SIG_FXOGS:
08234 case SIG_FXOKS:
08235 switch (ast->_state) {
08236 case AST_STATE_RINGING:
08237 dahdi_enable_ec(p);
08238 dahdi_train_ec(p);
08239 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08240 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08241
08242 p->subs[SUB_REAL].needringing = 0;
08243 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08244 ast_debug(1, "channel %d answered\n", p->channel);
08245
08246
08247 ast_free(p->cidspill);
08248 p->cidspill = NULL;
08249 restore_conference(p);
08250
08251 p->dialing = 0;
08252 p->callwaitcas = 0;
08253 if (p->confirmanswer) {
08254
08255 p->subs[idx].f.frametype = AST_FRAME_NULL;
08256 p->subs[idx].f.subclass.integer = 0;
08257 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08258
08259 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08260 if (res < 0) {
08261 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08262 p->dop.dialstr[0] = '\0';
08263 return NULL;
08264 } else {
08265 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08266 p->subs[idx].f.frametype = AST_FRAME_NULL;
08267 p->subs[idx].f.subclass.integer = 0;
08268 p->dialing = 1;
08269 }
08270 p->dop.dialstr[0] = '\0';
08271 ast_setstate(ast, AST_STATE_DIALING);
08272 } else
08273 ast_setstate(ast, AST_STATE_UP);
08274 return &p->subs[idx].f;
08275 case AST_STATE_DOWN:
08276 ast_setstate(ast, AST_STATE_RING);
08277 ast->rings = 1;
08278 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08279 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08280 ast_debug(1, "channel %d picked up\n", p->channel);
08281 return &p->subs[idx].f;
08282 case AST_STATE_UP:
08283
08284 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08285
08286 if (ast_bridged_channel(p->owner))
08287 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08288 p->subs[idx].needunhold = 1;
08289 break;
08290 case AST_STATE_RESERVED:
08291
08292 if (has_voicemail(p))
08293 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08294 else
08295 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08296 break;
08297 default:
08298 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08299 }
08300 break;
08301 case SIG_FXSLS:
08302 case SIG_FXSGS:
08303 case SIG_FXSKS:
08304 if (ast->_state == AST_STATE_RING) {
08305 p->ringt = p->ringt_base;
08306 }
08307
08308
08309
08310 ast_debug(1, "Setting IDLE polarity due "
08311 "to ring. Old polarity was %d\n",
08312 p->polarity);
08313 p->polarity = POLARITY_IDLE;
08314
08315
08316 case SIG_EM:
08317 case SIG_EM_E1:
08318 case SIG_EMWINK:
08319 case SIG_FEATD:
08320 case SIG_FEATDMF:
08321 case SIG_FEATDMF_TA:
08322 case SIG_E911:
08323 case SIG_FGC_CAMA:
08324 case SIG_FGC_CAMAMF:
08325 case SIG_FEATB:
08326 case SIG_SF:
08327 case SIG_SFWINK:
08328 case SIG_SF_FEATD:
08329 case SIG_SF_FEATDMF:
08330 case SIG_SF_FEATB:
08331 if (ast->_state == AST_STATE_PRERING)
08332 ast_setstate(ast, AST_STATE_RING);
08333 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08334 ast_debug(1, "Ring detected\n");
08335 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08336 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08337 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08338 ast_debug(1, "Line answered\n");
08339 if (p->confirmanswer) {
08340 p->subs[idx].f.frametype = AST_FRAME_NULL;
08341 p->subs[idx].f.subclass.integer = 0;
08342 } else {
08343 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08344 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08345 ast_setstate(ast, AST_STATE_UP);
08346 }
08347 } else if (ast->_state != AST_STATE_RING)
08348 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08349 break;
08350 default:
08351 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08352 }
08353 break;
08354 case DAHDI_EVENT_RINGBEGIN:
08355 switch (p->sig) {
08356 case SIG_FXSLS:
08357 case SIG_FXSGS:
08358 case SIG_FXSKS:
08359 if (ast->_state == AST_STATE_RING) {
08360 p->ringt = p->ringt_base;
08361 }
08362 break;
08363 }
08364 break;
08365 case DAHDI_EVENT_RINGERON:
08366 break;
08367 case DAHDI_EVENT_NOALARM:
08368 switch (p->sig) {
08369 #if defined(HAVE_PRI)
08370 case SIG_PRI_LIB_HANDLE_CASES:
08371 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08372 break;
08373 #endif
08374 #if defined(HAVE_SS7)
08375 case SIG_SS7:
08376 sig_ss7_set_alarm(p->sig_pvt, 0);
08377 break;
08378 #endif
08379 default:
08380 p->inalarm = 0;
08381 break;
08382 }
08383 handle_clear_alarms(p);
08384 break;
08385 case DAHDI_EVENT_WINKFLASH:
08386 if (p->inalarm) break;
08387 if (p->radio) break;
08388 if (p->oprmode < 0) break;
08389 if (p->oprmode > 1)
08390 {
08391 struct dahdi_params par;
08392
08393 memset(&par, 0, sizeof(par));
08394 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08395 {
08396 if (!par.rxisoffhook)
08397 {
08398
08399 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08400 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08401 save_conference(p);
08402 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08403 }
08404 }
08405 break;
08406 }
08407
08408 p->flashtime = ast_tvnow();
08409 switch (mysig) {
08410 case SIG_FXOLS:
08411 case SIG_FXOGS:
08412 case SIG_FXOKS:
08413 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08414 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08415
08416
08417 ast_free(p->cidspill);
08418 p->cidspill = NULL;
08419 restore_conference(p);
08420 p->callwaitcas = 0;
08421
08422 if (idx != SUB_REAL) {
08423 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08424 goto winkflashdone;
08425 }
08426
08427 if (p->subs[SUB_CALLWAIT].owner) {
08428
08429 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08430 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08431 p->owner = p->subs[SUB_REAL].owner;
08432 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08433 if (p->owner->_state == AST_STATE_RINGING) {
08434 ast_setstate(p->owner, AST_STATE_UP);
08435 p->subs[SUB_REAL].needanswer = 1;
08436 }
08437 p->callwaitingrepeat = 0;
08438 p->cidcwexpire = 0;
08439 p->cid_suppress_expire = 0;
08440
08441 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08442 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08443 S_OR(p->mohsuggest, NULL),
08444 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08445 }
08446 p->subs[SUB_CALLWAIT].needhold = 1;
08447 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08448 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08449 S_OR(p->mohsuggest, NULL),
08450 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08451 }
08452 p->subs[SUB_REAL].needunhold = 1;
08453 } else if (!p->subs[SUB_THREEWAY].owner) {
08454 if (!p->threewaycalling) {
08455
08456 p->subs[SUB_REAL].needflash = 1;
08457 goto winkflashdone;
08458 } else if (!check_for_conference(p)) {
08459 char cid_num[256];
08460 char cid_name[256];
08461
08462 cid_num[0] = 0;
08463 cid_name[0] = 0;
08464 if (p->dahditrcallerid && p->owner) {
08465 if (p->owner->caller.id.number.valid
08466 && p->owner->caller.id.number.str) {
08467 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08468 sizeof(cid_num));
08469 }
08470 if (p->owner->caller.id.name.valid
08471 && p->owner->caller.id.name.str) {
08472 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08473 sizeof(cid_name));
08474 }
08475 }
08476
08477
08478 if (!((ast->pbx) ||
08479 (ast->_state == AST_STATE_UP) ||
08480 (ast->_state == AST_STATE_RING))) {
08481 ast_debug(1, "Flash when call not up or ringing\n");
08482 goto winkflashdone;
08483 }
08484 if (alloc_sub(p, SUB_THREEWAY)) {
08485 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08486 goto winkflashdone;
08487 }
08488
08489 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08490 if (p->dahditrcallerid) {
08491 if (!p->origcid_num)
08492 p->origcid_num = ast_strdup(p->cid_num);
08493 if (!p->origcid_name)
08494 p->origcid_name = ast_strdup(p->cid_name);
08495 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08496 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08497 }
08498
08499 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08500
08501 dahdi_disable_ec(p);
08502 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08503 if (res)
08504 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08505 p->owner = chan;
08506 if (!chan) {
08507 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08508 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08509 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08510 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08511 dahdi_enable_ec(p);
08512 ast_hangup(chan);
08513 } else {
08514 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08515
08516
08517 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08518 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08519 S_OR(p->mohsuggest, NULL),
08520 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08521 }
08522 p->subs[SUB_THREEWAY].needhold = 1;
08523 }
08524 }
08525 } else {
08526
08527 if (p->subs[SUB_THREEWAY].inthreeway) {
08528
08529 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08530
08531 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08532
08533 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08534 p->owner = p->subs[SUB_REAL].owner;
08535 }
08536
08537 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08538 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08539 p->subs[SUB_REAL].inthreeway = 0;
08540 p->subs[SUB_THREEWAY].inthreeway = 0;
08541 } else {
08542
08543 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08544 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08545 int otherindex = SUB_THREEWAY;
08546
08547 ast_verb(3, "Building conference call with %s and %s\n",
08548 p->subs[SUB_THREEWAY].owner->name,
08549 p->subs[SUB_REAL].owner->name);
08550
08551 p->subs[SUB_THREEWAY].inthreeway = 1;
08552 p->subs[SUB_REAL].inthreeway = 1;
08553 if (ast->_state == AST_STATE_UP) {
08554 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08555 otherindex = SUB_REAL;
08556 }
08557 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08558 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08559 p->subs[otherindex].needunhold = 1;
08560 p->owner = p->subs[SUB_REAL].owner;
08561 } else {
08562 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08563 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08564 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08565 p->owner = p->subs[SUB_REAL].owner;
08566 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08567 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08568 p->subs[SUB_REAL].needunhold = 1;
08569 dahdi_enable_ec(p);
08570 }
08571 }
08572 }
08573 winkflashdone:
08574 update_conf(p);
08575 break;
08576 case SIG_EM:
08577 case SIG_EM_E1:
08578 case SIG_FEATD:
08579 case SIG_SF:
08580 case SIG_SFWINK:
08581 case SIG_SF_FEATD:
08582 case SIG_FXSLS:
08583 case SIG_FXSGS:
08584 if (p->dialing)
08585 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08586 else
08587 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08588 break;
08589 case SIG_FEATDMF_TA:
08590 switch (p->whichwink) {
08591 case 0:
08592 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08593 S_COR(p->owner->caller.ani.number.valid,
08594 p->owner->caller.ani.number.str, ""));
08595 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08596 p->owner->caller.ani2,
08597 S_COR(p->owner->caller.ani.number.valid,
08598 p->owner->caller.ani.number.str, ""));
08599 break;
08600 case 1:
08601 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08602 break;
08603 case 2:
08604 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08605 return NULL;
08606 }
08607 p->whichwink++;
08608
08609 case SIG_FEATDMF:
08610 case SIG_E911:
08611 case SIG_FGC_CAMAMF:
08612 case SIG_FGC_CAMA:
08613 case SIG_FEATB:
08614 case SIG_SF_FEATDMF:
08615 case SIG_SF_FEATB:
08616 case SIG_EMWINK:
08617
08618 if (!ast_strlen_zero(p->dop.dialstr)) {
08619 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08620 if (res < 0) {
08621 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08622 p->dop.dialstr[0] = '\0';
08623 return NULL;
08624 } else
08625 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08626 }
08627 p->dop.dialstr[0] = '\0';
08628 break;
08629 default:
08630 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08631 }
08632 break;
08633 case DAHDI_EVENT_HOOKCOMPLETE:
08634 if (p->inalarm) break;
08635 if ((p->radio || (p->oprmode < 0))) break;
08636 if (p->waitingfordt.tv_sec) break;
08637 switch (mysig) {
08638 case SIG_FXSLS:
08639 case SIG_FXSGS:
08640 case SIG_FXSKS:
08641 case SIG_EM:
08642 case SIG_EM_E1:
08643 case SIG_EMWINK:
08644 case SIG_FEATD:
08645 case SIG_SF:
08646 case SIG_SFWINK:
08647 case SIG_SF_FEATD:
08648 if (!ast_strlen_zero(p->dop.dialstr)) {
08649 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08650 if (res < 0) {
08651 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08652 p->dop.dialstr[0] = '\0';
08653 return NULL;
08654 } else
08655 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08656 }
08657 p->dop.dialstr[0] = '\0';
08658 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08659 break;
08660 case SIG_FEATDMF:
08661 case SIG_FEATDMF_TA:
08662 case SIG_E911:
08663 case SIG_FGC_CAMA:
08664 case SIG_FGC_CAMAMF:
08665 case SIG_FEATB:
08666 case SIG_SF_FEATDMF:
08667 case SIG_SF_FEATB:
08668 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08669 break;
08670 default:
08671 break;
08672 }
08673 break;
08674 case DAHDI_EVENT_POLARITY:
08675
08676
08677
08678
08679
08680
08681 if (p->polarity == POLARITY_IDLE) {
08682 p->polarity = POLARITY_REV;
08683 if (p->answeronpolarityswitch &&
08684 ((ast->_state == AST_STATE_DIALING) ||
08685 (ast->_state == AST_STATE_RINGING))) {
08686 ast_debug(1, "Answering on polarity switch!\n");
08687 ast_setstate(p->owner, AST_STATE_UP);
08688 if (p->hanguponpolarityswitch) {
08689 p->polaritydelaytv = ast_tvnow();
08690 }
08691 } else
08692 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08693 }
08694
08695
08696 if (p->hanguponpolarityswitch &&
08697 (p->polarityonanswerdelay > 0) &&
08698 (p->polarity == POLARITY_REV) &&
08699 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08700
08701 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) );
08702
08703 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08704 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08705 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08706 p->polarity = POLARITY_IDLE;
08707 } else
08708 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);
08709
08710 } else {
08711 p->polarity = POLARITY_IDLE;
08712 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08713 }
08714
08715 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) );
08716 break;
08717 default:
08718 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08719 }
08720 return &p->subs[idx].f;
08721 }
08722
08723 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08724 {
08725 int res;
08726 int idx;
08727 struct ast_frame *f;
08728 int usedindex = -1;
08729 struct dahdi_pvt *p = ast->tech_pvt;
08730
08731 idx = dahdi_get_index(ast, p, 1);
08732
08733 p->subs[idx].f.frametype = AST_FRAME_NULL;
08734 p->subs[idx].f.datalen = 0;
08735 p->subs[idx].f.samples = 0;
08736 p->subs[idx].f.mallocd = 0;
08737 p->subs[idx].f.offset = 0;
08738 p->subs[idx].f.subclass.integer = 0;
08739 p->subs[idx].f.delivery = ast_tv(0,0);
08740 p->subs[idx].f.src = "dahdi_exception";
08741 p->subs[idx].f.data.ptr = NULL;
08742
08743
08744 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08745
08746
08747
08748
08749
08750 if (p->fake_event) {
08751 res = p->fake_event;
08752 p->fake_event = 0;
08753 } else
08754 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08755
08756 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08757 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08758 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08759 p->owner = p->subs[SUB_REAL].owner;
08760 if (p->owner && ast_bridged_channel(p->owner))
08761 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08762 p->subs[SUB_REAL].needunhold = 1;
08763 }
08764 switch (res) {
08765 case DAHDI_EVENT_ONHOOK:
08766 dahdi_disable_ec(p);
08767 if (p->owner) {
08768 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08769 dahdi_ring_phone(p);
08770 p->callwaitingrepeat = 0;
08771 p->cidcwexpire = 0;
08772 p->cid_suppress_expire = 0;
08773 } else
08774 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08775 update_conf(p);
08776 break;
08777 case DAHDI_EVENT_RINGOFFHOOK:
08778 dahdi_enable_ec(p);
08779 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08780 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08781 p->subs[SUB_REAL].needanswer = 1;
08782 p->dialing = 0;
08783 }
08784 break;
08785 case DAHDI_EVENT_HOOKCOMPLETE:
08786 case DAHDI_EVENT_RINGERON:
08787 case DAHDI_EVENT_RINGEROFF:
08788
08789 break;
08790 case DAHDI_EVENT_WINKFLASH:
08791 p->flashtime = ast_tvnow();
08792 if (p->owner) {
08793 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08794 if (p->owner->_state != AST_STATE_UP) {
08795
08796 usedindex = dahdi_get_index(p->owner, p, 0);
08797 if (usedindex > -1) {
08798 p->subs[usedindex].needanswer = 1;
08799 }
08800 ast_setstate(p->owner, AST_STATE_UP);
08801 }
08802 p->callwaitingrepeat = 0;
08803 p->cidcwexpire = 0;
08804 p->cid_suppress_expire = 0;
08805 if (ast_bridged_channel(p->owner))
08806 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08807 p->subs[SUB_REAL].needunhold = 1;
08808 } else
08809 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08810 update_conf(p);
08811 break;
08812 default:
08813 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08814 }
08815 f = &p->subs[idx].f;
08816 return f;
08817 }
08818 if (!(p->radio || (p->oprmode < 0)))
08819 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08820
08821 if (ast != p->owner) {
08822 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08823 f = &p->subs[idx].f;
08824 return f;
08825 }
08826 f = dahdi_handle_event(ast);
08827
08828
08829 if (f == NULL) {
08830 ast_set_hangupsource(ast, ast->name, 0);
08831 }
08832
08833 return f;
08834 }
08835
08836 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08837 {
08838 struct dahdi_pvt *p = ast->tech_pvt;
08839 struct ast_frame *f;
08840 ast_mutex_lock(&p->lock);
08841 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08842 struct analog_pvt *analog_p = p->sig_pvt;
08843 f = analog_exception(analog_p, ast);
08844 } else {
08845 f = __dahdi_exception(ast);
08846 }
08847 ast_mutex_unlock(&p->lock);
08848 return f;
08849 }
08850
08851 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08852 {
08853 struct dahdi_pvt *p;
08854 int res;
08855 int idx;
08856 void *readbuf;
08857 struct ast_frame *f;
08858
08859
08860
08861
08862
08863
08864 p = ast->tech_pvt;
08865 while (ast_mutex_trylock(&p->lock)) {
08866 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08867
08868
08869
08870
08871
08872
08873 p = ast->tech_pvt;
08874 }
08875
08876 idx = dahdi_get_index(ast, p, 0);
08877
08878
08879 if (idx < 0) {
08880 ast_log(LOG_WARNING, "We don't exist?\n");
08881 ast_mutex_unlock(&p->lock);
08882 return NULL;
08883 }
08884
08885 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08886 ast_mutex_unlock(&p->lock);
08887 return NULL;
08888 }
08889
08890 p->subs[idx].f.frametype = AST_FRAME_NULL;
08891 p->subs[idx].f.datalen = 0;
08892 p->subs[idx].f.samples = 0;
08893 p->subs[idx].f.mallocd = 0;
08894 p->subs[idx].f.offset = 0;
08895 p->subs[idx].f.subclass.integer = 0;
08896 p->subs[idx].f.delivery = ast_tv(0,0);
08897 p->subs[idx].f.src = "dahdi_read";
08898 p->subs[idx].f.data.ptr = NULL;
08899
08900
08901 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08902 {
08903 struct dahdi_params ps;
08904
08905 memset(&ps, 0, sizeof(ps));
08906 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08907 ast_mutex_unlock(&p->lock);
08908 return NULL;
08909 }
08910 p->firstradio = 1;
08911 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08912 if (ps.rxisoffhook)
08913 {
08914 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08915 }
08916 else
08917 {
08918 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08919 }
08920 ast_mutex_unlock(&p->lock);
08921 return &p->subs[idx].f;
08922 }
08923 if (p->ringt > 0) {
08924 if (!(--p->ringt)) {
08925 ast_mutex_unlock(&p->lock);
08926 return NULL;
08927 }
08928 }
08929
08930 #ifdef HAVE_OPENR2
08931 if (p->mfcr2) {
08932 openr2_chan_process_event(p->r2chan);
08933 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08934 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08935
08936
08937 if (p->mfcr2_call_accepted &&
08938 !p->mfcr2_progress &&
08939 ast->_state == AST_STATE_RINGING) {
08940 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08941 ast_queue_frame(p->owner, &f);
08942 p->mfcr2_progress = 1;
08943 }
08944 }
08945 }
08946 #endif
08947
08948 if (p->subs[idx].needringing) {
08949
08950 p->subs[idx].needringing = 0;
08951 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08952 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08953 ast_setstate(ast, AST_STATE_RINGING);
08954 ast_mutex_unlock(&p->lock);
08955 return &p->subs[idx].f;
08956 }
08957
08958 if (p->subs[idx].needbusy) {
08959
08960 p->subs[idx].needbusy = 0;
08961 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08962 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08963 ast_mutex_unlock(&p->lock);
08964 return &p->subs[idx].f;
08965 }
08966
08967 if (p->subs[idx].needcongestion) {
08968
08969 p->subs[idx].needcongestion = 0;
08970 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08971 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08972 ast_mutex_unlock(&p->lock);
08973 return &p->subs[idx].f;
08974 }
08975
08976 if (p->subs[idx].needanswer) {
08977
08978 p->subs[idx].needanswer = 0;
08979 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08980 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08981 ast_mutex_unlock(&p->lock);
08982 return &p->subs[idx].f;
08983 }
08984 #ifdef HAVE_OPENR2
08985 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08986
08987
08988
08989
08990 ast_mutex_unlock(&p->lock);
08991 return &ast_null_frame;
08992 }
08993 #endif
08994
08995 if (p->subs[idx].needflash) {
08996
08997 p->subs[idx].needflash = 0;
08998 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08999 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09000 ast_mutex_unlock(&p->lock);
09001 return &p->subs[idx].f;
09002 }
09003
09004 if (p->subs[idx].needhold) {
09005
09006 p->subs[idx].needhold = 0;
09007 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09008 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09009 ast_mutex_unlock(&p->lock);
09010 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09011 return &p->subs[idx].f;
09012 }
09013
09014 if (p->subs[idx].needunhold) {
09015
09016 p->subs[idx].needunhold = 0;
09017 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09018 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09019 ast_mutex_unlock(&p->lock);
09020 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09021 return &p->subs[idx].f;
09022 }
09023
09024
09025
09026
09027
09028 if (p->fake_event && p->owner == ast) {
09029 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09030 struct analog_pvt *analog_p = p->sig_pvt;
09031
09032 f = analog_exception(analog_p, ast);
09033 } else {
09034 f = __dahdi_exception(ast);
09035 }
09036 ast_mutex_unlock(&p->lock);
09037 return f;
09038 }
09039
09040 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09041 if (!p->subs[idx].linear) {
09042 p->subs[idx].linear = 1;
09043 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09044 if (res)
09045 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09046 }
09047 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09048 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09049 if (p->subs[idx].linear) {
09050 p->subs[idx].linear = 0;
09051 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09052 if (res)
09053 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09054 }
09055 } else {
09056 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09057 ast_mutex_unlock(&p->lock);
09058 return NULL;
09059 }
09060 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09061 CHECK_BLOCKING(ast);
09062 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09063 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09064
09065 if (res < 0) {
09066 f = NULL;
09067 if (res == -1) {
09068 if (errno == EAGAIN) {
09069
09070 ast_mutex_unlock(&p->lock);
09071 return &p->subs[idx].f;
09072 } else if (errno == ELAST) {
09073 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09074 struct analog_pvt *analog_p = p->sig_pvt;
09075 f = analog_exception(analog_p, ast);
09076 } else {
09077 f = __dahdi_exception(ast);
09078 }
09079 } else
09080 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09081 }
09082 ast_mutex_unlock(&p->lock);
09083 return f;
09084 }
09085 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09086 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09087 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09088 struct analog_pvt *analog_p = p->sig_pvt;
09089 f = analog_exception(analog_p, ast);
09090 } else {
09091 f = __dahdi_exception(ast);
09092 }
09093 ast_mutex_unlock(&p->lock);
09094 return f;
09095 }
09096 if (p->tdd) {
09097 int c;
09098
09099 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09100 if (c < 0) {
09101 ast_debug(1,"tdd_feed failed\n");
09102 ast_mutex_unlock(&p->lock);
09103 return NULL;
09104 }
09105 if (c) {
09106 p->subs[idx].f.subclass.integer = 0;
09107 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09108 p->subs[idx].f.mallocd = 0;
09109 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09110 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09111 p->subs[idx].f.datalen = 1;
09112 *((char *) p->subs[idx].f.data.ptr) = c;
09113 ast_mutex_unlock(&p->lock);
09114 return &p->subs[idx].f;
09115 }
09116 }
09117 if (idx == SUB_REAL) {
09118
09119 if (p->cidcwexpire) {
09120 if (!--p->cidcwexpire) {
09121
09122 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09123 restore_conference(p);
09124 }
09125 }
09126 if (p->cid_suppress_expire) {
09127 --p->cid_suppress_expire;
09128 }
09129 if (p->callwaitingrepeat) {
09130 if (!--p->callwaitingrepeat) {
09131
09132 ++p->callwaitrings;
09133 dahdi_callwait(ast);
09134 }
09135 }
09136 }
09137 if (p->subs[idx].linear) {
09138 p->subs[idx].f.datalen = READ_SIZE * 2;
09139 } else
09140 p->subs[idx].f.datalen = READ_SIZE;
09141
09142
09143 if ((p->owner == ast) && p->cidspill) {
09144 send_callerid(p);
09145 }
09146
09147 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09148 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09149 p->subs[idx].f.samples = READ_SIZE;
09150 p->subs[idx].f.mallocd = 0;
09151 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09152 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09153 #if 0
09154 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09155 #endif
09156 if (p->dialing || p->radio ||
09157 (idx && (ast->_state != AST_STATE_UP)) ||
09158 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09159 ) {
09160
09161
09162 p->subs[idx].f.frametype = AST_FRAME_NULL;
09163 p->subs[idx].f.subclass.integer = 0;
09164 p->subs[idx].f.samples = 0;
09165 p->subs[idx].f.mallocd = 0;
09166 p->subs[idx].f.offset = 0;
09167 p->subs[idx].f.data.ptr = NULL;
09168 p->subs[idx].f.datalen= 0;
09169 }
09170 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09171
09172 int mute;
09173
09174 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09175
09176
09177 mute = ast_dsp_was_muted(p->dsp);
09178 if (p->muting != mute) {
09179 p->muting = mute;
09180 dahdi_confmute(p, mute);
09181 }
09182
09183 if (f) {
09184 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09185 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09186
09187
09188 f = NULL;
09189 }
09190 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09191 || f->frametype == AST_FRAME_DTMF_END) {
09192 #ifdef HAVE_PRI
09193 if (dahdi_sig_pri_lib_handles(p->sig)
09194 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09195 && p->pri
09196 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09197 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09198
09199 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09200 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09201 f->subclass.integer, f->subclass.integer, ast->name);
09202
09203 f->frametype = AST_FRAME_NULL;
09204 f->subclass.integer = 0;
09205 }
09206 #endif
09207
09208 p->pulsedial = 0;
09209 } else if (p->waitingfordt.tv_sec) {
09210 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09211 p->waitingfordt.tv_sec = 0;
09212 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09213 f=NULL;
09214 } else if (f->frametype == AST_FRAME_VOICE) {
09215 f->frametype = AST_FRAME_NULL;
09216 f->subclass.integer = 0;
09217 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) {
09218 p->waitingfordt.tv_sec = 0;
09219 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09220 ast_dsp_set_features(p->dsp, p->dsp_features);
09221 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09222 if (!ast_strlen_zero(p->dop.dialstr)) {
09223 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09224 if (res < 0) {
09225 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09226 p->dop.dialstr[0] = '\0';
09227 ast_mutex_unlock(&p->lock);
09228 return NULL;
09229 } else {
09230 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09231 p->dialing = 1;
09232 p->dop.dialstr[0] = '\0';
09233 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09234 ast_setstate(ast, AST_STATE_DIALING);
09235 }
09236 }
09237 }
09238 }
09239 }
09240 }
09241 } else
09242 f = &p->subs[idx].f;
09243
09244 if (f) {
09245 switch (f->frametype) {
09246 case AST_FRAME_DTMF_BEGIN:
09247 case AST_FRAME_DTMF_END:
09248 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09249 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09250 } else {
09251 dahdi_handle_dtmf(ast, idx, &f);
09252 }
09253 break;
09254 case AST_FRAME_VOICE:
09255 if (p->cidspill || p->cid_suppress_expire) {
09256
09257 p->subs[idx].f.frametype = AST_FRAME_NULL;
09258 p->subs[idx].f.subclass.integer = 0;
09259 p->subs[idx].f.samples = 0;
09260 p->subs[idx].f.mallocd = 0;
09261 p->subs[idx].f.offset = 0;
09262 p->subs[idx].f.data.ptr = NULL;
09263 p->subs[idx].f.datalen= 0;
09264 }
09265 break;
09266 default:
09267 break;
09268 }
09269 }
09270
09271 ast_mutex_unlock(&p->lock);
09272 return f;
09273 }
09274
09275 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09276 {
09277 int sent=0;
09278 int size;
09279 int res;
09280 int fd;
09281 fd = p->subs[idx].dfd;
09282 while (len) {
09283 size = len;
09284 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09285 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09286 res = write(fd, buf, size);
09287 if (res != size) {
09288 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09289 return sent;
09290 }
09291 len -= size;
09292 buf += size;
09293 }
09294 return sent;
09295 }
09296
09297 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09298 {
09299 struct dahdi_pvt *p = ast->tech_pvt;
09300 int res;
09301 int idx;
09302 idx = dahdi_get_index(ast, p, 0);
09303 if (idx < 0) {
09304 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09305 return -1;
09306 }
09307
09308
09309 if (frame->frametype != AST_FRAME_VOICE) {
09310 if (frame->frametype != AST_FRAME_IMAGE)
09311 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09312 return 0;
09313 }
09314 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09315 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09316 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09317 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09318 return -1;
09319 }
09320 if (p->dialing) {
09321 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09322 return 0;
09323 }
09324 if (!p->owner) {
09325 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09326 return 0;
09327 }
09328 if (p->cidspill) {
09329 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09330 ast->name);
09331 return 0;
09332 }
09333
09334 if (!frame->data.ptr || !frame->datalen)
09335 return 0;
09336
09337 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09338 if (!p->subs[idx].linear) {
09339 p->subs[idx].linear = 1;
09340 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09341 if (res)
09342 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09343 }
09344 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09345 } else {
09346
09347 if (p->subs[idx].linear) {
09348 p->subs[idx].linear = 0;
09349 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09350 if (res)
09351 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09352 }
09353 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09354 }
09355 if (res < 0) {
09356 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09357 return -1;
09358 }
09359 return 0;
09360 }
09361
09362 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09363 {
09364 struct dahdi_pvt *p = chan->tech_pvt;
09365 int res=-1;
09366 int idx;
09367 int func = DAHDI_FLASH;
09368
09369 ast_mutex_lock(&p->lock);
09370 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09371 switch (p->sig) {
09372 #if defined(HAVE_PRI)
09373 case SIG_PRI_LIB_HANDLE_CASES:
09374 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09375 ast_mutex_unlock(&p->lock);
09376 return res;
09377 #endif
09378 #if defined(HAVE_SS7)
09379 case SIG_SS7:
09380 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09381 ast_mutex_unlock(&p->lock);
09382 return res;
09383 #endif
09384 default:
09385 break;
09386 }
09387 #ifdef HAVE_OPENR2
09388 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09389 ast_mutex_unlock(&p->lock);
09390
09391
09392 return 0;
09393 }
09394 #endif
09395 idx = dahdi_get_index(chan, p, 0);
09396 if (idx == SUB_REAL) {
09397 switch (condition) {
09398 case AST_CONTROL_BUSY:
09399 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09400 break;
09401 case AST_CONTROL_RINGING:
09402 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09403
09404 if (chan->_state != AST_STATE_UP) {
09405 if ((chan->_state != AST_STATE_RING) ||
09406 ((p->sig != SIG_FXSKS) &&
09407 (p->sig != SIG_FXSLS) &&
09408 (p->sig != SIG_FXSGS)))
09409 ast_setstate(chan, AST_STATE_RINGING);
09410 }
09411 break;
09412 case AST_CONTROL_INCOMPLETE:
09413 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09414
09415 res = 0;
09416 break;
09417 case AST_CONTROL_PROCEEDING:
09418 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09419
09420 res = 0;
09421 break;
09422 case AST_CONTROL_PROGRESS:
09423 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09424
09425 res = 0;
09426 break;
09427 case AST_CONTROL_CONGESTION:
09428
09429 switch (chan->hangupcause) {
09430 case AST_CAUSE_USER_BUSY:
09431 case AST_CAUSE_NORMAL_CLEARING:
09432 case 0:
09433
09434 chan->hangupcause = AST_CAUSE_CONGESTION;
09435 break;
09436 default:
09437 break;
09438 }
09439 break;
09440 case AST_CONTROL_HOLD:
09441 ast_moh_start(chan, data, p->mohinterpret);
09442 break;
09443 case AST_CONTROL_UNHOLD:
09444 ast_moh_stop(chan);
09445 break;
09446 case AST_CONTROL_RADIO_KEY:
09447 if (p->radio)
09448 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09449 res = 0;
09450 break;
09451 case AST_CONTROL_RADIO_UNKEY:
09452 if (p->radio)
09453 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09454 res = 0;
09455 break;
09456 case AST_CONTROL_FLASH:
09457
09458 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09459
09460 p->dop.dialstr[0] = '\0';
09461 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09462 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09463 chan->name, strerror(errno));
09464 } else
09465 res = 0;
09466 } else
09467 res = 0;
09468 break;
09469 case AST_CONTROL_SRCUPDATE:
09470 res = 0;
09471 break;
09472 case -1:
09473 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09474 break;
09475 }
09476 } else {
09477 res = 0;
09478 }
09479 ast_mutex_unlock(&p->lock);
09480 return res;
09481 }
09482
09483 #if defined(HAVE_PRI)
09484 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09485 #else
09486 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09487 #endif
09488 {
09489 struct ast_str *chan_name;
09490 int x, y;
09491
09492
09493 if (!(chan_name = ast_str_create(32))) {
09494 return NULL;
09495 }
09496 if (i->channel == CHAN_PSEUDO) {
09497 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09498 #if defined(HAVE_PRI)
09499 } else if (i->pri) {
09500 ast_mutex_lock(&i->pri->lock);
09501 y = ++i->pri->new_chan_seq;
09502 if (is_outgoing) {
09503 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09504 address[0] = '\0';
09505 } else if (ast_strlen_zero(i->cid_subaddr)) {
09506
09507 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09508 } else {
09509
09510 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09511 i->cid_subaddr, y);
09512 }
09513 ast_mutex_unlock(&i->pri->lock);
09514 #endif
09515 } else {
09516 y = 1;
09517 do {
09518 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09519 for (x = 0; x < 3; ++x) {
09520 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09521 i->subs[x].owner->name + 6)) {
09522 break;
09523 }
09524 }
09525 ++y;
09526 } while (x < 3);
09527 }
09528 return chan_name;
09529 }
09530
09531 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09532 {
09533 struct ast_channel *tmp;
09534 format_t deflaw;
09535 int x;
09536 int features;
09537 struct ast_str *chan_name;
09538 struct ast_variable *v;
09539 char *dashptr;
09540 char device_name[AST_CHANNEL_NAME];
09541
09542 if (i->subs[idx].owner) {
09543 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09544 return NULL;
09545 }
09546
09547 #if defined(HAVE_PRI)
09548
09549
09550
09551
09552 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09553 #else
09554 chan_name = create_channel_name(i);
09555 #endif
09556 if (!chan_name) {
09557 return NULL;
09558 }
09559
09560 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));
09561 ast_free(chan_name);
09562 if (!tmp)
09563 return NULL;
09564 tmp->tech = &dahdi_tech;
09565 #if defined(HAVE_PRI)
09566 if (i->pri) {
09567 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09568 }
09569 #endif
09570 ast_channel_cc_params_init(tmp, i->cc_params);
09571 if (law) {
09572 i->law = law;
09573 if (law == DAHDI_LAW_ALAW) {
09574 deflaw = AST_FORMAT_ALAW;
09575 } else {
09576 deflaw = AST_FORMAT_ULAW;
09577 }
09578 } else {
09579 switch (i->sig) {
09580 case SIG_PRI_LIB_HANDLE_CASES:
09581
09582 i->law = (i->law_default == DAHDI_LAW_ALAW)
09583 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09584 break;
09585 default:
09586 i->law = i->law_default;
09587 break;
09588 }
09589 if (i->law_default == DAHDI_LAW_ALAW) {
09590 deflaw = AST_FORMAT_ALAW;
09591 } else {
09592 deflaw = AST_FORMAT_ULAW;
09593 }
09594 }
09595 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09596 tmp->nativeformats = deflaw;
09597
09598 tmp->rawreadformat = deflaw;
09599 tmp->readformat = deflaw;
09600 tmp->rawwriteformat = deflaw;
09601 tmp->writeformat = deflaw;
09602 i->subs[idx].linear = 0;
09603 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09604 features = 0;
09605 if (idx == SUB_REAL) {
09606 if (i->busydetect && CANBUSYDETECT(i))
09607 features |= DSP_FEATURE_BUSY_DETECT;
09608 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09609 features |= DSP_FEATURE_CALL_PROGRESS;
09610 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09611 features |= DSP_FEATURE_WAITDIALTONE;
09612 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09613 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09614 features |= DSP_FEATURE_FAX_DETECT;
09615 }
09616 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09617 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09618 i->hardwaredtmf = 0;
09619 features |= DSP_FEATURE_DIGIT_DETECT;
09620 } else if (NEED_MFDETECT(i)) {
09621 i->hardwaredtmf = 1;
09622 features |= DSP_FEATURE_DIGIT_DETECT;
09623 }
09624 }
09625 if (features) {
09626 if (i->dsp) {
09627 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09628 } else {
09629 if (i->channel != CHAN_PSEUDO)
09630 i->dsp = ast_dsp_new();
09631 else
09632 i->dsp = NULL;
09633 if (i->dsp) {
09634 i->dsp_features = features;
09635 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09636
09637 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09638
09639
09640 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09641 features = 0;
09642 }
09643 #endif
09644 ast_dsp_set_features(i->dsp, features);
09645 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09646 if (!ast_strlen_zero(progzone))
09647 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09648 if (i->busydetect && CANBUSYDETECT(i)) {
09649 ast_dsp_set_busy_count(i->dsp, i->busycount);
09650 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09651 }
09652 }
09653 }
09654 }
09655
09656 if (state == AST_STATE_RING)
09657 tmp->rings = 1;
09658 tmp->tech_pvt = i;
09659 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09660
09661 tmp->callgroup = i->callgroup;
09662 tmp->pickupgroup = i->pickupgroup;
09663 }
09664 if (!ast_strlen_zero(i->parkinglot))
09665 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09666 if (!ast_strlen_zero(i->language))
09667 ast_string_field_set(tmp, language, i->language);
09668 if (!i->owner)
09669 i->owner = tmp;
09670 if (!ast_strlen_zero(i->accountcode))
09671 ast_string_field_set(tmp, accountcode, i->accountcode);
09672 if (i->amaflags)
09673 tmp->amaflags = i->amaflags;
09674 i->subs[idx].owner = tmp;
09675 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09676 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09677 ast_string_field_set(tmp, call_forward, i->call_forward);
09678 }
09679
09680 if (!i->adsi)
09681 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09682 if (!ast_strlen_zero(i->exten))
09683 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09684 if (!ast_strlen_zero(i->rdnis)) {
09685 tmp->redirecting.from.number.valid = 1;
09686 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09687 }
09688 if (!ast_strlen_zero(i->dnid)) {
09689 tmp->dialed.number.str = ast_strdup(i->dnid);
09690 }
09691
09692
09693
09694 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09695 if (!ast_strlen_zero(i->cid_ani)) {
09696 tmp->caller.ani.number.valid = 1;
09697 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09698 } else if (!ast_strlen_zero(i->cid_num)) {
09699 tmp->caller.ani.number.valid = 1;
09700 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09701 }
09702 #else
09703 if (!ast_strlen_zero(i->cid_num)) {
09704 tmp->caller.ani.number.valid = 1;
09705 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09706 }
09707 #endif
09708 tmp->caller.id.name.presentation = i->callingpres;
09709 tmp->caller.id.number.presentation = i->callingpres;
09710 tmp->caller.id.number.plan = i->cid_ton;
09711 tmp->caller.ani2 = i->cid_ani2;
09712 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09713
09714 i->fake_event = 0;
09715
09716 dahdi_confmute(i, 0);
09717 i->muting = 0;
09718
09719 ast_jb_configure(tmp, &global_jbconf);
09720
09721
09722 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09723 dashptr = strrchr(device_name, '-');
09724 if (dashptr) {
09725 *dashptr = '\0';
09726 }
09727 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09728
09729 for (v = i->vars ; v ; v = v->next)
09730 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09731
09732 ast_module_ref(ast_module_info->self);
09733
09734 dahdi_ami_channel_event(i, tmp);
09735 if (startpbx) {
09736 #ifdef HAVE_OPENR2
09737 if (i->mfcr2call) {
09738 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09739 }
09740 #endif
09741 if (ast_pbx_start(tmp)) {
09742 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09743 ast_hangup(tmp);
09744 return NULL;
09745 }
09746 }
09747 return tmp;
09748 }
09749
09750
09751 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09752 {
09753 char c;
09754
09755 *str = 0;
09756 for (;;)
09757 {
09758
09759 c = ast_waitfordigit(chan, ms);
09760
09761 if (c < 1)
09762 return c;
09763 *str++ = c;
09764 *str = 0;
09765 if (strchr(term, c))
09766 return 1;
09767 }
09768 }
09769
09770 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09771 {
09772 int j;
09773 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09774 for (;;)
09775 {
09776
09777 j = DAHDI_IOMUX_SIGEVENT;
09778
09779 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09780
09781 if (j & DAHDI_IOMUX_SIGEVENT) break;
09782 }
09783
09784 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09785 return 0;
09786 }
09787
09788
09789
09790
09791
09792
09793
09794
09795
09796
09797 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09798 {
09799 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09800 return analog_dnd(dahdichan->sig_pvt, flag);
09801 }
09802
09803 if (flag == -1) {
09804 return dahdichan->dnd;
09805 }
09806
09807
09808 dahdichan->dnd = flag;
09809 ast_verb(3, "%s DND on channel %d\n",
09810 flag? "Enabled" : "Disabled",
09811 dahdichan->channel);
09812 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09813 "Channel: DAHDI/%d\r\n"
09814 "Status: %s\r\n", dahdichan->channel,
09815 flag? "enabled" : "disabled");
09816
09817 return 0;
09818 }
09819
09820 static int canmatch_featurecode(const char *exten)
09821 {
09822 int extlen = strlen(exten);
09823 const char *pickup_ext;
09824 if (!extlen) {
09825 return 1;
09826 }
09827 pickup_ext = ast_pickup_ext();
09828 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09829 return 1;
09830 }
09831
09832 if (exten[0] == '*' && extlen < 3) {
09833 if (extlen == 1) {
09834 return 1;
09835 }
09836
09837 switch (exten[1]) {
09838 case '6':
09839 case '7':
09840 case '8':
09841 return 1;
09842 }
09843 }
09844 return 0;
09845 }
09846
09847 static void *analog_ss_thread(void *data)
09848 {
09849 struct ast_channel *chan = data;
09850 struct dahdi_pvt *p = chan->tech_pvt;
09851 char exten[AST_MAX_EXTENSION] = "";
09852 char exten2[AST_MAX_EXTENSION] = "";
09853 unsigned char buf[256];
09854 char dtmfcid[300];
09855 char dtmfbuf[300];
09856 struct callerid_state *cs = NULL;
09857 char *name = NULL, *number = NULL;
09858 int distMatches;
09859 int curRingData[3];
09860 int receivedRingT;
09861 int counter1;
09862 int counter;
09863 int samples = 0;
09864 struct ast_smdi_md_message *smdi_msg = NULL;
09865 int flags = 0;
09866 int i;
09867 int timeout;
09868 int getforward = 0;
09869 char *s1, *s2;
09870 int len = 0;
09871 int res;
09872 int idx;
09873
09874 ast_mutex_lock(&ss_thread_lock);
09875 ss_thread_count++;
09876 ast_mutex_unlock(&ss_thread_lock);
09877
09878
09879
09880 if (!p) {
09881 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09882 ast_hangup(chan);
09883 goto quit;
09884 }
09885 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09886 idx = dahdi_get_index(chan, p, 1);
09887 if (idx < 0) {
09888 ast_log(LOG_WARNING, "Huh?\n");
09889 ast_hangup(chan);
09890 goto quit;
09891 }
09892 if (p->dsp)
09893 ast_dsp_digitreset(p->dsp);
09894 switch (p->sig) {
09895 case SIG_FEATD:
09896 case SIG_FEATDMF:
09897 case SIG_FEATDMF_TA:
09898 case SIG_E911:
09899 case SIG_FGC_CAMAMF:
09900 case SIG_FEATB:
09901 case SIG_EMWINK:
09902 case SIG_SF_FEATD:
09903 case SIG_SF_FEATDMF:
09904 case SIG_SF_FEATB:
09905 case SIG_SFWINK:
09906 if (dahdi_wink(p, idx))
09907 goto quit;
09908
09909 case SIG_EM:
09910 case SIG_EM_E1:
09911 case SIG_SF:
09912 case SIG_FGC_CAMA:
09913 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09914 if (p->dsp)
09915 ast_dsp_digitreset(p->dsp);
09916
09917 if (p->dsp) {
09918 if (NEED_MFDETECT(p))
09919 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09920 else
09921 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09922 }
09923 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09924
09925 if (!p->immediate)
09926
09927 res = ast_waitfordigit(chan, 5000);
09928 else
09929 res = 0;
09930 if (res > 0) {
09931
09932 dtmfbuf[0] = res;
09933 switch (p->sig) {
09934 case SIG_FEATD:
09935 case SIG_SF_FEATD:
09936 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09937 if (res > 0)
09938 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09939 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09940 break;
09941 case SIG_FEATDMF_TA:
09942 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09943 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09944 if (dahdi_wink(p, idx)) goto quit;
09945 dtmfbuf[0] = 0;
09946
09947 res = ast_waitfordigit(chan, 5000);
09948 if (res <= 0) break;
09949 dtmfbuf[0] = res;
09950
09951 case SIG_FEATDMF:
09952 case SIG_E911:
09953 case SIG_FGC_CAMAMF:
09954 case SIG_SF_FEATDMF:
09955 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09956
09957 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09958 {
09959 if (dahdi_wink(p, idx)) goto quit;
09960 dtmfbuf[0] = 0;
09961
09962 res = ast_waitfordigit(chan, 5000);
09963 if (res <= 0) break;
09964 dtmfbuf[0] = res;
09965 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09966 }
09967 if (res > 0) {
09968
09969 if (p->sig == SIG_E911)
09970 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09971 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09972 }
09973 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09974 break;
09975 case SIG_FEATB:
09976 case SIG_SF_FEATB:
09977 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09978 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09979 break;
09980 case SIG_EMWINK:
09981
09982
09983
09984
09985 if (res == '*') {
09986 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09987 if (res > 0)
09988 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09989 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09990 break;
09991 }
09992 default:
09993
09994 len = 1;
09995 dtmfbuf[len] = '\0';
09996 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09997 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09998 timeout = matchdigittimeout;
09999 } else {
10000 timeout = gendigittimeout;
10001 }
10002 res = ast_waitfordigit(chan, timeout);
10003 if (res < 0) {
10004 ast_debug(1, "waitfordigit returned < 0...\n");
10005 ast_hangup(chan);
10006 goto quit;
10007 } else if (res) {
10008 dtmfbuf[len++] = res;
10009 dtmfbuf[len] = '\0';
10010 } else {
10011 break;
10012 }
10013 }
10014 break;
10015 }
10016 }
10017 if (res == -1) {
10018 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10019 ast_hangup(chan);
10020 goto quit;
10021 } else if (res < 0) {
10022 ast_debug(1, "Got hung up before digits finished\n");
10023 ast_hangup(chan);
10024 goto quit;
10025 }
10026
10027 if (p->sig == SIG_FGC_CAMA) {
10028 char anibuf[100];
10029
10030 if (ast_safe_sleep(chan,1000) == -1) {
10031 ast_hangup(chan);
10032 goto quit;
10033 }
10034 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10035 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10036 res = my_getsigstr(chan, anibuf, "#", 10000);
10037 if ((res > 0) && (strlen(anibuf) > 2)) {
10038 if (anibuf[strlen(anibuf) - 1] == '#')
10039 anibuf[strlen(anibuf) - 1] = 0;
10040 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10041 }
10042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10043 }
10044
10045 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10046 if (ast_strlen_zero(exten))
10047 ast_copy_string(exten, "s", sizeof(exten));
10048 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10049
10050 if (exten[0] == '*') {
10051 char *stringp=NULL;
10052 ast_copy_string(exten2, exten, sizeof(exten2));
10053
10054 stringp=exten2 +1;
10055 s1 = strsep(&stringp, "*");
10056 s2 = strsep(&stringp, "*");
10057 if (s2) {
10058 if (!ast_strlen_zero(p->cid_num))
10059 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10060 else
10061 ast_set_callerid(chan, s1, NULL, s1);
10062 ast_copy_string(exten, s2, sizeof(exten));
10063 } else
10064 ast_copy_string(exten, s1, sizeof(exten));
10065 } else if (p->sig == SIG_FEATD)
10066 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10067 }
10068 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10069 if (exten[0] == '*') {
10070 char *stringp=NULL;
10071 ast_copy_string(exten2, exten, sizeof(exten2));
10072
10073 stringp=exten2 +1;
10074 s1 = strsep(&stringp, "#");
10075 s2 = strsep(&stringp, "#");
10076 if (s2) {
10077 if (!ast_strlen_zero(p->cid_num))
10078 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10079 else
10080 if (*(s1 + 2))
10081 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10082 ast_copy_string(exten, s2 + 1, sizeof(exten));
10083 } else
10084 ast_copy_string(exten, s1 + 2, sizeof(exten));
10085 } else
10086 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10087 }
10088 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10089 if (exten[0] == '*') {
10090 char *stringp=NULL;
10091 ast_copy_string(exten2, exten, sizeof(exten2));
10092
10093 stringp=exten2 +1;
10094 s1 = strsep(&stringp, "#");
10095 s2 = strsep(&stringp, "#");
10096 if (s2 && (*(s2 + 1) == '0')) {
10097 if (*(s2 + 2))
10098 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10099 }
10100 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10101 else ast_copy_string(exten, "911", sizeof(exten));
10102 } else
10103 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10104 }
10105 if (p->sig == SIG_FEATB) {
10106 if (exten[0] == '*') {
10107 char *stringp=NULL;
10108 ast_copy_string(exten2, exten, sizeof(exten2));
10109
10110 stringp=exten2 +1;
10111 s1 = strsep(&stringp, "#");
10112 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10113 } else
10114 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10115 }
10116 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10117 dahdi_wink(p, idx);
10118
10119
10120
10121 if (ast_safe_sleep(chan, 100)) {
10122 ast_hangup(chan);
10123 goto quit;
10124 }
10125 }
10126 dahdi_enable_ec(p);
10127 if (NEED_MFDETECT(p)) {
10128 if (p->dsp) {
10129 if (!p->hardwaredtmf)
10130 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10131 else {
10132 ast_dsp_free(p->dsp);
10133 p->dsp = NULL;
10134 }
10135 }
10136 }
10137
10138 if (ast_exists_extension(chan, chan->context, exten, 1,
10139 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10140 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10141 if (p->dsp) ast_dsp_digitreset(p->dsp);
10142 res = ast_pbx_run(chan);
10143 if (res) {
10144 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10145 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10146 }
10147 goto quit;
10148 } else {
10149 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10150 sleep(2);
10151 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10152 if (res < 0)
10153 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10154 else
10155 sleep(1);
10156 res = ast_streamfile(chan, "ss-noservice", chan->language);
10157 if (res >= 0)
10158 ast_waitstream(chan, "");
10159 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10160 ast_hangup(chan);
10161 goto quit;
10162 }
10163 break;
10164 case SIG_FXOLS:
10165 case SIG_FXOGS:
10166 case SIG_FXOKS:
10167
10168 timeout = firstdigittimeout;
10169
10170
10171 if (p->subs[SUB_THREEWAY].owner)
10172 timeout = 999999;
10173 while (len < AST_MAX_EXTENSION-1) {
10174
10175
10176 if (p->immediate)
10177 res = 's';
10178 else
10179 res = ast_waitfordigit(chan, timeout);
10180 timeout = 0;
10181 if (res < 0) {
10182 ast_debug(1, "waitfordigit returned < 0...\n");
10183 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10184 ast_hangup(chan);
10185 goto quit;
10186 } else if (res) {
10187 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10188 exten[len++]=res;
10189 exten[len] = '\0';
10190 }
10191 if (!ast_ignore_pattern(chan->context, exten))
10192 tone_zone_play_tone(p->subs[idx].dfd, -1);
10193 else
10194 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10195 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10196 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10197 if (getforward) {
10198
10199 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10200 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10201 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10202 if (res)
10203 break;
10204 usleep(500000);
10205 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10206 sleep(1);
10207 memset(exten, 0, sizeof(exten));
10208 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10209 len = 0;
10210 getforward = 0;
10211 } else {
10212 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10213 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10214 if (!ast_strlen_zero(p->cid_num)) {
10215 if (!p->hidecallerid)
10216 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10217 else
10218 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10219 }
10220 if (!ast_strlen_zero(p->cid_name)) {
10221 if (!p->hidecallerid)
10222 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10223 }
10224 ast_setstate(chan, AST_STATE_RING);
10225 dahdi_enable_ec(p);
10226 res = ast_pbx_run(chan);
10227 if (res) {
10228 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10229 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10230 }
10231 goto quit;
10232 }
10233 } else {
10234
10235
10236 timeout = matchdigittimeout;
10237 }
10238 } else if (res == 0) {
10239 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10240 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10241 dahdi_wait_event(p->subs[idx].dfd);
10242 ast_hangup(chan);
10243 goto quit;
10244 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10245 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10246
10247 p->callwaiting = 0;
10248 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10249 if (res) {
10250 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10251 chan->name, strerror(errno));
10252 }
10253 len = 0;
10254 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10255 memset(exten, 0, sizeof(exten));
10256 timeout = firstdigittimeout;
10257
10258 } else if (!strcmp(exten,ast_pickup_ext())) {
10259
10260
10261
10262
10263 if (idx == SUB_REAL) {
10264
10265 if (p->subs[SUB_THREEWAY].owner) {
10266
10267
10268 alloc_sub(p, SUB_CALLWAIT);
10269 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10270 unalloc_sub(p, SUB_THREEWAY);
10271 }
10272 dahdi_enable_ec(p);
10273 if (ast_pickup_call(chan)) {
10274 ast_debug(1, "No call pickup possible...\n");
10275 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10276 dahdi_wait_event(p->subs[idx].dfd);
10277 }
10278 ast_hangup(chan);
10279 goto quit;
10280 } else {
10281 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10282 ast_hangup(chan);
10283 goto quit;
10284 }
10285
10286 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10287 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10288
10289 p->hidecallerid = 1;
10290 ast_party_number_free(&chan->caller.id.number);
10291 ast_party_number_init(&chan->caller.id.number);
10292 ast_party_name_free(&chan->caller.id.name);
10293 ast_party_name_init(&chan->caller.id.name);
10294 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10295 if (res) {
10296 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10297 chan->name, strerror(errno));
10298 }
10299 len = 0;
10300 memset(exten, 0, sizeof(exten));
10301 timeout = firstdigittimeout;
10302 } else if (p->callreturn && !strcmp(exten, "*69")) {
10303 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10304 break;
10305 } else if (!strcmp(exten, "*78")) {
10306 dahdi_dnd(p, 1);
10307
10308 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10309 getforward = 0;
10310 memset(exten, 0, sizeof(exten));
10311 len = 0;
10312 } else if (!strcmp(exten, "*79")) {
10313 dahdi_dnd(p, 0);
10314
10315 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10316 getforward = 0;
10317 memset(exten, 0, sizeof(exten));
10318 len = 0;
10319 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10320 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10321 getforward = 1;
10322 memset(exten, 0, sizeof(exten));
10323 len = 0;
10324 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10325 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10326 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10327 memset(p->call_forward, 0, sizeof(p->call_forward));
10328 getforward = 0;
10329 memset(exten, 0, sizeof(exten));
10330 len = 0;
10331 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10332 p->subs[SUB_THREEWAY].owner &&
10333 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10334
10335
10336 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10337 chan, exten, chan->context, 0, NULL);
10338 ast_verb(3, "Parking call to '%s'\n", chan->name);
10339 break;
10340 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10341 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10342
10343 p->hidecallerid = 0;
10344 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10345 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10346 if (res) {
10347 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10348 chan->name, strerror(errno));
10349 }
10350 len = 0;
10351 memset(exten, 0, sizeof(exten));
10352 timeout = firstdigittimeout;
10353 } else if (!strcmp(exten, "*0")) {
10354 struct ast_channel *nbridge =
10355 p->subs[SUB_THREEWAY].owner;
10356 struct dahdi_pvt *pbridge = NULL;
10357
10358 if (nbridge && ast_bridged_channel(nbridge))
10359 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10360 if (nbridge && pbridge &&
10361 (nbridge->tech == &dahdi_tech) &&
10362 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10363 ISTRUNK(pbridge)) {
10364 int func = DAHDI_FLASH;
10365
10366 p->dop.dialstr[0] = '\0';
10367
10368 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10369 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10370 nbridge->name, strerror(errno));
10371 }
10372 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10373 unalloc_sub(p, SUB_THREEWAY);
10374 p->owner = p->subs[SUB_REAL].owner;
10375 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10376 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10377 ast_hangup(chan);
10378 goto quit;
10379 } else {
10380 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10381 dahdi_wait_event(p->subs[idx].dfd);
10382 tone_zone_play_tone(p->subs[idx].dfd, -1);
10383 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10384 unalloc_sub(p, SUB_THREEWAY);
10385 p->owner = p->subs[SUB_REAL].owner;
10386 ast_hangup(chan);
10387 goto quit;
10388 }
10389 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10390 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10391 && !canmatch_featurecode(exten)) {
10392 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10393 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10394 chan->context);
10395 break;
10396 }
10397 if (!timeout)
10398 timeout = gendigittimeout;
10399 if (len && !ast_ignore_pattern(chan->context, exten))
10400 tone_zone_play_tone(p->subs[idx].dfd, -1);
10401 }
10402 break;
10403 case SIG_FXSLS:
10404 case SIG_FXSGS:
10405 case SIG_FXSKS:
10406
10407 if (p->use_smdi && p->smdi_iface) {
10408 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10409
10410 if (smdi_msg != NULL) {
10411 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10412
10413 if (smdi_msg->type == 'B')
10414 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10415 else if (smdi_msg->type == 'N')
10416 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10417
10418 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10419 } else {
10420 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10421 }
10422 }
10423
10424 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10425 number = smdi_msg->calling_st;
10426
10427
10428
10429
10430 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10431 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10432
10433 if (p->cid_signalling == CID_SIG_DTMF) {
10434 int k = 0;
10435 cs = NULL;
10436 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10437 dahdi_setlinear(p->subs[idx].dfd, 0);
10438
10439
10440
10441
10442
10443
10444 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10445 res = 4000;
10446 for (;;) {
10447 struct ast_frame *f;
10448 res = ast_waitfor(chan, res);
10449 if (res <= 0) {
10450
10451
10452
10453
10454
10455 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10456 "Exiting simple switch\n");
10457 ast_hangup(chan);
10458 goto quit;
10459 }
10460 f = ast_read(chan);
10461 if (!f)
10462 break;
10463 if (f->frametype == AST_FRAME_DTMF) {
10464 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10465 dtmfbuf[k++] = f->subclass.integer;
10466 }
10467 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10468 res = 4000;
10469 }
10470 ast_frfree(f);
10471 if (chan->_state == AST_STATE_RING ||
10472 chan->_state == AST_STATE_RINGING)
10473 break;
10474 }
10475 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10476 dtmfbuf[k] = '\0';
10477 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10478
10479 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10480 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10481 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10482
10483 if (!ast_strlen_zero(dtmfcid))
10484 number = dtmfcid;
10485 else
10486 number = NULL;
10487
10488 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10489 cs = callerid_new(p->cid_signalling);
10490 if (cs) {
10491 samples = 0;
10492 #if 1
10493 bump_gains(p);
10494 #endif
10495
10496 dahdi_setlinear(p->subs[idx].dfd, 0);
10497
10498
10499 for (;;) {
10500 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10501 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10502 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10503 callerid_free(cs);
10504 ast_hangup(chan);
10505 goto quit;
10506 }
10507 if (i & DAHDI_IOMUX_SIGEVENT) {
10508 res = dahdi_get_event(p->subs[idx].dfd);
10509 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10510 if (res == DAHDI_EVENT_NOALARM) {
10511 p->inalarm = 0;
10512 }
10513
10514 if (p->cid_signalling == CID_SIG_V23_JP) {
10515 if (res == DAHDI_EVENT_RINGBEGIN) {
10516 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10517 usleep(1);
10518 }
10519 } else {
10520 res = 0;
10521 break;
10522 }
10523 } else if (i & DAHDI_IOMUX_READ) {
10524 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10525 if (res < 0) {
10526 if (errno != ELAST) {
10527 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10528 callerid_free(cs);
10529 ast_hangup(chan);
10530 goto quit;
10531 }
10532 break;
10533 }
10534 samples += res;
10535
10536 if (p->cid_signalling == CID_SIG_V23_JP) {
10537 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10538 } else {
10539 res = callerid_feed(cs, buf, res, AST_LAW(p));
10540 }
10541 if (res < 0) {
10542
10543
10544
10545
10546 ast_log(LOG_WARNING,
10547 "Failed to decode CallerID on channel '%s'\n",
10548 chan->name);
10549 break;
10550 } else if (res)
10551 break;
10552 else if (samples > (8000 * 10))
10553 break;
10554 }
10555 }
10556 if (res == 1) {
10557 callerid_get(cs, &name, &number, &flags);
10558 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10559 }
10560
10561 if (p->cid_signalling == CID_SIG_V23_JP) {
10562 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10563 usleep(1);
10564 }
10565
10566
10567 res = 4000;
10568 for (;;) {
10569 struct ast_frame *f;
10570 res = ast_waitfor(chan, res);
10571 if (res <= 0) {
10572 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10573 "Exiting simple switch\n");
10574 ast_hangup(chan);
10575 goto quit;
10576 }
10577 if (!(f = ast_read(chan))) {
10578 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10579 ast_hangup(chan);
10580 goto quit;
10581 }
10582 ast_frfree(f);
10583 if (chan->_state == AST_STATE_RING ||
10584 chan->_state == AST_STATE_RINGING)
10585 break;
10586 }
10587
10588
10589
10590 if (p->usedistinctiveringdetection) {
10591 len = 0;
10592 distMatches = 0;
10593
10594 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10595 curRingData[receivedRingT] = 0;
10596 receivedRingT = 0;
10597 counter = 0;
10598 counter1 = 0;
10599
10600 if (strcmp(p->context,p->defcontext) != 0) {
10601 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10602 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10603 }
10604
10605 for (;;) {
10606 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10607 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10608 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10609 callerid_free(cs);
10610 ast_hangup(chan);
10611 goto quit;
10612 }
10613 if (i & DAHDI_IOMUX_SIGEVENT) {
10614 res = dahdi_get_event(p->subs[idx].dfd);
10615 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10616 if (res == DAHDI_EVENT_NOALARM) {
10617 p->inalarm = 0;
10618 }
10619 res = 0;
10620
10621
10622 curRingData[receivedRingT] = p->ringt;
10623
10624 if (p->ringt < p->ringt_base/2)
10625 break;
10626
10627
10628 if (++receivedRingT == ARRAY_LEN(curRingData))
10629 break;
10630 } else if (i & DAHDI_IOMUX_READ) {
10631 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10632 if (res < 0) {
10633 if (errno != ELAST) {
10634 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10635 callerid_free(cs);
10636 ast_hangup(chan);
10637 goto quit;
10638 }
10639 break;
10640 }
10641 if (p->ringt > 0) {
10642 if (!(--p->ringt)) {
10643 res = -1;
10644 break;
10645 }
10646 }
10647 }
10648 }
10649
10650 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10651 for (counter = 0; counter < 3; counter++) {
10652
10653
10654 distMatches = 0;
10655 for (counter1 = 0; counter1 < 3; counter1++) {
10656 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10657 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10658 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10659 curRingData[counter1]);
10660 distMatches++;
10661 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10662 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10663 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10664 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10665 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10666 distMatches++;
10667 }
10668 }
10669
10670 if (distMatches == 3) {
10671
10672 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10673 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10674 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10675 break;
10676 }
10677 }
10678 }
10679
10680 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10681 #if 1
10682 restore_gains(p);
10683 #endif
10684 } else
10685 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10686 } else {
10687 ast_log(LOG_WARNING, "Channel %s in prering "
10688 "state, but I have nothing to do. "
10689 "Terminating simple switch, should be "
10690 "restarted by the actual ring.\n",
10691 chan->name);
10692 ast_hangup(chan);
10693 goto quit;
10694 }
10695 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10696 if (p->cid_signalling == CID_SIG_DTMF) {
10697 int k = 0;
10698 cs = NULL;
10699 dahdi_setlinear(p->subs[idx].dfd, 0);
10700 res = 2000;
10701 for (;;) {
10702 struct ast_frame *f;
10703 res = ast_waitfor(chan, res);
10704 if (res <= 0) {
10705 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10706 "Exiting simple switch\n");
10707 ast_hangup(chan);
10708 goto quit;
10709 }
10710 f = ast_read(chan);
10711 if (!f) {
10712
10713 ast_hangup(chan);
10714 goto quit;
10715 }
10716 if (f->frametype == AST_FRAME_DTMF) {
10717 dtmfbuf[k++] = f->subclass.integer;
10718 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10719 res = 2000;
10720 }
10721 ast_frfree(f);
10722
10723 if (p->ringt_base == p->ringt)
10724 break;
10725 }
10726 dtmfbuf[k] = '\0';
10727 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10728
10729 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10730 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10731 dtmfcid, flags);
10732
10733 if (!ast_strlen_zero(dtmfcid))
10734 number = dtmfcid;
10735 else
10736 number = NULL;
10737
10738 } else {
10739
10740 cs = callerid_new(p->cid_signalling);
10741 if (cs) {
10742 #if 1
10743 bump_gains(p);
10744 #endif
10745 samples = 0;
10746 len = 0;
10747 distMatches = 0;
10748
10749 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10750 curRingData[receivedRingT] = 0;
10751 receivedRingT = 0;
10752 counter = 0;
10753 counter1 = 0;
10754
10755 if (strcmp(p->context,p->defcontext) != 0) {
10756 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10757 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10758 }
10759
10760
10761 dahdi_setlinear(p->subs[idx].dfd, 0);
10762 for (;;) {
10763 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10764 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10765 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10766 callerid_free(cs);
10767 ast_hangup(chan);
10768 goto quit;
10769 }
10770 if (i & DAHDI_IOMUX_SIGEVENT) {
10771 res = dahdi_get_event(p->subs[idx].dfd);
10772 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10773 if (res == DAHDI_EVENT_NOALARM) {
10774 p->inalarm = 0;
10775 }
10776
10777 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10778 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10779 p->polarity = POLARITY_IDLE;
10780 callerid_free(cs);
10781 ast_hangup(chan);
10782 goto quit;
10783 }
10784 res = 0;
10785
10786
10787 curRingData[receivedRingT] = p->ringt;
10788
10789 if (p->ringt < p->ringt_base/2)
10790 break;
10791
10792
10793 if (++receivedRingT == ARRAY_LEN(curRingData))
10794 break;
10795 } else if (i & DAHDI_IOMUX_READ) {
10796 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10797 if (res < 0) {
10798 if (errno != ELAST) {
10799 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10800 callerid_free(cs);
10801 ast_hangup(chan);
10802 goto quit;
10803 }
10804 break;
10805 }
10806 if (p->ringt > 0) {
10807 if (!(--p->ringt)) {
10808 res = -1;
10809 break;
10810 }
10811 }
10812 samples += res;
10813 res = callerid_feed(cs, buf, res, AST_LAW(p));
10814 if (res < 0) {
10815
10816
10817
10818
10819 ast_log(LOG_WARNING,
10820 "Failed to decode CallerID on channel '%s'\n",
10821 chan->name);
10822 break;
10823 } else if (res)
10824 break;
10825 else if (samples > (8000 * 10))
10826 break;
10827 }
10828 }
10829 if (res == 1) {
10830 callerid_get(cs, &name, &number, &flags);
10831 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10832 }
10833 if (distinctiveringaftercid == 1) {
10834
10835 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10836 curRingData[receivedRingT] = 0;
10837 }
10838 receivedRingT = 0;
10839 ast_verb(3, "Detecting post-CID distinctive ring\n");
10840 for (;;) {
10841 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10842 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10843 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10844 callerid_free(cs);
10845 ast_hangup(chan);
10846 goto quit;
10847 }
10848 if (i & DAHDI_IOMUX_SIGEVENT) {
10849 res = dahdi_get_event(p->subs[idx].dfd);
10850 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10851 if (res == DAHDI_EVENT_NOALARM) {
10852 p->inalarm = 0;
10853 }
10854 res = 0;
10855
10856
10857 curRingData[receivedRingT] = p->ringt;
10858
10859 if (p->ringt < p->ringt_base/2)
10860 break;
10861
10862
10863 if (++receivedRingT == ARRAY_LEN(curRingData))
10864 break;
10865 } else if (i & DAHDI_IOMUX_READ) {
10866 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10867 if (res < 0) {
10868 if (errno != ELAST) {
10869 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10870 callerid_free(cs);
10871 ast_hangup(chan);
10872 goto quit;
10873 }
10874 break;
10875 }
10876 if (p->ringt > 0) {
10877 if (!(--p->ringt)) {
10878 res = -1;
10879 break;
10880 }
10881 }
10882 }
10883 }
10884 }
10885 if (p->usedistinctiveringdetection) {
10886
10887 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10888
10889 for (counter = 0; counter < 3; counter++) {
10890
10891
10892
10893 ast_verb(3, "Checking %d,%d,%d\n",
10894 p->drings.ringnum[counter].ring[0],
10895 p->drings.ringnum[counter].ring[1],
10896 p->drings.ringnum[counter].ring[2]);
10897 distMatches = 0;
10898 for (counter1 = 0; counter1 < 3; counter1++) {
10899 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10900 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10901 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10902 curRingData[counter1]);
10903 distMatches++;
10904 }
10905 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10906 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10907 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10908 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10909 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10910 distMatches++;
10911 }
10912 }
10913 if (distMatches == 3) {
10914
10915 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10916 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10917 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10918 break;
10919 }
10920 }
10921 }
10922
10923 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10924 #if 1
10925 restore_gains(p);
10926 #endif
10927 if (res < 0) {
10928 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10929 }
10930 } else
10931 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10932 }
10933 } else
10934 cs = NULL;
10935
10936 if (number)
10937 ast_shrink_phone_number(number);
10938 ast_set_callerid(chan, number, name, number);
10939
10940 if (smdi_msg)
10941 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10942
10943 if (cs)
10944 callerid_free(cs);
10945
10946 my_handle_notify_message(chan, p, flags, -1);
10947
10948 ast_setstate(chan, AST_STATE_RING);
10949 chan->rings = 1;
10950 p->ringt = p->ringt_base;
10951 res = ast_pbx_run(chan);
10952 if (res) {
10953 ast_hangup(chan);
10954 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10955 }
10956 goto quit;
10957 default:
10958 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10959 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10960 if (res < 0)
10961 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10962 }
10963 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10964 if (res < 0)
10965 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10966 ast_hangup(chan);
10967 quit:
10968 ast_mutex_lock(&ss_thread_lock);
10969 ss_thread_count--;
10970 ast_cond_signal(&ss_thread_complete);
10971 ast_mutex_unlock(&ss_thread_lock);
10972 return NULL;
10973 }
10974
10975 struct mwi_thread_data {
10976 struct dahdi_pvt *pvt;
10977 unsigned char buf[READ_SIZE];
10978 size_t len;
10979 };
10980
10981 static int calc_energy(const unsigned char *buf, int len, format_t law)
10982 {
10983 int x;
10984 int sum = 0;
10985
10986 if (!len)
10987 return 0;
10988
10989 for (x = 0; x < len; x++)
10990 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10991
10992 return sum / len;
10993 }
10994
10995 static void *mwi_thread(void *data)
10996 {
10997 struct mwi_thread_data *mtd = data;
10998 struct callerid_state *cs;
10999 pthread_t threadid;
11000 int samples = 0;
11001 char *name, *number;
11002 int flags;
11003 int i, res;
11004 unsigned int spill_done = 0;
11005 int spill_result = -1;
11006
11007 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11008 mtd->pvt->mwimonitoractive = 0;
11009
11010 return NULL;
11011 }
11012
11013 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11014
11015 bump_gains(mtd->pvt);
11016
11017 for (;;) {
11018 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11019 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11020 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11021 goto quit;
11022 }
11023
11024 if (i & DAHDI_IOMUX_SIGEVENT) {
11025 struct ast_channel *chan;
11026
11027
11028
11029
11030 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11031
11032 switch (res) {
11033 case DAHDI_EVENT_NEONMWI_ACTIVE:
11034 case DAHDI_EVENT_NEONMWI_INACTIVE:
11035 case DAHDI_EVENT_NONE:
11036 case DAHDI_EVENT_BITSCHANGED:
11037 break;
11038 case DAHDI_EVENT_NOALARM:
11039 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11040 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11041
11042 analog_p->inalarm = 0;
11043 }
11044 mtd->pvt->inalarm = 0;
11045 handle_clear_alarms(mtd->pvt);
11046 break;
11047 case DAHDI_EVENT_ALARM:
11048 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11049 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11050
11051 analog_p->inalarm = 1;
11052 }
11053 mtd->pvt->inalarm = 1;
11054 res = get_alarms(mtd->pvt);
11055 handle_alarms(mtd->pvt, res);
11056 break;
11057 default:
11058 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11059 callerid_free(cs);
11060
11061 restore_gains(mtd->pvt);
11062 mtd->pvt->ringt = mtd->pvt->ringt_base;
11063
11064 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11065 int result;
11066 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11067 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11068 } else {
11069 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11070 }
11071 if (result) {
11072 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11073 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11074 if (res < 0)
11075 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11076 ast_hangup(chan);
11077 goto quit;
11078 }
11079 goto quit_no_clean;
11080
11081 } else {
11082 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11083 }
11084 }
11085 } else if (i & DAHDI_IOMUX_READ) {
11086 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11087 if (errno != ELAST) {
11088 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11089 goto quit;
11090 }
11091 break;
11092 }
11093 samples += res;
11094 if (!spill_done) {
11095 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11096
11097
11098
11099
11100 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11101 break;
11102 } else if (spill_result) {
11103 spill_done = 1;
11104 }
11105 } else {
11106
11107
11108
11109 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11110 break;
11111 }
11112 if (samples > (8000 * 4))
11113 break;
11114 }
11115 }
11116
11117 if (spill_result == 1) {
11118 callerid_get(cs, &name, &number, &flags);
11119 if (flags & CID_MSGWAITING) {
11120 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11121 notify_message(mtd->pvt->mailbox, 1);
11122 } else if (flags & CID_NOMSGWAITING) {
11123 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11124 notify_message(mtd->pvt->mailbox, 0);
11125 } else {
11126 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11127 }
11128 }
11129
11130
11131 quit:
11132 callerid_free(cs);
11133
11134 restore_gains(mtd->pvt);
11135
11136 quit_no_clean:
11137 mtd->pvt->mwimonitoractive = 0;
11138
11139 ast_free(mtd);
11140
11141 return NULL;
11142 }
11143
11144
11145
11146
11147
11148
11149
11150
11151 static int mwi_send_init(struct dahdi_pvt * pvt)
11152 {
11153 int x;
11154
11155 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11156
11157 if (pvt->mwisend_rpas) {
11158 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11159 pvt->mwisendactive = 1;
11160 } else if (pvt->mwisend_fsk) {
11161 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11162 pvt->mwisendactive = 1;
11163 } else {
11164 pvt->mwisendactive = 0;
11165 return 0;
11166 }
11167 #else
11168 if (mwisend_rpas) {
11169 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11170 } else {
11171 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11172 }
11173 pvt->mwisendactive = 1;
11174 #endif
11175
11176 if (pvt->cidspill) {
11177 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11178 ast_free(pvt->cidspill);
11179 pvt->cidspill = NULL;
11180 pvt->cidpos = 0;
11181 pvt->cidlen = 0;
11182 }
11183 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11184 if (!pvt->cidspill) {
11185 pvt->mwisendactive = 0;
11186 return -1;
11187 }
11188 x = DAHDI_FLUSH_BOTH;
11189 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11190 x = 3000;
11191 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11192 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11193 if (pvt->mwisend_fsk) {
11194 #endif
11195 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11196 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11197 pvt->cidpos = 0;
11198 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11199 }
11200 #endif
11201 return 0;
11202 }
11203
11204 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11205 {
11206 struct timeval now;
11207 int res;
11208
11209
11210
11211
11212 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11213 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11214 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11215
11216 switch ( pvt->mwisend_data.mwisend_current) {
11217 case MWI_SEND_SA:
11218
11219 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11220 if (res) {
11221 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11222 goto quit;
11223 }
11224 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11225 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11226 break;
11227 case MWI_SEND_SA_WAIT:
11228 break;
11229 case MWI_SEND_PAUSE:
11230 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11231 if (pvt->mwisend_fsk) {
11232 #endif
11233 gettimeofday(&now, NULL);
11234 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11235 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11236 }
11237 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11238 } else {
11239 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11240 }
11241 #endif
11242 break;
11243 case MWI_SEND_SPILL:
11244
11245 if(0 < num_read) {
11246 if (num_read > pvt->cidlen - pvt->cidpos)
11247 num_read = pvt->cidlen - pvt->cidpos;
11248 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11249 if (res > 0) {
11250 pvt->cidpos += res;
11251 if (pvt->cidpos >= pvt->cidlen) {
11252 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11253 }
11254 } else {
11255 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11256 goto quit;
11257 }
11258 }
11259 break;
11260 case MWI_SEND_CLEANUP:
11261
11262 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11263 break;
11264 default:
11265
11266 goto quit;
11267 }
11268 }
11269
11270 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11271 if (pvt->cidspill) {
11272 ast_free(pvt->cidspill);
11273 pvt->cidspill = NULL;
11274 pvt->cidpos = 0;
11275 pvt->cidlen = 0;
11276 }
11277 pvt->mwisendactive = 0;
11278 }
11279 return 0;
11280 quit:
11281 if (pvt->cidspill) {
11282 ast_free(pvt->cidspill);
11283 pvt->cidspill = NULL;
11284 pvt->cidpos = 0;
11285 pvt->cidlen = 0;
11286 }
11287 pvt->mwisendactive = 0;
11288 return -1;
11289 }
11290
11291 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11292 {
11293 int handled = 0;
11294
11295 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11296 switch (event) {
11297 case DAHDI_EVENT_RINGEROFF:
11298 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11299 handled = 1;
11300
11301 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11302 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11303 ast_free(pvt->cidspill);
11304 pvt->cidspill = NULL;
11305 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11306 pvt->mwisendactive = 0;
11307 } else {
11308 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11309 gettimeofday(&pvt->mwisend_data.pause, NULL);
11310 }
11311 }
11312 break;
11313
11314 case DAHDI_EVENT_RINGOFFHOOK:
11315 if (pvt->cidspill) {
11316 ast_free(pvt->cidspill);
11317 pvt->cidspill = NULL;
11318 pvt->cidpos = 0;
11319 pvt->cidlen = 0;
11320 }
11321 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11322 pvt->mwisendactive = 0;
11323 break;
11324 case DAHDI_EVENT_RINGERON:
11325 case DAHDI_EVENT_HOOKCOMPLETE:
11326 break;
11327 default:
11328 break;
11329 }
11330 }
11331 return handled;
11332 }
11333
11334
11335 static int dahdi_destroy_channel_bynum(int channel)
11336 {
11337 struct dahdi_pvt *cur;
11338
11339 ast_mutex_lock(&iflock);
11340 for (cur = iflist; cur; cur = cur->next) {
11341 if (cur->channel == channel) {
11342 int x = DAHDI_FLASH;
11343
11344
11345 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11346
11347 destroy_channel(cur, 1);
11348 ast_mutex_unlock(&iflock);
11349 ast_module_unref(ast_module_info->self);
11350 return RESULT_SUCCESS;
11351 }
11352 }
11353 ast_mutex_unlock(&iflock);
11354 return RESULT_FAILURE;
11355 }
11356
11357 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11358 {
11359 int res;
11360 pthread_t threadid;
11361 struct ast_channel *chan;
11362
11363
11364
11365 switch (event) {
11366 case DAHDI_EVENT_NONE:
11367 case DAHDI_EVENT_BITSCHANGED:
11368 break;
11369 case DAHDI_EVENT_WINKFLASH:
11370 case DAHDI_EVENT_RINGOFFHOOK:
11371 if (i->inalarm) break;
11372 if (i->radio) break;
11373
11374 switch (i->sig) {
11375 case SIG_FXOLS:
11376 case SIG_FXOGS:
11377 case SIG_FXOKS:
11378 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11379 if (res && (errno == EBUSY))
11380 break;
11381
11382
11383 ast_free(i->cidspill);
11384 i->cidspill = NULL;
11385 restore_conference(i);
11386
11387 if (i->immediate) {
11388 dahdi_enable_ec(i);
11389
11390 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11391 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11392 if (!chan) {
11393 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11394 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11395 if (res < 0)
11396 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11397 }
11398 } else {
11399
11400 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11401 if (chan) {
11402 if (has_voicemail(i))
11403 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11404 else
11405 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11406 if (res < 0)
11407 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11408 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11409 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11410 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11411 if (res < 0)
11412 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11413 ast_hangup(chan);
11414 }
11415 } else
11416 ast_log(LOG_WARNING, "Unable to create channel\n");
11417 }
11418 break;
11419 case SIG_FXSLS:
11420 case SIG_FXSGS:
11421 case SIG_FXSKS:
11422 i->ringt = i->ringt_base;
11423
11424 case SIG_EMWINK:
11425 case SIG_FEATD:
11426 case SIG_FEATDMF:
11427 case SIG_FEATDMF_TA:
11428 case SIG_E911:
11429 case SIG_FGC_CAMA:
11430 case SIG_FGC_CAMAMF:
11431 case SIG_FEATB:
11432 case SIG_EM:
11433 case SIG_EM_E1:
11434 case SIG_SFWINK:
11435 case SIG_SF_FEATD:
11436 case SIG_SF_FEATDMF:
11437 case SIG_SF_FEATB:
11438 case SIG_SF:
11439
11440 if (i->cid_start == CID_START_POLARITY_IN) {
11441 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11442 } else {
11443 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11444 }
11445
11446 if (!chan) {
11447 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11448 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11449 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11450 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11451 if (res < 0) {
11452 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11453 }
11454 ast_hangup(chan);
11455 }
11456 break;
11457 default:
11458 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11459 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11460 if (res < 0)
11461 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11462 return NULL;
11463 }
11464 break;
11465 case DAHDI_EVENT_NOALARM:
11466 switch (i->sig) {
11467 #if defined(HAVE_PRI)
11468 case SIG_PRI_LIB_HANDLE_CASES:
11469 ast_mutex_lock(&i->lock);
11470 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11471 ast_mutex_unlock(&i->lock);
11472 break;
11473 #endif
11474 #if defined(HAVE_SS7)
11475 case SIG_SS7:
11476 sig_ss7_set_alarm(i->sig_pvt, 0);
11477 break;
11478 #endif
11479 default:
11480 i->inalarm = 0;
11481 break;
11482 }
11483 handle_clear_alarms(i);
11484 break;
11485 case DAHDI_EVENT_ALARM:
11486 switch (i->sig) {
11487 #if defined(HAVE_PRI)
11488 case SIG_PRI_LIB_HANDLE_CASES:
11489 ast_mutex_lock(&i->lock);
11490 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11491 ast_mutex_unlock(&i->lock);
11492 break;
11493 #endif
11494 #if defined(HAVE_SS7)
11495 case SIG_SS7:
11496 sig_ss7_set_alarm(i->sig_pvt, 1);
11497 break;
11498 #endif
11499 default:
11500 i->inalarm = 1;
11501 break;
11502 }
11503 res = get_alarms(i);
11504 handle_alarms(i, res);
11505
11506 case DAHDI_EVENT_ONHOOK:
11507 if (i->radio)
11508 break;
11509
11510 switch (i->sig) {
11511 case SIG_FXOLS:
11512 case SIG_FXOGS:
11513 case SIG_FEATD:
11514 case SIG_FEATDMF:
11515 case SIG_FEATDMF_TA:
11516 case SIG_E911:
11517 case SIG_FGC_CAMA:
11518 case SIG_FGC_CAMAMF:
11519 case SIG_FEATB:
11520 case SIG_EM:
11521 case SIG_EM_E1:
11522 case SIG_EMWINK:
11523 case SIG_SF_FEATD:
11524 case SIG_SF_FEATDMF:
11525 case SIG_SF_FEATB:
11526 case SIG_SF:
11527 case SIG_SFWINK:
11528 case SIG_FXSLS:
11529 case SIG_FXSGS:
11530 case SIG_FXSKS:
11531 case SIG_FXOKS:
11532 dahdi_disable_ec(i);
11533
11534 #ifdef ZHONE_HACK
11535 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11536 usleep(1);
11537 #endif
11538 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11539 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11540 break;
11541 case SIG_SS7:
11542 case SIG_PRI_LIB_HANDLE_CASES:
11543 dahdi_disable_ec(i);
11544 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11545 break;
11546 default:
11547 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11548 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11549 return NULL;
11550 }
11551 break;
11552 case DAHDI_EVENT_POLARITY:
11553 switch (i->sig) {
11554 case SIG_FXSLS:
11555 case SIG_FXSKS:
11556 case SIG_FXSGS:
11557
11558
11559
11560
11561 if (i->hanguponpolarityswitch)
11562 i->polarity = POLARITY_REV;
11563 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11564 i->polarity = POLARITY_REV;
11565 ast_verb(2, "Starting post polarity "
11566 "CID detection on channel %d\n",
11567 i->channel);
11568 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11569 if (!chan) {
11570 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11571 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11572 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11573 }
11574 }
11575 break;
11576 default:
11577 ast_log(LOG_WARNING, "handle_init_event detected "
11578 "polarity reversal on non-FXO (SIG_FXS) "
11579 "interface %d\n", i->channel);
11580 }
11581 break;
11582 case DAHDI_EVENT_REMOVED:
11583 ast_log(LOG_NOTICE,
11584 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11585 i->channel);
11586 return i;
11587 case DAHDI_EVENT_NEONMWI_ACTIVE:
11588 if (i->mwimonitor_neon) {
11589 notify_message(i->mailbox, 1);
11590 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11591 }
11592 break;
11593 case DAHDI_EVENT_NEONMWI_INACTIVE:
11594 if (i->mwimonitor_neon) {
11595 notify_message(i->mailbox, 0);
11596 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11597 }
11598 break;
11599 }
11600 return NULL;
11601 }
11602
11603 static void *do_monitor(void *data)
11604 {
11605 int count, res, res2, spoint, pollres=0;
11606 struct dahdi_pvt *i;
11607 struct dahdi_pvt *last = NULL;
11608 struct dahdi_pvt *doomed;
11609 time_t thispass = 0, lastpass = 0;
11610 int found;
11611 char buf[1024];
11612 struct pollfd *pfds=NULL;
11613 int lastalloc = -1;
11614
11615
11616
11617 #if 0
11618 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11619 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11620 return NULL;
11621 }
11622 ast_debug(1, "Monitor starting...\n");
11623 #endif
11624 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11625
11626 for (;;) {
11627
11628 ast_mutex_lock(&iflock);
11629 if (!pfds || (lastalloc != ifcount)) {
11630 if (pfds) {
11631 ast_free(pfds);
11632 pfds = NULL;
11633 }
11634 if (ifcount) {
11635 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11636 ast_mutex_unlock(&iflock);
11637 return NULL;
11638 }
11639 }
11640 lastalloc = ifcount;
11641 }
11642
11643
11644 count = 0;
11645 for (i = iflist; i; i = i->next) {
11646 ast_mutex_lock(&i->lock);
11647 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11648 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11649 struct analog_pvt *p = i->sig_pvt;
11650
11651 if (!p)
11652 ast_log(LOG_ERROR, "No sig_pvt?\n");
11653
11654 if (!p->owner && !p->subs[SUB_REAL].owner) {
11655
11656 pfds[count].fd = i->subs[SUB_REAL].dfd;
11657 pfds[count].events = POLLPRI;
11658 pfds[count].revents = 0;
11659
11660 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11661 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11662 pfds[count].events |= POLLIN;
11663 }
11664 count++;
11665 }
11666 } else {
11667 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11668
11669 pfds[count].fd = i->subs[SUB_REAL].dfd;
11670 pfds[count].events = POLLPRI;
11671 pfds[count].revents = 0;
11672
11673
11674 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11675 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11676 pfds[count].events |= POLLIN;
11677 }
11678 count++;
11679 }
11680 }
11681 }
11682 ast_mutex_unlock(&i->lock);
11683 }
11684
11685 ast_mutex_unlock(&iflock);
11686
11687 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11688 pthread_testcancel();
11689
11690 res = poll(pfds, count, 1000);
11691 pthread_testcancel();
11692 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11693
11694
11695 if (res < 0) {
11696 if ((errno != EAGAIN) && (errno != EINTR))
11697 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11698 continue;
11699 }
11700
11701
11702 ast_mutex_lock(&iflock);
11703 found = 0;
11704 spoint = 0;
11705 lastpass = thispass;
11706 thispass = time(NULL);
11707 doomed = NULL;
11708 for (i = iflist;; i = i->next) {
11709 if (doomed) {
11710 int res;
11711 res = dahdi_destroy_channel_bynum(doomed->channel);
11712 if (res != RESULT_SUCCESS) {
11713 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11714 }
11715 doomed = NULL;
11716 }
11717 if (!i) {
11718 break;
11719 }
11720
11721 if (thispass != lastpass) {
11722 if (!found && ((i == last) || ((i == iflist) && !last))) {
11723 last = i;
11724 if (last) {
11725 struct analog_pvt *analog_p = last->sig_pvt;
11726
11727 if (analog_p
11728 && !last->mwisendactive
11729 && (last->sig & __DAHDI_SIG_FXO)
11730 && !analog_p->fxsoffhookstate
11731 && !last->owner
11732 && !ast_strlen_zero(last->mailbox)
11733 && (thispass - analog_p->onhooktime > 3)) {
11734 res = has_voicemail(last);
11735 if (analog_p->msgstate != res) {
11736
11737 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11738 if (res2) {
11739
11740 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11741 }
11742
11743 if (mwi_send_init(last)) {
11744 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11745 }
11746 analog_p->msgstate = res;
11747 found ++;
11748 }
11749 }
11750 last = last->next;
11751 }
11752 }
11753 }
11754 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11755 if (i->radio && !i->owner)
11756 {
11757 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11758 if (res)
11759 {
11760 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11761
11762 ast_mutex_unlock(&iflock);
11763 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11764 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11765 else
11766 doomed = handle_init_event(i, res);
11767 ast_mutex_lock(&iflock);
11768 }
11769 continue;
11770 }
11771 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11772 if (pollres & POLLIN) {
11773 if (i->owner || i->subs[SUB_REAL].owner) {
11774 #ifdef HAVE_PRI
11775 if (!i->pri)
11776 #endif
11777 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11778 continue;
11779 }
11780 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11781 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11782 continue;
11783 }
11784 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11785 if (res > 0) {
11786 if (i->mwimonitor_fsk) {
11787 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11788 pthread_attr_t attr;
11789 pthread_t threadid;
11790 struct mwi_thread_data *mtd;
11791
11792 pthread_attr_init(&attr);
11793 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11794
11795 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11796 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11797 mtd->pvt = i;
11798 memcpy(mtd->buf, buf, res);
11799 mtd->len = res;
11800 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11801 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11802 ast_free(mtd);
11803 }
11804 i->mwimonitoractive = 1;
11805 }
11806 }
11807
11808 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11809 int energy;
11810 struct timeval now;
11811
11812
11813
11814 if (1 == i->dtmfcid_holdoff_state) {
11815 gettimeofday(&i->dtmfcid_delay, NULL);
11816 i->dtmfcid_holdoff_state = 2;
11817 } else if (2 == i->dtmfcid_holdoff_state) {
11818 gettimeofday(&now, NULL);
11819 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11820 i->dtmfcid_holdoff_state = 0;
11821 }
11822 } else {
11823 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11824 if (!i->mwisendactive && energy > dtmfcid_level) {
11825 pthread_t threadid;
11826 struct ast_channel *chan;
11827 ast_mutex_unlock(&iflock);
11828 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11829
11830 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11831 i->dtmfcid_holdoff_state = 1;
11832 } else {
11833 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11834 if (!chan) {
11835 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11836 } else {
11837 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11838 if (res) {
11839 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11840 } else {
11841 i->dtmfcid_holdoff_state = 1;
11842 }
11843 }
11844 }
11845 ast_mutex_lock(&iflock);
11846 }
11847 }
11848 }
11849 if (i->mwisendactive) {
11850 mwi_send_process_buffer(i, res);
11851 }
11852 } else {
11853 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11854 }
11855 }
11856 if (pollres & POLLPRI) {
11857 if (i->owner || i->subs[SUB_REAL].owner) {
11858 #ifdef HAVE_PRI
11859 if (!i->pri)
11860 #endif
11861 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11862 continue;
11863 }
11864 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11865 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11866
11867 ast_mutex_unlock(&iflock);
11868 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11869 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11870 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11871 else
11872 doomed = handle_init_event(i, res);
11873 }
11874 ast_mutex_lock(&iflock);
11875 }
11876 }
11877 }
11878 ast_mutex_unlock(&iflock);
11879 }
11880
11881 return NULL;
11882
11883 }
11884
11885 static int restart_monitor(void)
11886 {
11887
11888 if (monitor_thread == AST_PTHREADT_STOP)
11889 return 0;
11890 ast_mutex_lock(&monlock);
11891 if (monitor_thread == pthread_self()) {
11892 ast_mutex_unlock(&monlock);
11893 ast_log(LOG_WARNING, "Cannot kill myself\n");
11894 return -1;
11895 }
11896 if (monitor_thread != AST_PTHREADT_NULL) {
11897
11898 pthread_kill(monitor_thread, SIGURG);
11899 } else {
11900
11901 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11902 ast_mutex_unlock(&monlock);
11903 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11904 return -1;
11905 }
11906 }
11907 ast_mutex_unlock(&monlock);
11908 return 0;
11909 }
11910
11911 #if defined(HAVE_PRI)
11912 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11913 {
11914 int x;
11915 int trunkgroup;
11916
11917 trunkgroup = pris[*span].mastertrunkgroup;
11918 if (trunkgroup) {
11919
11920 for (x = 0; x < NUM_SPANS; x++) {
11921 if (pris[x].pri.trunkgroup == trunkgroup) {
11922 *span = x;
11923 return 0;
11924 }
11925 }
11926 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11927 *span = -1;
11928 } else {
11929 if (pris[*span].pri.trunkgroup) {
11930 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);
11931 *span = -1;
11932 } else if (pris[*span].mastertrunkgroup) {
11933 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11934 *span = -1;
11935 } else {
11936 if (si->totalchans == 31) {
11937
11938 pris[*span].dchannels[0] = 16 + offset;
11939 } else if (si->totalchans == 24) {
11940
11941 pris[*span].dchannels[0] = 24 + offset;
11942 } else if (si->totalchans == 3) {
11943
11944 pris[*span].dchannels[0] = 3 + offset;
11945 } else {
11946 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);
11947 *span = -1;
11948 return 0;
11949 }
11950 pris[*span].pri.span = *span + 1;
11951 }
11952 }
11953 return 0;
11954 }
11955 #endif
11956
11957 #if defined(HAVE_PRI)
11958 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11959 {
11960 struct dahdi_spaninfo si;
11961 struct dahdi_params p;
11962 int fd;
11963 int span;
11964 int ospan=0;
11965 int x,y;
11966 for (x = 0; x < NUM_SPANS; x++) {
11967 if (pris[x].pri.trunkgroup == trunkgroup) {
11968 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11969 return -1;
11970 }
11971 }
11972 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11973 if (!channels[y])
11974 break;
11975 memset(&si, 0, sizeof(si));
11976 memset(&p, 0, sizeof(p));
11977 fd = open("/dev/dahdi/channel", O_RDWR);
11978 if (fd < 0) {
11979 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11980 return -1;
11981 }
11982 x = channels[y];
11983 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11984 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11985 close(fd);
11986 return -1;
11987 }
11988 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11989 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11990 return -1;
11991 }
11992 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11993 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11994 close(fd);
11995 return -1;
11996 }
11997 span = p.spanno - 1;
11998 if (pris[span].pri.trunkgroup) {
11999 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12000 close(fd);
12001 return -1;
12002 }
12003 if (pris[span].pri.pvts[0]) {
12004 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12005 close(fd);
12006 return -1;
12007 }
12008 if (!y) {
12009 pris[span].pri.trunkgroup = trunkgroup;
12010 ospan = span;
12011 }
12012 pris[ospan].dchannels[y] = channels[y];
12013 pris[span].pri.span = span + 1;
12014 close(fd);
12015 }
12016 return 0;
12017 }
12018 #endif
12019
12020 #if defined(HAVE_PRI)
12021 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12022 {
12023 if (pris[span].mastertrunkgroup) {
12024 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);
12025 return -1;
12026 }
12027 pris[span].mastertrunkgroup = trunkgroup;
12028 pris[span].prilogicalspan = logicalspan;
12029 return 0;
12030 }
12031 #endif
12032
12033 #if defined(HAVE_SS7)
12034 static unsigned int parse_pointcode(const char *pcstring)
12035 {
12036 unsigned int code1, code2, code3;
12037 int numvals;
12038
12039 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12040 if (numvals == 1)
12041 return code1;
12042 if (numvals == 3)
12043 return (code1 << 16) | (code2 << 8) | code3;
12044
12045 return 0;
12046 }
12047 #endif
12048
12049 #if defined(HAVE_SS7)
12050 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12051 {
12052 if ((linkset < 0) || (linkset >= NUM_SPANS))
12053 return NULL;
12054 else
12055 return &linksets[linkset - 1];
12056 }
12057 #endif
12058
12059 #ifdef HAVE_OPENR2
12060 static void dahdi_r2_destroy_links(void)
12061 {
12062 int i = 0;
12063 if (!r2links) {
12064 return;
12065 }
12066 for (; i < r2links_count; i++) {
12067 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12068 pthread_cancel(r2links[i]->r2master);
12069 pthread_join(r2links[i]->r2master, NULL);
12070 openr2_context_delete(r2links[i]->protocol_context);
12071 }
12072 ast_free(r2links[i]);
12073 }
12074 ast_free(r2links);
12075 r2links = NULL;
12076 r2links_count = 0;
12077 }
12078
12079 #define R2_LINK_CAPACITY 10
12080 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12081 {
12082 struct dahdi_mfcr2 *new_r2link = NULL;
12083 struct dahdi_mfcr2 **new_r2links = NULL;
12084
12085
12086 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12087 new_r2link = ast_calloc(1, sizeof(**r2links));
12088 if (!new_r2link) {
12089 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12090 return NULL;
12091 }
12092 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12093 if (!new_r2links) {
12094 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12095 ast_free(new_r2link);
12096 return NULL;
12097 }
12098 r2links = new_r2links;
12099 new_r2link->r2master = AST_PTHREADT_NULL;
12100 r2links[r2links_count] = new_r2link;
12101 r2links_count++;
12102 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12103 }
12104 return r2links[r2links_count - 1];
12105 }
12106
12107 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12108 {
12109 char tmplogdir[] = "/tmp";
12110 char logdir[OR2_MAX_PATH];
12111 int threshold = 0;
12112 int snres = 0;
12113 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12114 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12115 conf->mfcr2.max_dnis);
12116 if (!r2_link->protocol_context) {
12117 return -1;
12118 }
12119 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12120 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12121 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12122 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12123 #endif
12124 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12125 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12126 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12127 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12128 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12129 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12130 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12131 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12132 }
12133 } else {
12134 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12135 if (snres >= sizeof(logdir)) {
12136 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12137 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12138 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12139 }
12140 } else {
12141 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12142 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12143 }
12144 }
12145 }
12146 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12147 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12148 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12149 }
12150 }
12151 r2_link->monitored_count = 0;
12152 return 0;
12153 }
12154 #endif
12155
12156
12157
12158
12159
12160
12161 static int sigtype_to_signalling(int sigtype)
12162 {
12163 return sigtype;
12164 }
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12179 {
12180 struct stat stbuf;
12181 int num;
12182
12183 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12184 if (stat(path, &stbuf) < 0) {
12185 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12186 return -errno;
12187 }
12188 if (!S_ISCHR(stbuf.st_mode)) {
12189 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12190 return -EINVAL;
12191 }
12192 num = minor(stbuf.st_rdev);
12193 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12194 return num;
12195
12196 }
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12213 {
12214
12215 struct dahdi_pvt *tmp;
12216 char fn[80];
12217 struct dahdi_bufferinfo bi;
12218
12219 int res;
12220 #if defined(HAVE_PRI)
12221 int span = 0;
12222 #endif
12223 int here = 0;
12224 int x;
12225 struct analog_pvt *analog_p = NULL;
12226 struct dahdi_params p;
12227 #if defined(HAVE_PRI)
12228 struct dahdi_spaninfo si;
12229 struct sig_pri_chan *pri_chan = NULL;
12230 #endif
12231 #if defined(HAVE_SS7)
12232 struct sig_ss7_chan *ss7_chan = NULL;
12233 #endif
12234
12235
12236 for (tmp = iflist; tmp; tmp = tmp->next) {
12237 if (!tmp->destroy) {
12238 if (tmp->channel == channel) {
12239
12240 here = 1;
12241 break;
12242 }
12243 if (tmp->channel > channel) {
12244
12245 tmp = NULL;
12246 break;
12247 }
12248 }
12249 }
12250
12251 if (!here && reloading != 1) {
12252 tmp = ast_calloc(1, sizeof(*tmp));
12253 if (!tmp) {
12254 return NULL;
12255 }
12256 tmp->cc_params = ast_cc_config_params_init();
12257 if (!tmp->cc_params) {
12258 ast_free(tmp);
12259 return NULL;
12260 }
12261 ast_mutex_init(&tmp->lock);
12262 ifcount++;
12263 for (x = 0; x < 3; x++)
12264 tmp->subs[x].dfd = -1;
12265 tmp->channel = channel;
12266 tmp->priindication_oob = conf->chan.priindication_oob;
12267 }
12268
12269 if (tmp) {
12270 int chan_sig = conf->chan.sig;
12271
12272
12273 if (reloading && tmp->vars) {
12274 ast_variables_destroy(tmp->vars);
12275 tmp->vars = NULL;
12276 }
12277
12278
12279 if (!here) {
12280
12281 if ((channel != CHAN_PSEUDO)) {
12282 int count = 0;
12283
12284 snprintf(fn, sizeof(fn), "%d", channel);
12285
12286 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12287 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12288 usleep(1);
12289 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12290 count++;
12291 }
12292
12293 if (tmp->subs[SUB_REAL].dfd < 0) {
12294 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);
12295 destroy_dahdi_pvt(tmp);
12296 return NULL;
12297 }
12298 memset(&p, 0, sizeof(p));
12299 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12300 if (res < 0) {
12301 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12302 destroy_dahdi_pvt(tmp);
12303 return NULL;
12304 }
12305 if (conf->is_sig_auto)
12306 chan_sig = sigtype_to_signalling(p.sigtype);
12307 if (p.sigtype != (chan_sig & 0x3ffff)) {
12308 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));
12309 destroy_dahdi_pvt(tmp);
12310 return NULL;
12311 }
12312 tmp->law_default = p.curlaw;
12313 tmp->law = p.curlaw;
12314 tmp->span = p.spanno;
12315 #if defined(HAVE_PRI)
12316 span = p.spanno - 1;
12317 #endif
12318 } else {
12319 chan_sig = 0;
12320 }
12321 tmp->sig = chan_sig;
12322 tmp->outsigmod = conf->chan.outsigmod;
12323
12324 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12325 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12326 if (!analog_p) {
12327 destroy_dahdi_pvt(tmp);
12328 return NULL;
12329 }
12330 tmp->sig_pvt = analog_p;
12331 }
12332 #if defined(HAVE_SS7)
12333 if (chan_sig == SIG_SS7) {
12334 struct dahdi_ss7 *ss7;
12335 int clear = 0;
12336
12337 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12338 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12339 destroy_dahdi_pvt(tmp);
12340 return NULL;
12341 }
12342
12343 ss7 = ss7_resolve_linkset(cur_linkset);
12344 if (!ss7) {
12345 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12346 destroy_dahdi_pvt(tmp);
12347 return NULL;
12348 }
12349 ss7->ss7.span = cur_linkset;
12350 if (cur_cicbeginswith < 0) {
12351 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12352 destroy_dahdi_pvt(tmp);
12353 return NULL;
12354 }
12355 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12356 if (!ss7_chan) {
12357 destroy_dahdi_pvt(tmp);
12358 return NULL;
12359 }
12360 tmp->sig_pvt = ss7_chan;
12361 tmp->ss7 = &ss7->ss7;
12362
12363 ss7_chan->channel = tmp->channel;
12364 ss7_chan->cic = cur_cicbeginswith++;
12365
12366
12367 ss7_chan->dpc = cur_defaultdpc;
12368
12369 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12370
12371 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12372 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12373 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12374 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12375
12376 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12377 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12378 }
12379 #endif
12380 #ifdef HAVE_OPENR2
12381 if (chan_sig == SIG_MFCR2) {
12382 struct dahdi_mfcr2 *r2_link;
12383 r2_link = dahdi_r2_get_link();
12384 if (!r2_link) {
12385 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12386 destroy_dahdi_pvt(tmp);
12387 return NULL;
12388 }
12389 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12390 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12391 destroy_dahdi_pvt(tmp);
12392 return NULL;
12393 }
12394 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12395 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12396 destroy_dahdi_pvt(tmp);
12397 return NULL;
12398 }
12399 r2_link->pvts[r2_link->numchans++] = tmp;
12400 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12401 tmp->subs[SUB_REAL].dfd,
12402 NULL, NULL);
12403 if (!tmp->r2chan) {
12404 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12405 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12406 destroy_dahdi_pvt(tmp);
12407 return NULL;
12408 }
12409 tmp->mfcr2 = r2_link;
12410 if (conf->mfcr2.call_files) {
12411 openr2_chan_enable_call_files(tmp->r2chan);
12412 }
12413 openr2_chan_set_client_data(tmp->r2chan, tmp);
12414
12415 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12416 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12417 tmp->mfcr2_category = conf->mfcr2.category;
12418 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12419 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12420 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12421 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12422 tmp->mfcr2call = 0;
12423 tmp->mfcr2_dnis_index = 0;
12424 tmp->mfcr2_ani_index = 0;
12425 r2_link->monitored_count++;
12426 }
12427 #endif
12428 #ifdef HAVE_PRI
12429 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12430 int offset;
12431 int matchesdchan;
12432 int x,y;
12433 int myswitchtype = 0;
12434
12435 offset = 0;
12436 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12437 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12438 destroy_dahdi_pvt(tmp);
12439 return NULL;
12440 }
12441 if (span >= NUM_SPANS) {
12442 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12443 destroy_dahdi_pvt(tmp);
12444 return NULL;
12445 } else {
12446 si.spanno = 0;
12447 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12448 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12449 destroy_dahdi_pvt(tmp);
12450 return NULL;
12451 }
12452
12453 tmp->logicalspan = pris[span].prilogicalspan;
12454 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12455 if (span < 0) {
12456 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12457 destroy_dahdi_pvt(tmp);
12458 return NULL;
12459 }
12460 myswitchtype = conf->pri.pri.switchtype;
12461
12462 matchesdchan=0;
12463 for (x = 0; x < NUM_SPANS; x++) {
12464 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12465 if (pris[x].dchannels[y] == tmp->channel) {
12466 matchesdchan = 1;
12467 break;
12468 }
12469 }
12470 }
12471 if (!matchesdchan) {
12472 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12473 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12474 destroy_dahdi_pvt(tmp);
12475 return NULL;
12476 }
12477 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12478 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12479 destroy_dahdi_pvt(tmp);
12480 return NULL;
12481 }
12482 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12483 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));
12484 destroy_dahdi_pvt(tmp);
12485 return NULL;
12486 }
12487 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12488 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12489 destroy_dahdi_pvt(tmp);
12490 return NULL;
12491 }
12492 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12493 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12494 destroy_dahdi_pvt(tmp);
12495 return NULL;
12496 }
12497 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12498 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12499 destroy_dahdi_pvt(tmp);
12500 return NULL;
12501 }
12502 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12503 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12504 destroy_dahdi_pvt(tmp);
12505 return NULL;
12506 }
12507 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12508 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12509 pris[span].pri.trunkgroup);
12510 destroy_dahdi_pvt(tmp);
12511 return NULL;
12512 }
12513
12514 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12515 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12516 if (!pri_chan) {
12517 destroy_dahdi_pvt(tmp);
12518 return NULL;
12519 }
12520 tmp->sig_pvt = pri_chan;
12521 tmp->pri = &pris[span].pri;
12522
12523 tmp->priexclusive = conf->chan.priexclusive;
12524
12525 if (!tmp->pri->cc_params) {
12526 tmp->pri->cc_params = ast_cc_config_params_init();
12527 if (!tmp->pri->cc_params) {
12528 destroy_dahdi_pvt(tmp);
12529 return NULL;
12530 }
12531 }
12532 ast_cc_copy_config_params(tmp->pri->cc_params,
12533 conf->chan.cc_params);
12534
12535 pris[span].pri.sig = chan_sig;
12536 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12537 pris[span].pri.switchtype = myswitchtype;
12538 pris[span].pri.nsf = conf->pri.pri.nsf;
12539 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12540 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12541 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12542 pris[span].pri.minunused = conf->pri.pri.minunused;
12543 pris[span].pri.minidle = conf->pri.pri.minidle;
12544 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12545 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12546 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12547 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12548 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12549 #endif
12550 #ifdef HAVE_PRI_INBANDDISCONNECT
12551 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12552 #endif
12553 #if defined(HAVE_PRI_CALL_HOLD)
12554 pris[span].pri.hold_disconnect_transfer =
12555 conf->pri.pri.hold_disconnect_transfer;
12556 #endif
12557 #if defined(HAVE_PRI_CCSS)
12558 pris[span].pri.cc_ptmp_recall_mode =
12559 conf->pri.pri.cc_ptmp_recall_mode;
12560 pris[span].pri.cc_qsig_signaling_link_req =
12561 conf->pri.pri.cc_qsig_signaling_link_req;
12562 pris[span].pri.cc_qsig_signaling_link_rsp =
12563 conf->pri.pri.cc_qsig_signaling_link_rsp;
12564 #endif
12565 #if defined(HAVE_PRI_CALL_WAITING)
12566 pris[span].pri.max_call_waiting_calls =
12567 conf->pri.pri.max_call_waiting_calls;
12568 pris[span].pri.allow_call_waiting_calls =
12569 conf->pri.pri.allow_call_waiting_calls;
12570 #endif
12571 pris[span].pri.transfer = conf->chan.transfer;
12572 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12573 #if defined(HAVE_PRI_L2_PERSISTENCE)
12574 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12575 #endif
12576 #if defined(HAVE_PRI_AOC_EVENTS)
12577 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12578 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12579 #endif
12580 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12581 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12582 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12583 #if defined(HAVE_PRI_MWI)
12584 ast_copy_string(pris[span].pri.mwi_mailboxes,
12585 conf->pri.pri.mwi_mailboxes,
12586 sizeof(pris[span].pri.mwi_mailboxes));
12587 #endif
12588 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12589 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12590 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12591 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12592 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12593 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12594 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12595 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12596
12597 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12598 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12599 }
12600
12601 #if defined(HAVE_PRI_CALL_WAITING)
12602
12603 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12604 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12605 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12606 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12607 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12608 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12609 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12610 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12611 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12612 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12613 #endif
12614 } else {
12615 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12616 destroy_dahdi_pvt(tmp);
12617 return NULL;
12618 }
12619 }
12620 }
12621 #endif
12622 } else {
12623
12624 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));
12625 chan_sig = tmp->sig;
12626 if (tmp->subs[SUB_REAL].dfd > -1) {
12627 memset(&p, 0, sizeof(p));
12628 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12629 }
12630 }
12631
12632 switch (chan_sig) {
12633 case SIG_FXSKS:
12634 case SIG_FXSLS:
12635 case SIG_EM:
12636 case SIG_EM_E1:
12637 case SIG_EMWINK:
12638 case SIG_FEATD:
12639 case SIG_FEATDMF:
12640 case SIG_FEATDMF_TA:
12641 case SIG_FEATB:
12642 case SIG_E911:
12643 case SIG_SF:
12644 case SIG_SFWINK:
12645 case SIG_FGC_CAMA:
12646 case SIG_FGC_CAMAMF:
12647 case SIG_SF_FEATD:
12648 case SIG_SF_FEATDMF:
12649 case SIG_SF_FEATB:
12650 p.starttime = 250;
12651 break;
12652 }
12653
12654 if (tmp->radio) {
12655
12656 p.channo = channel;
12657 p.rxwinktime = 1;
12658 p.rxflashtime = 1;
12659 p.starttime = 1;
12660 p.debouncetime = 5;
12661 } else {
12662 p.channo = channel;
12663
12664 if (conf->timing.prewinktime >= 0)
12665 p.prewinktime = conf->timing.prewinktime;
12666 if (conf->timing.preflashtime >= 0)
12667 p.preflashtime = conf->timing.preflashtime;
12668 if (conf->timing.winktime >= 0)
12669 p.winktime = conf->timing.winktime;
12670 if (conf->timing.flashtime >= 0)
12671 p.flashtime = conf->timing.flashtime;
12672 if (conf->timing.starttime >= 0)
12673 p.starttime = conf->timing.starttime;
12674 if (conf->timing.rxwinktime >= 0)
12675 p.rxwinktime = conf->timing.rxwinktime;
12676 if (conf->timing.rxflashtime >= 0)
12677 p.rxflashtime = conf->timing.rxflashtime;
12678 if (conf->timing.debouncetime >= 0)
12679 p.debouncetime = conf->timing.debouncetime;
12680 }
12681
12682
12683 if (tmp->subs[SUB_REAL].dfd >= 0)
12684 {
12685 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12686 if (res < 0) {
12687 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12688 destroy_dahdi_pvt(tmp);
12689 return NULL;
12690 }
12691 }
12692 #if 1
12693 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12694 memset(&bi, 0, sizeof(bi));
12695 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12696 if (!res) {
12697 bi.txbufpolicy = conf->chan.buf_policy;
12698 bi.rxbufpolicy = conf->chan.buf_policy;
12699 bi.numbufs = conf->chan.buf_no;
12700 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12701 if (res < 0) {
12702 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12703 }
12704 } else {
12705 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12706 }
12707 tmp->buf_policy = conf->chan.buf_policy;
12708 tmp->buf_no = conf->chan.buf_no;
12709 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12710 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12711 tmp->faxbuf_no = conf->chan.faxbuf_no;
12712
12713
12714
12715
12716 tmp->bufsize = bi.bufsize;
12717 }
12718 #endif
12719 tmp->immediate = conf->chan.immediate;
12720 tmp->transfertobusy = conf->chan.transfertobusy;
12721 if (chan_sig & __DAHDI_SIG_FXS) {
12722 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12723 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12724 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12725 }
12726 tmp->ringt_base = ringt_base;
12727 tmp->firstradio = 0;
12728 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12729 tmp->permcallwaiting = conf->chan.callwaiting;
12730 else
12731 tmp->permcallwaiting = 0;
12732
12733 tmp->destroy = 0;
12734 tmp->drings = conf->chan.drings;
12735
12736
12737 if (tmp->drings.ringnum[0].range == 0)
12738 tmp->drings.ringnum[0].range = 10;
12739 if (tmp->drings.ringnum[1].range == 0)
12740 tmp->drings.ringnum[1].range = 10;
12741 if (tmp->drings.ringnum[2].range == 0)
12742 tmp->drings.ringnum[2].range = 10;
12743
12744 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12745 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12746 tmp->threewaycalling = conf->chan.threewaycalling;
12747 tmp->adsi = conf->chan.adsi;
12748 tmp->use_smdi = conf->chan.use_smdi;
12749 tmp->permhidecallerid = conf->chan.hidecallerid;
12750 tmp->hidecalleridname = conf->chan.hidecalleridname;
12751 tmp->callreturn = conf->chan.callreturn;
12752 tmp->echocancel = conf->chan.echocancel;
12753 tmp->echotraining = conf->chan.echotraining;
12754 tmp->pulse = conf->chan.pulse;
12755 if (tmp->echocancel.head.tap_length) {
12756 tmp->echocanbridged = conf->chan.echocanbridged;
12757 } else {
12758 if (conf->chan.echocanbridged)
12759 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12760 tmp->echocanbridged = 0;
12761 }
12762 tmp->busydetect = conf->chan.busydetect;
12763 tmp->busycount = conf->chan.busycount;
12764 tmp->busy_tonelength = conf->chan.busy_tonelength;
12765 tmp->busy_quietlength = conf->chan.busy_quietlength;
12766 tmp->callprogress = conf->chan.callprogress;
12767 tmp->waitfordialtone = conf->chan.waitfordialtone;
12768 tmp->cancallforward = conf->chan.cancallforward;
12769 tmp->dtmfrelax = conf->chan.dtmfrelax;
12770 tmp->callwaiting = tmp->permcallwaiting;
12771 tmp->hidecallerid = tmp->permhidecallerid;
12772 tmp->channel = channel;
12773 tmp->stripmsd = conf->chan.stripmsd;
12774 tmp->use_callerid = conf->chan.use_callerid;
12775 tmp->cid_signalling = conf->chan.cid_signalling;
12776 tmp->cid_start = conf->chan.cid_start;
12777 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12778 tmp->restrictcid = conf->chan.restrictcid;
12779 tmp->use_callingpres = conf->chan.use_callingpres;
12780 if (tmp->usedistinctiveringdetection) {
12781 if (!tmp->use_callerid) {
12782 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12783 tmp->use_callerid = 1;
12784 }
12785 }
12786
12787 if (tmp->cid_signalling == CID_SIG_SMDI) {
12788 if (!tmp->use_smdi) {
12789 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12790 tmp->use_smdi = 1;
12791 }
12792 }
12793 if (tmp->use_smdi) {
12794 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12795 if (!(tmp->smdi_iface)) {
12796 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12797 tmp->use_smdi = 0;
12798 }
12799 }
12800
12801 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12802 tmp->amaflags = conf->chan.amaflags;
12803 if (!here) {
12804 tmp->confno = -1;
12805 tmp->propconfno = -1;
12806 }
12807 tmp->canpark = conf->chan.canpark;
12808 tmp->transfer = conf->chan.transfer;
12809 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12810 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12811 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12812 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12813 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12814 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12815 tmp->cid_ton = 0;
12816 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12817 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12818 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12819 } else {
12820 tmp->cid_num[0] = '\0';
12821 tmp->cid_name[0] = '\0';
12822 }
12823 #if defined(HAVE_PRI)
12824 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12825 tmp->cid_tag[0] = '\0';
12826 } else
12827 #endif
12828 {
12829 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12830 }
12831 tmp->cid_subaddr[0] = '\0';
12832 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12833 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12834 char *mailbox, *context;
12835 mailbox = context = ast_strdupa(tmp->mailbox);
12836 strsep(&context, "@");
12837 if (ast_strlen_zero(context))
12838 context = "default";
12839 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12840 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12841 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12842 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12843 AST_EVENT_IE_END);
12844 }
12845 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12846 tmp->mwisend_setting = conf->chan.mwisend_setting;
12847 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12848 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12849 #endif
12850
12851 tmp->group = conf->chan.group;
12852 tmp->callgroup = conf->chan.callgroup;
12853 tmp->pickupgroup= conf->chan.pickupgroup;
12854 if (conf->chan.vars) {
12855 struct ast_variable *v, *tmpvar;
12856 for (v = conf->chan.vars ; v ; v = v->next) {
12857 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12858 tmpvar->next = tmp->vars;
12859 tmp->vars = tmpvar;
12860 }
12861 }
12862 }
12863 tmp->cid_rxgain = conf->chan.cid_rxgain;
12864 tmp->rxgain = conf->chan.rxgain;
12865 tmp->txgain = conf->chan.txgain;
12866 tmp->txdrc = conf->chan.txdrc;
12867 tmp->rxdrc = conf->chan.rxdrc;
12868 tmp->tonezone = conf->chan.tonezone;
12869 if (tmp->subs[SUB_REAL].dfd > -1) {
12870 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12871 if (tmp->dsp)
12872 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12873 update_conf(tmp);
12874 if (!here) {
12875 switch (chan_sig) {
12876 case SIG_PRI_LIB_HANDLE_CASES:
12877 case SIG_SS7:
12878 case SIG_MFCR2:
12879 break;
12880 default:
12881
12882 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12883 break;
12884 }
12885 }
12886 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12887 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12888
12889 switch (tmp->sig) {
12890 #ifdef HAVE_PRI
12891 case SIG_PRI_LIB_HANDLE_CASES:
12892 sig_pri_set_alarm(tmp->sig_pvt, 1);
12893 break;
12894 #endif
12895 #if defined(HAVE_SS7)
12896 case SIG_SS7:
12897 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12898 break;
12899 #endif
12900 default:
12901
12902 analog_p = tmp->sig_pvt;
12903 if (analog_p) {
12904 analog_p->inalarm = 1;
12905 }
12906 tmp->inalarm = 1;
12907 break;
12908 }
12909 handle_alarms(tmp, res);
12910 }
12911 }
12912
12913 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12914 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12915 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12916 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12917 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12918
12919 if (!here) {
12920 tmp->locallyblocked = 0;
12921 tmp->remotelyblocked = 0;
12922 switch (tmp->sig) {
12923 #if defined(HAVE_PRI)
12924 case SIG_PRI_LIB_HANDLE_CASES:
12925 tmp->inservice = 1;
12926 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12927 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12928 if (chan_sig == SIG_PRI) {
12929 char db_chan_name[20];
12930 char db_answer[5];
12931
12932
12933
12934
12935
12936 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12937 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12938 unsigned *why;
12939
12940 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12941 if (tmp->pri->enable_service_message_support) {
12942 char state;
12943
12944 sscanf(db_answer, "%1c:%30u", &state, why);
12945
12946
12947 *why &= (SRVST_NEAREND | SRVST_FAREND);
12948 }
12949 if (!*why) {
12950 ast_db_del(db_chan_name, SRVST_DBKEY);
12951 }
12952 }
12953 }
12954 #endif
12955 break;
12956 #endif
12957 #if defined(HAVE_SS7)
12958 case SIG_SS7:
12959 tmp->inservice = 0;
12960 break;
12961 #endif
12962 default:
12963
12964 tmp->inservice = 1;
12965 break;
12966 }
12967 }
12968
12969 switch (tmp->sig) {
12970 #if defined(HAVE_PRI)
12971 case SIG_PRI_LIB_HANDLE_CASES:
12972 if (pri_chan) {
12973 pri_chan->channel = tmp->channel;
12974 pri_chan->hidecallerid = tmp->hidecallerid;
12975 pri_chan->hidecalleridname = tmp->hidecalleridname;
12976 pri_chan->immediate = tmp->immediate;
12977 pri_chan->inalarm = tmp->inalarm;
12978 pri_chan->priexclusive = tmp->priexclusive;
12979 pri_chan->priindication_oob = tmp->priindication_oob;
12980 pri_chan->use_callerid = tmp->use_callerid;
12981 pri_chan->use_callingpres = tmp->use_callingpres;
12982 ast_copy_string(pri_chan->context, tmp->context,
12983 sizeof(pri_chan->context));
12984 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12985 sizeof(pri_chan->mohinterpret));
12986 pri_chan->stripmsd = tmp->stripmsd;
12987 }
12988 break;
12989 #endif
12990 #if defined(HAVE_SS7)
12991 case SIG_SS7:
12992 if (ss7_chan) {
12993 ss7_chan->inalarm = tmp->inalarm;
12994
12995 ss7_chan->stripmsd = tmp->stripmsd;
12996 ss7_chan->hidecallerid = tmp->hidecallerid;
12997 ss7_chan->use_callerid = tmp->use_callerid;
12998 ss7_chan->use_callingpres = tmp->use_callingpres;
12999 ss7_chan->immediate = tmp->immediate;
13000 ss7_chan->locallyblocked = tmp->locallyblocked;
13001 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13002 ast_copy_string(ss7_chan->context, tmp->context,
13003 sizeof(ss7_chan->context));
13004 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13005 sizeof(ss7_chan->mohinterpret));
13006 }
13007 break;
13008 #endif
13009 default:
13010
13011 analog_p = tmp->sig_pvt;
13012 if (analog_p) {
13013 analog_p->channel = tmp->channel;
13014 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13015 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13016 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13017 analog_p->permcallwaiting = conf->chan.callwaiting;
13018 analog_p->callreturn = conf->chan.callreturn;
13019 analog_p->cancallforward = conf->chan.cancallforward;
13020 analog_p->canpark = conf->chan.canpark;
13021 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13022 analog_p->immediate = conf->chan.immediate;
13023 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13024 analog_p->pulse = conf->chan.pulse;
13025 analog_p->threewaycalling = conf->chan.threewaycalling;
13026 analog_p->transfer = conf->chan.transfer;
13027 analog_p->transfertobusy = conf->chan.transfertobusy;
13028 analog_p->use_callerid = tmp->use_callerid;
13029 analog_p->use_smdi = tmp->use_smdi;
13030 analog_p->smdi_iface = tmp->smdi_iface;
13031 analog_p->outsigmod = ANALOG_SIG_NONE;
13032 analog_p->echotraining = conf->chan.echotraining;
13033 analog_p->cid_signalling = conf->chan.cid_signalling;
13034 analog_p->stripmsd = conf->chan.stripmsd;
13035 switch (conf->chan.cid_start) {
13036 case CID_START_POLARITY:
13037 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13038 break;
13039 case CID_START_POLARITY_IN:
13040 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13041 break;
13042 case CID_START_DTMF_NOALERT:
13043 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13044 break;
13045 default:
13046 analog_p->cid_start = ANALOG_CID_START_RING;
13047 break;
13048 }
13049 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13050 analog_p->ringt = conf->chan.ringt;
13051 analog_p->ringt_base = ringt_base;
13052 analog_p->chan_tech = &dahdi_tech;
13053 analog_p->onhooktime = time(NULL);
13054 if (chan_sig & __DAHDI_SIG_FXO) {
13055 memset(&p, 0, sizeof(p));
13056 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13057 if (!res) {
13058 analog_p->fxsoffhookstate = p.rxisoffhook;
13059 }
13060 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13061 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13062 #endif
13063 }
13064 analog_p->msgstate = -1;
13065
13066 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13067 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13068 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13069
13070 analog_config_complete(analog_p);
13071 }
13072 break;
13073 }
13074 #if defined(HAVE_PRI)
13075 if (tmp->channel == CHAN_PSEUDO) {
13076
13077
13078
13079
13080 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13081 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13082 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13083 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13084 }
13085 #endif
13086 }
13087 if (tmp && !here) {
13088
13089 dahdi_iflist_insert(tmp);
13090 }
13091 return tmp;
13092 }
13093
13094 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13095 {
13096 #if defined(HAVE_PRI)
13097 if (0 < span) {
13098
13099 if (!p->pri || p->pri->span != span) {
13100 return 0;
13101 }
13102 if (!groupmatch && channelmatch == -1) {
13103
13104 *groupmatched = 1;
13105 return 1;
13106 }
13107 }
13108 #endif
13109
13110 if (groupmatch) {
13111 if ((p->group & groupmatch) != groupmatch)
13112
13113 return 0;
13114 *groupmatched = 1;
13115 }
13116
13117 if (channelmatch != -1) {
13118 if (p->channel != channelmatch)
13119
13120 return 0;
13121 *channelmatched = 1;
13122 }
13123
13124 return 1;
13125 }
13126
13127 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13128 {
13129 struct dahdi_pvt *p = *pvt;
13130
13131 if (p->inalarm)
13132 return 0;
13133
13134 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13135 return analog_available(p->sig_pvt);
13136
13137 switch (p->sig) {
13138 #if defined(HAVE_PRI)
13139 case SIG_PRI_LIB_HANDLE_CASES:
13140 {
13141 struct sig_pri_chan *pvt_chan;
13142 int res;
13143
13144 pvt_chan = p->sig_pvt;
13145 res = sig_pri_available(&pvt_chan, is_specific_channel);
13146 *pvt = pvt_chan->chan_pvt;
13147 return res;
13148 }
13149 #endif
13150 #if defined(HAVE_SS7)
13151 case SIG_SS7:
13152 return sig_ss7_available(p->sig_pvt);
13153 #endif
13154 default:
13155 break;
13156 }
13157
13158 if (p->locallyblocked || p->remotelyblocked) {
13159 return 0;
13160 }
13161
13162
13163 if (!p->owner) {
13164 #ifdef HAVE_OPENR2
13165
13166 if (p->mfcr2) {
13167 if (p->mfcr2call) {
13168 return 0;
13169 } else {
13170 return 1;
13171 }
13172 }
13173 #endif
13174 return 1;
13175 }
13176
13177 return 0;
13178 }
13179
13180 #if defined(HAVE_PRI)
13181 #if defined(HAVE_PRI_CALL_WAITING)
13182
13183
13184
13185
13186
13187
13188
13189
13190
13191
13192
13193
13194 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13195 {
13196 struct dahdi_pvt *pvt = priv;
13197
13198 pvt->stripmsd = pri->ch_cfg.stripmsd;
13199 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13200 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13201 pvt->immediate = pri->ch_cfg.immediate;
13202 pvt->priexclusive = pri->ch_cfg.priexclusive;
13203 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13204 pvt->use_callerid = pri->ch_cfg.use_callerid;
13205 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13206 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13207 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13208 }
13209 #endif
13210 #endif
13211
13212 #if defined(HAVE_PRI)
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13226 {
13227 int pvt_idx;
13228 int res;
13229 unsigned idx;
13230 struct dahdi_pvt *pvt;
13231 struct sig_pri_chan *chan;
13232 struct dahdi_bufferinfo bi;
13233
13234 static int nobch_channel = CHAN_PSEUDO;
13235
13236
13237 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13238 if (!pri->pvts[pvt_idx]) {
13239 break;
13240 }
13241 }
13242 if (pri->numchans == pvt_idx) {
13243 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13244 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13245 return -1;
13246 }
13247
13248
13249 pri->pvts[pvt_idx] = NULL;
13250 ++pri->numchans;
13251 }
13252
13253 pvt = ast_calloc(1, sizeof(*pvt));
13254 if (!pvt) {
13255 return -1;
13256 }
13257 pvt->cc_params = ast_cc_config_params_init();
13258 if (!pvt->cc_params) {
13259 ast_free(pvt);
13260 return -1;
13261 }
13262 ast_mutex_init(&pvt->lock);
13263 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13264 pvt->subs[idx].dfd = -1;
13265 }
13266 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13267 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13268 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13269 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13270
13271 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13272 if (!chan) {
13273 destroy_dahdi_pvt(pvt);
13274 return -1;
13275 }
13276 chan->no_b_channel = 1;
13277
13278
13279
13280
13281
13282
13283 pvt->law_default = DAHDI_LAW_ALAW;
13284
13285 pvt->sig = pri->sig;
13286 pvt->outsigmod = -1;
13287 pvt->pri = pri;
13288 pvt->sig_pvt = chan;
13289 pri->pvts[pvt_idx] = chan;
13290
13291 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13292 if (pvt->subs[SUB_REAL].dfd < 0) {
13293 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13294 strerror(errno));
13295 destroy_dahdi_pvt(pvt);
13296 return -1;
13297 }
13298 memset(&bi, 0, sizeof(bi));
13299 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13300 if (!res) {
13301 pvt->bufsize = bi.bufsize;
13302 bi.txbufpolicy = pvt->buf_policy;
13303 bi.rxbufpolicy = pvt->buf_policy;
13304 bi.numbufs = pvt->buf_no;
13305 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13306 if (res < 0) {
13307 ast_log(LOG_WARNING,
13308 "Unable to set buffer policy on no B channel interface: %s\n",
13309 strerror(errno));
13310 }
13311 } else
13312 ast_log(LOG_WARNING,
13313 "Unable to check buffer policy on no B channel interface: %s\n",
13314 strerror(errno));
13315
13316 --nobch_channel;
13317 if (CHAN_PSEUDO < nobch_channel) {
13318 nobch_channel = CHAN_PSEUDO - 1;
13319 }
13320 pvt->channel = nobch_channel;
13321 pvt->span = pri->span;
13322 chan->channel = pvt->channel;
13323
13324 dahdi_nobch_insert(pri, pvt);
13325
13326 return pvt_idx;
13327 }
13328 #endif
13329
13330
13331
13332
13333
13334
13335 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13336 {
13337 struct dahdi_pvt *p;
13338 struct dahdi_bufferinfo bi;
13339 int res;
13340
13341 p = ast_malloc(sizeof(*p));
13342 if (!p) {
13343 return NULL;
13344 }
13345 *p = *src;
13346
13347
13348 p->cc_params = ast_cc_config_params_init();
13349 if (!p->cc_params) {
13350 ast_free(p);
13351 return NULL;
13352 }
13353 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13354
13355 p->which_iflist = DAHDI_IFLIST_NONE;
13356 p->next = NULL;
13357 p->prev = NULL;
13358 ast_mutex_init(&p->lock);
13359 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13360 if (p->subs[SUB_REAL].dfd < 0) {
13361 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13362 destroy_dahdi_pvt(p);
13363 return NULL;
13364 }
13365 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13366 if (!res) {
13367 bi.txbufpolicy = src->buf_policy;
13368 bi.rxbufpolicy = src->buf_policy;
13369 bi.numbufs = src->buf_no;
13370 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13371 if (res < 0) {
13372 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13373 }
13374 } else
13375 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13376 p->destroy = 1;
13377 dahdi_iflist_insert(p);
13378 return p;
13379 }
13380
13381 struct dahdi_starting_point {
13382
13383 ast_group_t groupmatch;
13384
13385 int channelmatch;
13386
13387 int rr_starting_point;
13388
13389 int span;
13390
13391 int cadance;
13392
13393 char opt;
13394
13395 char backwards;
13396
13397 char roundrobin;
13398 };
13399 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13400 {
13401 char *dest;
13402 char *s;
13403 int x;
13404 int res = 0;
13405 struct dahdi_pvt *p;
13406 char *subdir = NULL;
13407 AST_DECLARE_APP_ARGS(args,
13408 AST_APP_ARG(group);
13409
13410
13411 AST_APP_ARG(other);
13412 );
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435
13436
13437 if (data) {
13438 dest = ast_strdupa(data);
13439 } else {
13440 ast_log(LOG_WARNING, "Channel requested with no data\n");
13441 return NULL;
13442 }
13443 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13444 if (!args.argc || ast_strlen_zero(args.group)) {
13445 ast_log(LOG_WARNING, "No channel/group specified\n");
13446 return NULL;
13447 }
13448
13449
13450 memset(param, 0, sizeof(*param));
13451 param->channelmatch = -1;
13452
13453 if (strchr(args.group, '!') != NULL) {
13454 char *prev = args.group;
13455 while ((s = strchr(prev, '!')) != NULL) {
13456 *s++ = '/';
13457 prev = s;
13458 }
13459 *(prev - 1) = '\0';
13460 subdir = args.group;
13461 args.group = prev;
13462 } else if (args.group[0] == 'i') {
13463
13464 res = sscanf(args.group + 1, "%30d", &x);
13465 if (res < 1) {
13466 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13467 return NULL;
13468 }
13469 param->span = x;
13470
13471
13472 s = strchr(args.group, '-');
13473 if (!s) {
13474
13475 return iflist;
13476 }
13477 args.group = s + 1;
13478 res = 0;
13479 }
13480 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13481
13482 s = args.group + 1;
13483 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13484 if (res < 1) {
13485 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13486 return NULL;
13487 }
13488 param->groupmatch = ((ast_group_t) 1 << x);
13489
13490 if (toupper(args.group[0]) == 'G') {
13491 if (args.group[0] == 'G') {
13492 param->backwards = 1;
13493 p = ifend;
13494 } else
13495 p = iflist;
13496 } else {
13497 if (ARRAY_LEN(round_robin) <= x) {
13498 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13499 x, data);
13500 return NULL;
13501 }
13502 if (args.group[0] == 'R') {
13503 param->backwards = 1;
13504 p = round_robin[x] ? round_robin[x]->prev : ifend;
13505 if (!p)
13506 p = ifend;
13507 } else {
13508 p = round_robin[x] ? round_robin[x]->next : iflist;
13509 if (!p)
13510 p = iflist;
13511 }
13512 param->roundrobin = 1;
13513 param->rr_starting_point = x;
13514 }
13515 } else {
13516 s = args.group;
13517 if (!strcasecmp(s, "pseudo")) {
13518
13519 x = CHAN_PSEUDO;
13520 param->channelmatch = x;
13521 } else {
13522 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13523 if (res < 1) {
13524 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13525 return NULL;
13526 } else {
13527 param->channelmatch = x;
13528 }
13529 }
13530 if (subdir) {
13531 char path[PATH_MAX];
13532 struct stat stbuf;
13533
13534 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13535 subdir, param->channelmatch);
13536 if (stat(path, &stbuf) < 0) {
13537 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13538 path, strerror(errno));
13539 return NULL;
13540 }
13541 if (!S_ISCHR(stbuf.st_mode)) {
13542 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13543 path);
13544 return NULL;
13545 }
13546 param->channelmatch = minor(stbuf.st_rdev);
13547 }
13548
13549 p = iflist;
13550 }
13551
13552 if (param->opt == 'r' && res < 3) {
13553 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13554 param->opt = '\0';
13555 }
13556
13557 return p;
13558 }
13559
13560 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13561 {
13562 int callwait = 0;
13563 struct dahdi_pvt *p;
13564 struct ast_channel *tmp = NULL;
13565 struct dahdi_pvt *exitpvt;
13566 int channelmatched = 0;
13567 int groupmatched = 0;
13568 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13569 int transcapdigital = 0;
13570 #endif
13571 struct dahdi_starting_point start;
13572
13573 ast_mutex_lock(&iflock);
13574 p = determine_starting_point(data, &start);
13575 if (!p) {
13576
13577 ast_mutex_unlock(&iflock);
13578 return NULL;
13579 }
13580
13581
13582 exitpvt = p;
13583 while (p && !tmp) {
13584 if (start.roundrobin)
13585 round_robin[start.rr_starting_point] = p;
13586
13587 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13588 && available(&p, channelmatched)) {
13589 ast_debug(1, "Using channel %d\n", p->channel);
13590
13591 callwait = (p->owner != NULL);
13592 #ifdef HAVE_OPENR2
13593 if (p->mfcr2) {
13594 ast_mutex_lock(&p->lock);
13595 if (p->mfcr2call) {
13596 ast_mutex_unlock(&p->lock);
13597 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13598 goto next;
13599 }
13600 p->mfcr2call = 1;
13601 ast_mutex_unlock(&p->lock);
13602 }
13603 #endif
13604 if (p->channel == CHAN_PSEUDO) {
13605 p = duplicate_pseudo(p);
13606 if (!p) {
13607 break;
13608 }
13609 }
13610
13611 p->distinctivering = 0;
13612
13613 switch (start.opt) {
13614 case '\0':
13615
13616 break;
13617 case 'c':
13618
13619 p->confirmanswer = 1;
13620 break;
13621 case 'r':
13622
13623 p->distinctivering = start.cadance;
13624 break;
13625 case 'd':
13626 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13627
13628 transcapdigital = AST_TRANS_CAP_DIGITAL;
13629 #endif
13630 break;
13631 default:
13632 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13633 break;
13634 }
13635
13636 p->outgoing = 1;
13637 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13638 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13639 #ifdef HAVE_PRI
13640 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13641
13642
13643
13644
13645
13646 ast_mutex_lock(&p->lock);
13647 ast_mutex_unlock(&p->lock);
13648
13649 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13650 sizeof(p->dnid));
13651 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13652 #endif
13653 #if defined(HAVE_SS7)
13654 } else if (p->sig == SIG_SS7) {
13655 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13656 #endif
13657 } else {
13658 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13659 }
13660 if (!tmp) {
13661 p->outgoing = 0;
13662 #if defined(HAVE_PRI)
13663 switch (p->sig) {
13664 case SIG_PRI_LIB_HANDLE_CASES:
13665 #if defined(HAVE_PRI_CALL_WAITING)
13666 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13667 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13668 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13669 }
13670 #endif
13671
13672
13673
13674
13675 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13676 break;
13677 default:
13678 break;
13679 }
13680 #endif
13681 } else {
13682 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13683 }
13684 break;
13685 }
13686 #ifdef HAVE_OPENR2
13687 next:
13688 #endif
13689 if (start.backwards) {
13690 p = p->prev;
13691 if (!p)
13692 p = ifend;
13693 } else {
13694 p = p->next;
13695 if (!p)
13696 p = iflist;
13697 }
13698
13699 if (p == exitpvt)
13700 break;
13701 }
13702 ast_mutex_unlock(&iflock);
13703 restart_monitor();
13704 if (cause && !tmp) {
13705 if (callwait || channelmatched) {
13706 *cause = AST_CAUSE_BUSY;
13707 } else if (groupmatched) {
13708 *cause = AST_CAUSE_CONGESTION;
13709 } else {
13710
13711
13712
13713
13714 }
13715 }
13716
13717 return tmp;
13718 }
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730 static int dahdi_devicestate(void *data)
13731 {
13732 #if defined(HAVE_PRI)
13733 char *device;
13734 unsigned span;
13735 int res;
13736
13737 device = data;
13738
13739 if (*device != 'I') {
13740
13741 return AST_DEVICE_UNKNOWN;
13742 }
13743 res = sscanf(device, "I%30u", &span);
13744 if (res != 1 || !span || NUM_SPANS < span) {
13745
13746 return AST_DEVICE_UNKNOWN;
13747 }
13748 device = strchr(device, '/');
13749 if (!device) {
13750
13751 return AST_DEVICE_UNKNOWN;
13752 }
13753
13754
13755
13756
13757
13758 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13759 ++device;
13760 if (!strcmp(device, "congestion"))
13761 #endif
13762 {
13763 return pris[span - 1].pri.congestion_devstate;
13764 }
13765 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13766 else if (!strcmp(device, "threshold")) {
13767 return pris[span - 1].pri.threshold_devstate;
13768 }
13769 return AST_DEVICE_UNKNOWN;
13770 #endif
13771 #else
13772 return AST_DEVICE_UNKNOWN;
13773 #endif
13774 }
13775
13776
13777
13778
13779
13780
13781
13782
13783
13784
13785
13786
13787
13788
13789
13790
13791
13792 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13793 {
13794 struct dahdi_pvt *p;
13795 struct dahdi_pvt *exitpvt;
13796 struct dahdi_starting_point start;
13797 int groupmatched = 0;
13798 int channelmatched = 0;
13799
13800 ast_mutex_lock(&iflock);
13801 p = determine_starting_point(dest, &start);
13802 if (!p) {
13803 ast_mutex_unlock(&iflock);
13804 return -1;
13805 }
13806 exitpvt = p;
13807 for (;;) {
13808 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13809
13810 struct ast_str *device_name;
13811 char *dash;
13812 const char *monitor_type;
13813 char dialstring[AST_CHANNEL_NAME];
13814 char full_device_name[AST_CHANNEL_NAME];
13815
13816 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13817 case AST_CC_MONITOR_NEVER:
13818 break;
13819 case AST_CC_MONITOR_NATIVE:
13820 case AST_CC_MONITOR_ALWAYS:
13821 case AST_CC_MONITOR_GENERIC:
13822 #if defined(HAVE_PRI)
13823 if (dahdi_sig_pri_lib_handles(p->sig)) {
13824
13825
13826
13827
13828 snprintf(full_device_name, sizeof(full_device_name),
13829 "DAHDI/I%d/congestion", p->pri->span);
13830 } else
13831 #endif
13832 {
13833 #if defined(HAVE_PRI)
13834 device_name = create_channel_name(p, 1, "");
13835 #else
13836 device_name = create_channel_name(p);
13837 #endif
13838 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13839 device_name ? ast_str_buffer(device_name) : "");
13840 ast_free(device_name);
13841
13842
13843
13844
13845
13846 dash = strrchr(full_device_name, '-');
13847 if (dash) {
13848 *dash = '\0';
13849 }
13850 }
13851 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13852
13853
13854
13855
13856
13857
13858
13859 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13860 callback(inbound,
13861 #if defined(HAVE_PRI)
13862 p->pri ? p->pri->cc_params : p->cc_params,
13863 #else
13864 p->cc_params,
13865 #endif
13866 monitor_type, full_device_name, dialstring, NULL);
13867 break;
13868 }
13869 }
13870 p = start.backwards ? p->prev : p->next;
13871 if (!p) {
13872 p = start.backwards ? ifend : iflist;
13873 }
13874 if (p == exitpvt) {
13875 break;
13876 }
13877 }
13878 ast_mutex_unlock(&iflock);
13879 return 0;
13880 }
13881
13882 #if defined(HAVE_SS7)
13883 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13884 {
13885 int i;
13886
13887 if (ss7) {
13888 for (i = 0; i < NUM_SPANS; i++) {
13889 if (linksets[i].ss7.ss7 == ss7) {
13890 ast_verbose("[%d] %s", i + 1, s);
13891 return;
13892 }
13893 }
13894 }
13895 ast_verbose("%s", s);
13896 }
13897 #endif
13898
13899 #if defined(HAVE_SS7)
13900 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13901 {
13902 int i;
13903
13904 if (ss7) {
13905 for (i = 0; i < NUM_SPANS; i++) {
13906 if (linksets[i].ss7.ss7 == ss7) {
13907 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13908 return;
13909 }
13910 }
13911 }
13912 ast_log(LOG_ERROR, "%s", s);
13913 }
13914 #endif
13915
13916 #if defined(HAVE_OPENR2)
13917 static void *mfcr2_monitor(void *data)
13918 {
13919 struct dahdi_mfcr2 *mfcr2 = data;
13920
13921
13922
13923
13924
13925 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13926 int res = 0;
13927 int i = 0;
13928 int oldstate = 0;
13929 int quit_loop = 0;
13930 int maxsleep = 20;
13931 int was_idle = 0;
13932 int pollsize = 0;
13933
13934
13935 for (i = 0; i < mfcr2->numchans; i++) {
13936 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13937 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13938 }
13939 while (1) {
13940
13941
13942 pollsize = 0;
13943 for (i = 0; i < mfcr2->numchans; i++) {
13944 pollers[i].revents = 0;
13945 pollers[i].events = 0;
13946 if (mfcr2->pvts[i]->owner) {
13947 continue;
13948 }
13949 if (!mfcr2->pvts[i]->r2chan) {
13950 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13951 quit_loop = 1;
13952 break;
13953 }
13954 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13955 pollers[i].events = POLLIN | POLLPRI;
13956 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13957 pollsize++;
13958 }
13959 if (quit_loop) {
13960 break;
13961 }
13962 if (pollsize == 0) {
13963 if (!was_idle) {
13964 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13965 was_idle = 1;
13966 }
13967 poll(NULL, 0, maxsleep);
13968 continue;
13969 }
13970 was_idle = 0;
13971
13972
13973 pthread_testcancel();
13974 res = poll(pollers, mfcr2->numchans, maxsleep);
13975 pthread_testcancel();
13976 if ((res < 0) && (errno != EINTR)) {
13977 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13978 break;
13979 }
13980
13981 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13982 for (i = 0; i < mfcr2->numchans; i++) {
13983 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13984 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13985 }
13986 }
13987 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13988 }
13989 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13990 return 0;
13991 }
13992 #endif
13993
13994 #if defined(HAVE_PRI)
13995 #ifndef PRI_RESTART
13996 #error "Upgrade your libpri"
13997 #endif
13998 static void dahdi_pri_message(struct pri *pri, char *s)
13999 {
14000 int x;
14001 int y;
14002 int dchan = -1;
14003 int span = -1;
14004 int dchancount = 0;
14005
14006 if (pri) {
14007 for (x = 0; x < NUM_SPANS; x++) {
14008 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14009 if (pris[x].pri.dchans[y]) {
14010 dchancount++;
14011 }
14012
14013 if (pris[x].pri.dchans[y] == pri) {
14014 dchan = y;
14015 }
14016 }
14017 if (dchan >= 0) {
14018 span = x;
14019 break;
14020 }
14021 dchancount = 0;
14022 }
14023 if (-1 < span) {
14024 if (1 < dchancount) {
14025 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14026 } else {
14027 ast_verbose("PRI Span: %d %s", span + 1, s);
14028 }
14029 } else {
14030 ast_verbose("PRI Span: ? %s", s);
14031 }
14032 } else {
14033 ast_verbose("PRI Span: ? %s", s);
14034 }
14035
14036 ast_mutex_lock(&pridebugfdlock);
14037
14038 if (pridebugfd >= 0) {
14039 if (write(pridebugfd, s, strlen(s)) < 0) {
14040 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14041 }
14042 }
14043
14044 ast_mutex_unlock(&pridebugfdlock);
14045 }
14046 #endif
14047
14048 #if defined(HAVE_PRI)
14049 static void dahdi_pri_error(struct pri *pri, char *s)
14050 {
14051 int x;
14052 int y;
14053 int dchan = -1;
14054 int span = -1;
14055 int dchancount = 0;
14056
14057 if (pri) {
14058 for (x = 0; x < NUM_SPANS; x++) {
14059 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14060 if (pris[x].pri.dchans[y]) {
14061 dchancount++;
14062 }
14063
14064 if (pris[x].pri.dchans[y] == pri) {
14065 dchan = y;
14066 }
14067 }
14068 if (dchan >= 0) {
14069 span = x;
14070 break;
14071 }
14072 dchancount = 0;
14073 }
14074 if (-1 < span) {
14075 if (1 < dchancount) {
14076 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14077 } else {
14078 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14079 }
14080 } else {
14081 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14082 }
14083 } else {
14084 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14085 }
14086
14087 ast_mutex_lock(&pridebugfdlock);
14088
14089 if (pridebugfd >= 0) {
14090 if (write(pridebugfd, s, strlen(s)) < 0) {
14091 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14092 }
14093 }
14094
14095 ast_mutex_unlock(&pridebugfdlock);
14096 }
14097 #endif
14098
14099 #if defined(HAVE_PRI)
14100 static int prepare_pri(struct dahdi_pri *pri)
14101 {
14102 int i, res, x;
14103 struct dahdi_params p;
14104 struct dahdi_bufferinfo bi;
14105 struct dahdi_spaninfo si;
14106
14107 pri->pri.calls = &dahdi_pri_callbacks;
14108
14109 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14110 if (!pri->dchannels[i])
14111 break;
14112 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14113 x = pri->dchannels[i];
14114 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14115 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14116 return -1;
14117 }
14118 memset(&p, 0, sizeof(p));
14119 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14120 if (res) {
14121 dahdi_close_pri_fd(pri, i);
14122 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14123 return -1;
14124 }
14125 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14126 dahdi_close_pri_fd(pri, i);
14127 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14128 return -1;
14129 }
14130 memset(&si, 0, sizeof(si));
14131 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14132 if (res) {
14133 dahdi_close_pri_fd(pri, i);
14134 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14135 }
14136 if (!si.alarms) {
14137 pri_event_noalarm(&pri->pri, i, 1);
14138 } else {
14139 pri_event_alarm(&pri->pri, i, 1);
14140 }
14141 memset(&bi, 0, sizeof(bi));
14142 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14143 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14144 bi.numbufs = 32;
14145 bi.bufsize = 1024;
14146 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14147 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14148 dahdi_close_pri_fd(pri, i);
14149 return -1;
14150 }
14151 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14152 }
14153 return 0;
14154 }
14155 #endif
14156
14157 #if defined(HAVE_PRI)
14158 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14159 {
14160 int which, span;
14161 char *ret = NULL;
14162
14163 if (pos != rpos)
14164 return ret;
14165
14166 for (which = span = 0; span < NUM_SPANS; span++) {
14167 if (pris[span].pri.pri && ++which > state) {
14168 if (asprintf(&ret, "%d", span + 1) < 0) {
14169 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14170 }
14171 break;
14172 }
14173 }
14174 return ret;
14175 }
14176 #endif
14177
14178 #if defined(HAVE_PRI)
14179 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14180 {
14181 return complete_span_helper(line,word,pos,state,3);
14182 }
14183 #endif
14184
14185 #if defined(HAVE_PRI)
14186 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14187 {
14188 int myfd;
14189 switch (cmd) {
14190 case CLI_INIT:
14191 e->command = "pri set debug file";
14192 e->usage = "Usage: pri set debug file [output-file]\n"
14193 " Sends PRI debug output to the specified output file\n";
14194 return NULL;
14195 case CLI_GENERATE:
14196 return NULL;
14197 }
14198 if (a->argc < 5)
14199 return CLI_SHOWUSAGE;
14200
14201 if (ast_strlen_zero(a->argv[4]))
14202 return CLI_SHOWUSAGE;
14203
14204 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14205 if (myfd < 0) {
14206 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14207 return CLI_SUCCESS;
14208 }
14209
14210 ast_mutex_lock(&pridebugfdlock);
14211
14212 if (pridebugfd >= 0)
14213 close(pridebugfd);
14214
14215 pridebugfd = myfd;
14216 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14217 ast_mutex_unlock(&pridebugfdlock);
14218 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14219 return CLI_SUCCESS;
14220 }
14221 #endif
14222
14223 #if defined(HAVE_PRI)
14224 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14225 {
14226 int span;
14227 int x;
14228 int level = 0;
14229 switch (cmd) {
14230 case CLI_INIT:
14231 e->command = "pri set debug {on|off|0|1|2} span";
14232 e->usage =
14233 "Usage: pri set debug {<level>|on|off} span <span>\n"
14234 " Enables debugging on a given PRI span\n";
14235 return NULL;
14236 case CLI_GENERATE:
14237 return complete_span_4(a->line, a->word, a->pos, a->n);
14238 }
14239 if (a->argc < 6) {
14240 return CLI_SHOWUSAGE;
14241 }
14242
14243 if (!strcasecmp(a->argv[3], "on")) {
14244 level = 1;
14245 } else if (!strcasecmp(a->argv[3], "off")) {
14246 level = 0;
14247 } else {
14248 level = atoi(a->argv[3]);
14249 }
14250 span = atoi(a->argv[5]);
14251 if ((span < 1) || (span > NUM_SPANS)) {
14252 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14253 return CLI_SUCCESS;
14254 }
14255 if (!pris[span-1].pri.pri) {
14256 ast_cli(a->fd, "No PRI running on span %d\n", span);
14257 return CLI_SUCCESS;
14258 }
14259
14260
14261 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14262 if (pris[span - 1].pri.dchans[x]) {
14263 switch (level) {
14264 case 0:
14265 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14266 break;
14267 case 1:
14268 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14269 break;
14270 default:
14271 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14272 break;
14273 }
14274 }
14275 }
14276 if (level == 0) {
14277
14278 ast_mutex_lock(&pridebugfdlock);
14279 if (0 <= pridebugfd) {
14280 close(pridebugfd);
14281 pridebugfd = -1;
14282 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14283 pridebugfilename);
14284 }
14285 ast_mutex_unlock(&pridebugfdlock);
14286 }
14287 pris[span - 1].pri.debug = (level) ? 1 : 0;
14288 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14289 return CLI_SUCCESS;
14290 }
14291 #endif
14292
14293 #if defined(HAVE_PRI)
14294 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14295 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14296 {
14297 unsigned *why;
14298 int channel;
14299 int trunkgroup;
14300 int x, y, fd = a->fd;
14301 int interfaceid = 0;
14302 char *c;
14303 char db_chan_name[20], db_answer[5];
14304 struct dahdi_pvt *tmp;
14305 struct dahdi_pri *pri;
14306
14307 if (a->argc < 5 || a->argc > 6)
14308 return CLI_SHOWUSAGE;
14309 if ((c = strchr(a->argv[4], ':'))) {
14310 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14311 return CLI_SHOWUSAGE;
14312 if ((trunkgroup < 1) || (channel < 1))
14313 return CLI_SHOWUSAGE;
14314 pri = NULL;
14315 for (x=0;x<NUM_SPANS;x++) {
14316 if (pris[x].pri.trunkgroup == trunkgroup) {
14317 pri = pris + x;
14318 break;
14319 }
14320 }
14321 if (!pri) {
14322 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14323 return CLI_FAILURE;
14324 }
14325 } else
14326 channel = atoi(a->argv[4]);
14327
14328 if (a->argc == 6)
14329 interfaceid = atoi(a->argv[5]);
14330
14331
14332 for (x = 0; x < NUM_SPANS; x++) {
14333 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14334 if (pris[x].dchannels[y] == channel) {
14335 pri = pris + x;
14336 if (pri->pri.enable_service_message_support) {
14337 ast_mutex_lock(&pri->pri.lock);
14338 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14339 ast_mutex_unlock(&pri->pri.lock);
14340 } else {
14341 ast_cli(fd,
14342 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14343 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14344 }
14345 return CLI_SUCCESS;
14346 }
14347 }
14348 }
14349
14350
14351 ast_mutex_lock(&iflock);
14352 for (tmp = iflist; tmp; tmp = tmp->next) {
14353 if (tmp->pri && tmp->channel == channel) {
14354 ast_mutex_unlock(&iflock);
14355 ast_mutex_lock(&tmp->pri->lock);
14356 if (!tmp->pri->enable_service_message_support) {
14357 ast_mutex_unlock(&tmp->pri->lock);
14358 ast_cli(fd,
14359 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14360 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14361 return CLI_SUCCESS;
14362 }
14363 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14364 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14365 switch(changestatus) {
14366 case 0:
14367
14368 ast_db_del(db_chan_name, SRVST_DBKEY);
14369 *why &= ~SRVST_NEAREND;
14370 if (*why) {
14371 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14372 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14373 } else {
14374 dahdi_pri_update_span_devstate(tmp->pri);
14375 }
14376 break;
14377
14378 case 2:
14379
14380 ast_db_del(db_chan_name, SRVST_DBKEY);
14381 *why |= SRVST_NEAREND;
14382 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14383 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14384 dahdi_pri_update_span_devstate(tmp->pri);
14385 break;
14386
14387
14388 default:
14389 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14390 break;
14391 }
14392 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14393 ast_mutex_unlock(&tmp->pri->lock);
14394 return CLI_SUCCESS;
14395 }
14396 }
14397 ast_mutex_unlock(&iflock);
14398
14399 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14400 return CLI_FAILURE;
14401 }
14402
14403 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14404 {
14405 switch (cmd) {
14406 case CLI_INIT:
14407 e->command = "pri service enable channel";
14408 e->usage =
14409 "Usage: pri service enable channel <channel> [<interface id>]\n"
14410 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14411 " to restore a channel to service, with optional interface id\n"
14412 " as agreed upon with remote switch operator\n";
14413 return NULL;
14414 case CLI_GENERATE:
14415 return NULL;
14416 }
14417 return handle_pri_service_generic(e, cmd, a, 0);
14418 }
14419
14420 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14421 {
14422 switch (cmd) {
14423 case CLI_INIT:
14424 e->command = "pri service disable channel";
14425 e->usage =
14426 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14427 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14428 " to remove a channel from service, with optional interface id\n"
14429 " as agreed upon with remote switch operator\n";
14430 return NULL;
14431 case CLI_GENERATE:
14432 return NULL;
14433 }
14434 return handle_pri_service_generic(e, cmd, a, 2);
14435 }
14436 #endif
14437 #endif
14438
14439 #if defined(HAVE_PRI)
14440 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14441 {
14442 int span;
14443
14444 switch (cmd) {
14445 case CLI_INIT:
14446 e->command = "pri show channels";
14447 e->usage =
14448 "Usage: pri show channels\n"
14449 " Displays PRI channel information such as the current mapping\n"
14450 " of DAHDI B channels to Asterisk channel names and which calls\n"
14451 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14452 " are not associated with any B channel.\n";
14453 return NULL;
14454 case CLI_GENERATE:
14455 return NULL;
14456 }
14457
14458 if (a->argc != 3)
14459 return CLI_SHOWUSAGE;
14460
14461 sig_pri_cli_show_channels_header(a->fd);
14462 for (span = 0; span < NUM_SPANS; ++span) {
14463 if (pris[span].pri.pri) {
14464 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14465 }
14466 }
14467 return CLI_SUCCESS;
14468 }
14469 #endif
14470
14471 #if defined(HAVE_PRI)
14472 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14473 {
14474 int span;
14475
14476 switch (cmd) {
14477 case CLI_INIT:
14478 e->command = "pri show spans";
14479 e->usage =
14480 "Usage: pri show spans\n"
14481 " Displays PRI span information\n";
14482 return NULL;
14483 case CLI_GENERATE:
14484 return NULL;
14485 }
14486
14487 if (a->argc != 3)
14488 return CLI_SHOWUSAGE;
14489
14490 for (span = 0; span < NUM_SPANS; span++) {
14491 if (pris[span].pri.pri) {
14492 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14493 }
14494 }
14495 return CLI_SUCCESS;
14496 }
14497 #endif
14498
14499 #if defined(HAVE_PRI)
14500 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14501 {
14502 int span;
14503
14504 switch (cmd) {
14505 case CLI_INIT:
14506 e->command = "pri show span";
14507 e->usage =
14508 "Usage: pri show span <span>\n"
14509 " Displays PRI Information on a given PRI span\n";
14510 return NULL;
14511 case CLI_GENERATE:
14512 return complete_span_4(a->line, a->word, a->pos, a->n);
14513 }
14514
14515 if (a->argc < 4)
14516 return CLI_SHOWUSAGE;
14517 span = atoi(a->argv[3]);
14518 if ((span < 1) || (span > NUM_SPANS)) {
14519 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14520 return CLI_SUCCESS;
14521 }
14522 if (!pris[span-1].pri.pri) {
14523 ast_cli(a->fd, "No PRI running on span %d\n", span);
14524 return CLI_SUCCESS;
14525 }
14526
14527 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14528
14529 return CLI_SUCCESS;
14530 }
14531 #endif
14532
14533 #if defined(HAVE_PRI)
14534 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14535 {
14536 int x;
14537 int span;
14538 int count=0;
14539 int debug;
14540
14541 switch (cmd) {
14542 case CLI_INIT:
14543 e->command = "pri show debug";
14544 e->usage =
14545 "Usage: pri show debug\n"
14546 " Show the debug state of pri spans\n";
14547 return NULL;
14548 case CLI_GENERATE:
14549 return NULL;
14550 }
14551
14552 for (span = 0; span < NUM_SPANS; span++) {
14553 if (pris[span].pri.pri) {
14554 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14555 if (pris[span].pri.dchans[x]) {
14556 debug = pri_get_debug(pris[span].pri.dchans[x]);
14557 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" );
14558 count++;
14559 }
14560 }
14561 }
14562
14563 }
14564 ast_mutex_lock(&pridebugfdlock);
14565 if (pridebugfd >= 0)
14566 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14567 ast_mutex_unlock(&pridebugfdlock);
14568
14569 if (!count)
14570 ast_cli(a->fd, "No PRI running\n");
14571 return CLI_SUCCESS;
14572 }
14573 #endif
14574
14575 #if defined(HAVE_PRI)
14576 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14577 {
14578 switch (cmd) {
14579 case CLI_INIT:
14580 e->command = "pri show version";
14581 e->usage =
14582 "Usage: pri show version\n"
14583 "Show libpri version information\n";
14584 return NULL;
14585 case CLI_GENERATE:
14586 return NULL;
14587 }
14588
14589 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14590
14591 return CLI_SUCCESS;
14592 }
14593 #endif
14594
14595 #if defined(HAVE_PRI)
14596 static struct ast_cli_entry dahdi_pri_cli[] = {
14597 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14598 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14599 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14600 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14601 #endif
14602 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14603 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14604 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14605 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14606 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14607 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14608 };
14609 #endif
14610
14611 #ifdef HAVE_OPENR2
14612
14613 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14614 {
14615 switch (cmd) {
14616 case CLI_INIT:
14617 e->command = "mfcr2 show version";
14618 e->usage =
14619 "Usage: mfcr2 show version\n"
14620 " Shows the version of the OpenR2 library being used.\n";
14621 return NULL;
14622 case CLI_GENERATE:
14623 return NULL;
14624 }
14625 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14626 return CLI_SUCCESS;
14627 }
14628
14629 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14630 {
14631 #define FORMAT "%4s %40s\n"
14632 int i = 0;
14633 int numvariants = 0;
14634 const openr2_variant_entry_t *variants;
14635 switch (cmd) {
14636 case CLI_INIT:
14637 e->command = "mfcr2 show variants";
14638 e->usage =
14639 "Usage: mfcr2 show variants\n"
14640 " Shows the list of MFC/R2 variants supported.\n";
14641 return NULL;
14642 case CLI_GENERATE:
14643 return NULL;
14644 }
14645 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14646 ast_cli(a->fd, "Failed to get list of variants.\n");
14647 return CLI_FAILURE;
14648 }
14649 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14650 for (i = 0; i < numvariants; i++) {
14651 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14652 }
14653 return CLI_SUCCESS;
14654 #undef FORMAT
14655 }
14656
14657 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14658 {
14659 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14660 int filtertype = 0;
14661 int targetnum = 0;
14662 char channo[5];
14663 char anino[5];
14664 char dnisno[5];
14665 struct dahdi_pvt *p;
14666 openr2_context_t *r2context;
14667 openr2_variant_t r2variant;
14668 switch (cmd) {
14669 case CLI_INIT:
14670 e->command = "mfcr2 show channels [group|context]";
14671 e->usage =
14672 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14673 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14674 return NULL;
14675 case CLI_GENERATE:
14676 return NULL;
14677 }
14678 if (!((a->argc == 3) || (a->argc == 5))) {
14679 return CLI_SHOWUSAGE;
14680 }
14681 if (a->argc == 5) {
14682 if (!strcasecmp(a->argv[3], "group")) {
14683 targetnum = atoi(a->argv[4]);
14684 if ((targetnum < 0) || (targetnum > 63))
14685 return CLI_SHOWUSAGE;
14686 targetnum = 1 << targetnum;
14687 filtertype = 1;
14688 } else if (!strcasecmp(a->argv[3], "context")) {
14689 filtertype = 2;
14690 } else {
14691 return CLI_SHOWUSAGE;
14692 }
14693 }
14694 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14695 ast_mutex_lock(&iflock);
14696 for (p = iflist; p; p = p->next) {
14697 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14698 continue;
14699 }
14700 if (filtertype) {
14701 switch(filtertype) {
14702 case 1:
14703 if (p->group != targetnum) {
14704 continue;
14705 }
14706 break;
14707 case 2:
14708 if (strcasecmp(p->context, a->argv[4])) {
14709 continue;
14710 }
14711 break;
14712 default:
14713 ;
14714 }
14715 }
14716 r2context = openr2_chan_get_context(p->r2chan);
14717 r2variant = openr2_context_get_variant(r2context);
14718 snprintf(channo, sizeof(channo), "%d", p->channel);
14719 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14720 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14721 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14722 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14723 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14724 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14725 }
14726 ast_mutex_unlock(&iflock);
14727 return CLI_SUCCESS;
14728 #undef FORMAT
14729 }
14730
14731 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14732 {
14733 struct dahdi_pvt *p = NULL;
14734 int channo = 0;
14735 char *toklevel = NULL;
14736 char *saveptr = NULL;
14737 char *logval = NULL;
14738 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14739 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14740 switch (cmd) {
14741 case CLI_INIT:
14742 e->command = "mfcr2 set debug";
14743 e->usage =
14744 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14745 " Set a new logging level for the specified channel.\n"
14746 " If no channel is specified the logging level will be applied to all channels.\n";
14747 return NULL;
14748 case CLI_GENERATE:
14749 return NULL;
14750 }
14751 if (a->argc < 4) {
14752 return CLI_SHOWUSAGE;
14753 }
14754 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14755 logval = ast_strdupa(a->argv[3]);
14756 toklevel = strtok_r(logval, ",", &saveptr);
14757 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14758 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14759 return CLI_FAILURE;
14760 } else if (OR2_LOG_NOTHING == tmplevel) {
14761 loglevel = tmplevel;
14762 } else {
14763 loglevel |= tmplevel;
14764 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14765 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14766 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14767 continue;
14768 }
14769 loglevel |= tmplevel;
14770 }
14771 }
14772 ast_mutex_lock(&iflock);
14773 for (p = iflist; p; p = p->next) {
14774 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14775 continue;
14776 }
14777 if ((channo != -1) && (p->channel != channo )) {
14778 continue;
14779 }
14780 openr2_chan_set_log_level(p->r2chan, loglevel);
14781 if (channo != -1) {
14782 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14783 break;
14784 }
14785 }
14786 if ((channo != -1) && !p) {
14787 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14788 }
14789 if (channo == -1) {
14790 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14791 }
14792 ast_mutex_unlock(&iflock);
14793 return CLI_SUCCESS;
14794 }
14795
14796 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14797 {
14798 struct dahdi_pvt *p = NULL;
14799 int channo = 0;
14800 switch (cmd) {
14801 case CLI_INIT:
14802 e->command = "mfcr2 call files [on|off]";
14803 e->usage =
14804 "Usage: mfcr2 call files [on|off] <channel>\n"
14805 " Enable call files creation on the specified channel.\n"
14806 " If no channel is specified call files creation policy will be applied to all channels.\n";
14807 return NULL;
14808 case CLI_GENERATE:
14809 return NULL;
14810 }
14811 if (a->argc < 4) {
14812 return CLI_SHOWUSAGE;
14813 }
14814 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14815 ast_mutex_lock(&iflock);
14816 for (p = iflist; p; p = p->next) {
14817 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14818 continue;
14819 }
14820 if ((channo != -1) && (p->channel != channo )) {
14821 continue;
14822 }
14823 if (ast_true(a->argv[3])) {
14824 openr2_chan_enable_call_files(p->r2chan);
14825 } else {
14826 openr2_chan_disable_call_files(p->r2chan);
14827 }
14828 if (channo != -1) {
14829 if (ast_true(a->argv[3])) {
14830 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14831 } else {
14832 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14833 }
14834 break;
14835 }
14836 }
14837 if ((channo != -1) && !p) {
14838 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14839 }
14840 if (channo == -1) {
14841 if (ast_true(a->argv[3])) {
14842 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14843 } else {
14844 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14845 }
14846 }
14847 ast_mutex_unlock(&iflock);
14848 return CLI_SUCCESS;
14849 }
14850
14851 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14852 {
14853 struct dahdi_pvt *p = NULL;
14854 int channo = 0;
14855 switch (cmd) {
14856 case CLI_INIT:
14857 e->command = "mfcr2 set idle";
14858 e->usage =
14859 "Usage: mfcr2 set idle <channel>\n"
14860 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14861 " Force the given channel into IDLE state.\n"
14862 " If no channel is specified, all channels will be set to IDLE.\n";
14863 return NULL;
14864 case CLI_GENERATE:
14865 return NULL;
14866 }
14867 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14868 ast_mutex_lock(&iflock);
14869 for (p = iflist; p; p = p->next) {
14870 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14871 continue;
14872 }
14873 if ((channo != -1) && (p->channel != channo )) {
14874 continue;
14875 }
14876 openr2_chan_set_idle(p->r2chan);
14877 ast_mutex_lock(&p->lock);
14878 p->locallyblocked = 0;
14879 p->mfcr2call = 0;
14880 ast_mutex_unlock(&p->lock);
14881 if (channo != -1) {
14882 break;
14883 }
14884 }
14885 if ((channo != -1) && !p) {
14886 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14887 }
14888 ast_mutex_unlock(&iflock);
14889 return CLI_SUCCESS;
14890 }
14891
14892 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14893 {
14894 struct dahdi_pvt *p = NULL;
14895 int channo = 0;
14896 switch (cmd) {
14897 case CLI_INIT:
14898 e->command = "mfcr2 set blocked";
14899 e->usage =
14900 "Usage: mfcr2 set blocked <channel>\n"
14901 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14902 " Force the given channel into BLOCKED state.\n"
14903 " If no channel is specified, all channels will be set to BLOCKED.\n";
14904 return NULL;
14905 case CLI_GENERATE:
14906 return NULL;
14907 }
14908 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14909 ast_mutex_lock(&iflock);
14910 for (p = iflist; p; p = p->next) {
14911 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14912 continue;
14913 }
14914 if ((channo != -1) && (p->channel != channo )) {
14915 continue;
14916 }
14917 openr2_chan_set_blocked(p->r2chan);
14918 ast_mutex_lock(&p->lock);
14919 p->locallyblocked = 1;
14920 ast_mutex_unlock(&p->lock);
14921 if (channo != -1) {
14922 break;
14923 }
14924 }
14925 if ((channo != -1) && !p) {
14926 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14927 }
14928 ast_mutex_unlock(&iflock);
14929 return CLI_SUCCESS;
14930 }
14931
14932 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14933 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14934 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14935 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14936 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14937 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14938 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14939 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14940 };
14941
14942 #endif
14943
14944 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14945 {
14946 int channel;
14947 int ret;
14948 switch (cmd) {
14949 case CLI_INIT:
14950 e->command = "dahdi destroy channel";
14951 e->usage =
14952 "Usage: dahdi destroy channel <chan num>\n"
14953 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14954 return NULL;
14955 case CLI_GENERATE:
14956 return NULL;
14957 }
14958 if (a->argc != 4)
14959 return CLI_SHOWUSAGE;
14960
14961 channel = atoi(a->argv[3]);
14962 ret = dahdi_destroy_channel_bynum(channel);
14963 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14964 }
14965
14966 static void dahdi_softhangup_all(void)
14967 {
14968 struct dahdi_pvt *p;
14969 retry:
14970 ast_mutex_lock(&iflock);
14971 for (p = iflist; p; p = p->next) {
14972 ast_mutex_lock(&p->lock);
14973 if (p->owner && !p->restartpending) {
14974 if (ast_channel_trylock(p->owner)) {
14975 if (option_debug > 2)
14976 ast_verbose("Avoiding deadlock\n");
14977
14978 ast_mutex_unlock(&p->lock);
14979 ast_mutex_unlock(&iflock);
14980 goto retry;
14981 }
14982 if (option_debug > 2)
14983 ast_verbose("Softhanging up on %s\n", p->owner->name);
14984 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14985 p->restartpending = 1;
14986 num_restart_pending++;
14987 ast_channel_unlock(p->owner);
14988 }
14989 ast_mutex_unlock(&p->lock);
14990 }
14991 ast_mutex_unlock(&iflock);
14992 }
14993
14994 static int setup_dahdi(int reload);
14995 static int dahdi_restart(void)
14996 {
14997 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14998 int i, j;
14999 #endif
15000 int cancel_code;
15001 struct dahdi_pvt *p;
15002
15003 ast_mutex_lock(&restart_lock);
15004 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15005 dahdi_softhangup_all();
15006 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15007 #ifdef HAVE_OPENR2
15008 dahdi_r2_destroy_links();
15009 #endif
15010
15011 #if defined(HAVE_PRI)
15012 for (i = 0; i < NUM_SPANS; i++) {
15013 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15014 cancel_code = pthread_cancel(pris[i].pri.master);
15015 pthread_kill(pris[i].pri.master, SIGURG);
15016 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);
15017 pthread_join(pris[i].pri.master, NULL);
15018 ast_debug(4, "Joined thread of span %d\n", i);
15019 }
15020 }
15021 #endif
15022
15023 #if defined(HAVE_SS7)
15024 for (i = 0; i < NUM_SPANS; i++) {
15025 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15026 cancel_code = pthread_cancel(linksets[i].ss7.master);
15027 pthread_kill(linksets[i].ss7.master, SIGURG);
15028 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);
15029 pthread_join(linksets[i].ss7.master, NULL);
15030 ast_debug(4, "Joined thread of span %d\n", i);
15031 }
15032 }
15033 #endif
15034
15035 ast_mutex_lock(&monlock);
15036 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15037 cancel_code = pthread_cancel(monitor_thread);
15038 pthread_kill(monitor_thread, SIGURG);
15039 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15040 pthread_join(monitor_thread, NULL);
15041 ast_debug(4, "Joined monitor thread\n");
15042 }
15043 monitor_thread = AST_PTHREADT_NULL;
15044
15045 ast_mutex_lock(&ss_thread_lock);
15046 while (ss_thread_count > 0) {
15047 int x = DAHDI_FLASH;
15048 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15049
15050 ast_mutex_lock(&iflock);
15051 for (p = iflist; p; p = p->next) {
15052 if (p->owner) {
15053
15054 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15055 }
15056 }
15057 ast_mutex_unlock(&iflock);
15058 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15059 }
15060
15061
15062 dahdi_softhangup_all();
15063 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15064 destroy_all_channels();
15065 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15066
15067 ast_mutex_unlock(&monlock);
15068
15069 #ifdef HAVE_PRI
15070 for (i = 0; i < NUM_SPANS; i++) {
15071 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15072 dahdi_close_pri_fd(&(pris[i]), j);
15073 }
15074
15075 memset(pris, 0, sizeof(pris));
15076 for (i = 0; i < NUM_SPANS; i++) {
15077 sig_pri_init_pri(&pris[i].pri);
15078 }
15079 pri_set_error(dahdi_pri_error);
15080 pri_set_message(dahdi_pri_message);
15081 #endif
15082 #if defined(HAVE_SS7)
15083 for (i = 0; i < NUM_SPANS; i++) {
15084 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15085 dahdi_close_ss7_fd(&(linksets[i]), j);
15086 }
15087
15088 memset(linksets, 0, sizeof(linksets));
15089 for (i = 0; i < NUM_SPANS; i++) {
15090 sig_ss7_init_linkset(&linksets[i].ss7);
15091 }
15092 ss7_set_error(dahdi_ss7_error);
15093 ss7_set_message(dahdi_ss7_message);
15094 #endif
15095
15096 if (setup_dahdi(2) != 0) {
15097 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15098 ast_mutex_unlock(&ss_thread_lock);
15099 return 1;
15100 }
15101 ast_mutex_unlock(&ss_thread_lock);
15102 ast_mutex_unlock(&restart_lock);
15103 return 0;
15104 }
15105
15106 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15107 {
15108 switch (cmd) {
15109 case CLI_INIT:
15110 e->command = "dahdi restart";
15111 e->usage =
15112 "Usage: dahdi restart\n"
15113 " Restarts the DAHDI channels: destroys them all and then\n"
15114 " re-reads them from chan_dahdi.conf.\n"
15115 " Note that this will STOP any running CALL on DAHDI channels.\n"
15116 "";
15117 return NULL;
15118 case CLI_GENERATE:
15119 return NULL;
15120 }
15121 if (a->argc != 2)
15122 return CLI_SHOWUSAGE;
15123
15124 if (dahdi_restart() != 0)
15125 return CLI_FAILURE;
15126 return CLI_SUCCESS;
15127 }
15128
15129 static int action_dahdirestart(struct mansession *s, const struct message *m)
15130 {
15131 if (dahdi_restart() != 0) {
15132 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15133 return 1;
15134 }
15135 astman_send_ack(s, m, "DAHDIRestart: Success");
15136 return 0;
15137 }
15138
15139 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15140 {
15141 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15142 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15143 unsigned int targetnum = 0;
15144 int filtertype = 0;
15145 struct dahdi_pvt *tmp = NULL;
15146 char tmps[20] = "";
15147 char statestr[20] = "";
15148 char blockstr[20] = "";
15149
15150 switch (cmd) {
15151 case CLI_INIT:
15152 e->command = "dahdi show channels [group|context]";
15153 e->usage =
15154 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15155 " Shows a list of available channels with optional filtering\n"
15156 " <group> must be a number between 0 and 63\n";
15157 return NULL;
15158 case CLI_GENERATE:
15159 return NULL;
15160 }
15161
15162
15163
15164 if (!((a->argc == 3) || (a->argc == 5)))
15165 return CLI_SHOWUSAGE;
15166
15167 if (a->argc == 5) {
15168 if (!strcasecmp(a->argv[3], "group")) {
15169 targetnum = atoi(a->argv[4]);
15170 if ((targetnum < 0) || (targetnum > 63))
15171 return CLI_SHOWUSAGE;
15172 targetnum = 1 << targetnum;
15173 filtertype = 1;
15174 } else if (!strcasecmp(a->argv[3], "context")) {
15175 filtertype = 2;
15176 }
15177 }
15178
15179 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15180 ast_mutex_lock(&iflock);
15181 for (tmp = iflist; tmp; tmp = tmp->next) {
15182 if (filtertype) {
15183 switch(filtertype) {
15184 case 1:
15185 if (!(tmp->group & targetnum)) {
15186 continue;
15187 }
15188 break;
15189 case 2:
15190 if (strcasecmp(tmp->context, a->argv[4])) {
15191 continue;
15192 }
15193 break;
15194 default:
15195 break;
15196 }
15197 }
15198 if (tmp->channel > 0) {
15199 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15200 } else
15201 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15202
15203 if (tmp->locallyblocked)
15204 blockstr[0] = 'L';
15205 else
15206 blockstr[0] = ' ';
15207
15208 if (tmp->remotelyblocked)
15209 blockstr[1] = 'R';
15210 else
15211 blockstr[1] = ' ';
15212
15213 blockstr[2] = '\0';
15214
15215 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15216
15217 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15218 }
15219 ast_mutex_unlock(&iflock);
15220 return CLI_SUCCESS;
15221 #undef FORMAT
15222 #undef FORMAT2
15223 }
15224
15225 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15226 {
15227 int channel;
15228 struct dahdi_pvt *tmp = NULL;
15229 struct dahdi_confinfo ci;
15230 struct dahdi_params ps;
15231 int x;
15232
15233 switch (cmd) {
15234 case CLI_INIT:
15235 e->command = "dahdi show channel";
15236 e->usage =
15237 "Usage: dahdi show channel <chan num>\n"
15238 " Detailed information about a given channel\n";
15239 return NULL;
15240 case CLI_GENERATE:
15241 return NULL;
15242 }
15243
15244 if (a->argc != 4)
15245 return CLI_SHOWUSAGE;
15246
15247 channel = atoi(a->argv[3]);
15248
15249 ast_mutex_lock(&iflock);
15250 for (tmp = iflist; tmp; tmp = tmp->next) {
15251 if (tmp->channel == channel) {
15252 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15253 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15254 ast_cli(a->fd, "Span: %d\n", tmp->span);
15255 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15256 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15257 ast_cli(a->fd, "Context: %s\n", tmp->context);
15258 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15259 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15260 #if defined(HAVE_PRI)
15261 #if defined(HAVE_PRI_SUBADDR)
15262 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15263 #endif
15264 #endif
15265 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15266 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15267 if (tmp->vars) {
15268 struct ast_variable *v;
15269 ast_cli(a->fd, "Variables:\n");
15270 for (v = tmp->vars ; v ; v = v->next)
15271 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15272 }
15273 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15274 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15275 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15276 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15277 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15278 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)" : "");
15279 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)" : "");
15280 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)" : "");
15281 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15282 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15283 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15284 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15285 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15286 if (tmp->busydetect) {
15287 #if defined(BUSYDETECT_TONEONLY)
15288 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15289 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15290 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15291 #endif
15292 #ifdef BUSYDETECT_DEBUG
15293 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15294 #endif
15295 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15296 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15297 }
15298 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15299 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15300 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15301 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15302 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15303 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15304 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15305 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15306 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15307 ast_cli(a->fd, "Echo Cancellation:\n");
15308
15309 if (tmp->echocancel.head.tap_length) {
15310 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15311 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15312 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15313 }
15314 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15315 } else {
15316 ast_cli(a->fd, "\tnone\n");
15317 }
15318 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15319 if (tmp->master)
15320 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15321 for (x = 0; x < MAX_SLAVES; x++) {
15322 if (tmp->slaves[x])
15323 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15324 }
15325 #ifdef HAVE_OPENR2
15326 if (tmp->mfcr2) {
15327 char calldir[OR2_MAX_PATH];
15328 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15329 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15330 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15331 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15332 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15333 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15334 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15335 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15336 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15337 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15338 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15339 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15340 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15341 #endif
15342 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15343 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15344 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15345 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15346 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15347 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15348 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15349 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15350 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15351 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15352 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15353 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15354 }
15355 #endif
15356 #if defined(HAVE_SS7)
15357 if (tmp->ss7) {
15358 struct sig_ss7_chan *chan = tmp->sig_pvt;
15359
15360 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15361 }
15362 #endif
15363 #ifdef HAVE_PRI
15364 if (tmp->pri) {
15365 struct sig_pri_chan *chan = tmp->sig_pvt;
15366
15367 ast_cli(a->fd, "PRI Flags: ");
15368 if (chan->resetting)
15369 ast_cli(a->fd, "Resetting ");
15370 if (chan->call)
15371 ast_cli(a->fd, "Call ");
15372 if (chan->allocated) {
15373 ast_cli(a->fd, "Allocated ");
15374 }
15375 ast_cli(a->fd, "\n");
15376 if (tmp->logicalspan)
15377 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15378 else
15379 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15380 }
15381 #endif
15382 memset(&ci, 0, sizeof(ci));
15383 ps.channo = tmp->channel;
15384 if (tmp->subs[SUB_REAL].dfd > -1) {
15385 memset(&ci, 0, sizeof(ci));
15386 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15387 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15388 }
15389 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15390 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15391 }
15392 memset(&ps, 0, sizeof(ps));
15393 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15394 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15395 } else {
15396 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15397 }
15398 }
15399 ast_mutex_unlock(&iflock);
15400 return CLI_SUCCESS;
15401 }
15402 }
15403 ast_mutex_unlock(&iflock);
15404
15405 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15406 return CLI_FAILURE;
15407 }
15408
15409 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15410 {
15411 int i, j;
15412 switch (cmd) {
15413 case CLI_INIT:
15414 e->command = "dahdi show cadences";
15415 e->usage =
15416 "Usage: dahdi show cadences\n"
15417 " Shows all cadences currently defined\n";
15418 return NULL;
15419 case CLI_GENERATE:
15420 return NULL;
15421 }
15422 for (i = 0; i < num_cadence; i++) {
15423 char output[1024];
15424 char tmp[16], tmp2[64];
15425 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15426 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15427
15428 for (j = 0; j < 16; j++) {
15429 if (cadences[i].ringcadence[j] == 0)
15430 break;
15431 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15432 if (cidrings[i] * 2 - 1 == j)
15433 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15434 else
15435 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15436 if (j != 0)
15437 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15438 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15439 }
15440 ast_cli(a->fd,"%s\n",output);
15441 }
15442 return CLI_SUCCESS;
15443 }
15444
15445
15446 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15447 {
15448 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15449 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15450 int span;
15451 int res;
15452 char alarmstr[50];
15453
15454 int ctl;
15455 struct dahdi_spaninfo s;
15456
15457 switch (cmd) {
15458 case CLI_INIT:
15459 e->command = "dahdi show status";
15460 e->usage =
15461 "Usage: dahdi show status\n"
15462 " Shows a list of DAHDI cards with status\n";
15463 return NULL;
15464 case CLI_GENERATE:
15465 return NULL;
15466 }
15467 ctl = open("/dev/dahdi/ctl", O_RDWR);
15468 if (ctl < 0) {
15469 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15470 return CLI_FAILURE;
15471 }
15472 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15473
15474 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15475 s.spanno = span;
15476 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15477 if (res) {
15478 continue;
15479 }
15480 alarmstr[0] = '\0';
15481 if (s.alarms > 0) {
15482 if (s.alarms & DAHDI_ALARM_BLUE)
15483 strcat(alarmstr, "BLU/");
15484 if (s.alarms & DAHDI_ALARM_YELLOW)
15485 strcat(alarmstr, "YEL/");
15486 if (s.alarms & DAHDI_ALARM_RED)
15487 strcat(alarmstr, "RED/");
15488 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15489 strcat(alarmstr, "LB/");
15490 if (s.alarms & DAHDI_ALARM_RECOVER)
15491 strcat(alarmstr, "REC/");
15492 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15493 strcat(alarmstr, "NOP/");
15494 if (!strlen(alarmstr))
15495 strcat(alarmstr, "UUU/");
15496 if (strlen(alarmstr)) {
15497
15498 alarmstr[strlen(alarmstr) - 1] = '\0';
15499 }
15500 } else {
15501 if (s.numchans)
15502 strcpy(alarmstr, "OK");
15503 else
15504 strcpy(alarmstr, "UNCONFIGURED");
15505 }
15506
15507 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15508 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15509 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15510 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15511 "CAS",
15512 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15513 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15514 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15515 "Unk",
15516 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15517 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15518 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15519 lbostr[s.lbo]
15520 );
15521 }
15522 close(ctl);
15523
15524 return CLI_SUCCESS;
15525 #undef FORMAT
15526 #undef FORMAT2
15527 }
15528
15529 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15530 {
15531 int pseudo_fd = -1;
15532 struct dahdi_versioninfo vi;
15533
15534 switch (cmd) {
15535 case CLI_INIT:
15536 e->command = "dahdi show version";
15537 e->usage =
15538 "Usage: dahdi show version\n"
15539 " Shows the DAHDI version in use\n";
15540 return NULL;
15541 case CLI_GENERATE:
15542 return NULL;
15543 }
15544 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15545 ast_cli(a->fd, "Failed to open control file to get version.\n");
15546 return CLI_SUCCESS;
15547 }
15548
15549 strcpy(vi.version, "Unknown");
15550 strcpy(vi.echo_canceller, "Unknown");
15551
15552 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15553 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15554 else
15555 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15556
15557 close(pseudo_fd);
15558
15559 return CLI_SUCCESS;
15560 }
15561
15562 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15563 {
15564 int channel;
15565 int gain;
15566 int tx;
15567 struct dahdi_hwgain hwgain;
15568 struct dahdi_pvt *tmp = NULL;
15569
15570 switch (cmd) {
15571 case CLI_INIT:
15572 e->command = "dahdi set hwgain";
15573 e->usage =
15574 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15575 " Sets the hardware gain on a a given channel, overriding the\n"
15576 " value provided at module loadtime, whether the channel is in\n"
15577 " use or not. Changes take effect immediately.\n"
15578 " <rx|tx> which direction do you want to change (relative to our module)\n"
15579 " <chan num> is the channel number relative to the device\n"
15580 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15581 return NULL;
15582 case CLI_GENERATE:
15583 return NULL;
15584 }
15585
15586 if (a->argc != 6)
15587 return CLI_SHOWUSAGE;
15588
15589 if (!strcasecmp("rx", a->argv[3]))
15590 tx = 0;
15591 else if (!strcasecmp("tx", a->argv[3]))
15592 tx = 1;
15593 else
15594 return CLI_SHOWUSAGE;
15595
15596 channel = atoi(a->argv[4]);
15597 gain = atof(a->argv[5])*10.0;
15598
15599 ast_mutex_lock(&iflock);
15600
15601 for (tmp = iflist; tmp; tmp = tmp->next) {
15602
15603 if (tmp->channel != channel)
15604 continue;
15605
15606 if (tmp->subs[SUB_REAL].dfd == -1)
15607 break;
15608
15609 hwgain.newgain = gain;
15610 hwgain.tx = tx;
15611 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15612 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15613 ast_mutex_unlock(&iflock);
15614 return CLI_FAILURE;
15615 }
15616 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15617 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15618 break;
15619 }
15620
15621 ast_mutex_unlock(&iflock);
15622
15623 if (tmp)
15624 return CLI_SUCCESS;
15625
15626 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15627 return CLI_FAILURE;
15628
15629 }
15630
15631 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15632 {
15633 int channel;
15634 float gain;
15635 int tx;
15636 int res;
15637 struct dahdi_pvt *tmp = NULL;
15638
15639 switch (cmd) {
15640 case CLI_INIT:
15641 e->command = "dahdi set swgain";
15642 e->usage =
15643 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15644 " Sets the software gain on a a given channel, overriding the\n"
15645 " value provided at module loadtime, whether the channel is in\n"
15646 " use or not. Changes take effect immediately.\n"
15647 " <rx|tx> which direction do you want to change (relative to our module)\n"
15648 " <chan num> is the channel number relative to the device\n"
15649 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15650 return NULL;
15651 case CLI_GENERATE:
15652 return NULL;
15653 }
15654
15655 if (a->argc != 6)
15656 return CLI_SHOWUSAGE;
15657
15658 if (!strcasecmp("rx", a->argv[3]))
15659 tx = 0;
15660 else if (!strcasecmp("tx", a->argv[3]))
15661 tx = 1;
15662 else
15663 return CLI_SHOWUSAGE;
15664
15665 channel = atoi(a->argv[4]);
15666 gain = atof(a->argv[5]);
15667
15668 ast_mutex_lock(&iflock);
15669 for (tmp = iflist; tmp; tmp = tmp->next) {
15670
15671 if (tmp->channel != channel)
15672 continue;
15673
15674 if (tmp->subs[SUB_REAL].dfd == -1)
15675 break;
15676
15677 if (tx)
15678 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15679 else
15680 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15681
15682 if (res) {
15683 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15684 ast_mutex_unlock(&iflock);
15685 return CLI_FAILURE;
15686 }
15687
15688 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15689 tx ? "tx" : "rx", gain, channel);
15690 break;
15691 }
15692 ast_mutex_unlock(&iflock);
15693
15694 if (tmp)
15695 return CLI_SUCCESS;
15696
15697 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15698 return CLI_FAILURE;
15699
15700 }
15701
15702 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15703 {
15704 int channel;
15705 int on;
15706 struct dahdi_pvt *dahdi_chan = NULL;
15707
15708 switch (cmd) {
15709 case CLI_INIT:
15710 e->command = "dahdi set dnd";
15711 e->usage =
15712 "Usage: dahdi set dnd <chan#> <on|off>\n"
15713 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15714 " Changes take effect immediately.\n"
15715 " <chan num> is the channel number\n"
15716 " <on|off> Enable or disable DND mode?\n"
15717 ;
15718 return NULL;
15719 case CLI_GENERATE:
15720 return NULL;
15721 }
15722
15723 if (a->argc != 5)
15724 return CLI_SHOWUSAGE;
15725
15726 if ((channel = atoi(a->argv[3])) <= 0) {
15727 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15728 return CLI_SHOWUSAGE;
15729 }
15730
15731 if (ast_true(a->argv[4]))
15732 on = 1;
15733 else if (ast_false(a->argv[4]))
15734 on = 0;
15735 else {
15736 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15737 return CLI_SHOWUSAGE;
15738 }
15739
15740 ast_mutex_lock(&iflock);
15741 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15742 if (dahdi_chan->channel != channel)
15743 continue;
15744
15745
15746 dahdi_dnd(dahdi_chan, on);
15747 break;
15748 }
15749 ast_mutex_unlock(&iflock);
15750
15751 if (!dahdi_chan) {
15752 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15753 return CLI_FAILURE;
15754 }
15755
15756 return CLI_SUCCESS;
15757 }
15758
15759 static struct ast_cli_entry dahdi_cli[] = {
15760 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15761 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15762 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15763 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15764 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15765 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15766 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15767 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15768 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15769 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15770 };
15771
15772 #define TRANSFER 0
15773 #define HANGUP 1
15774
15775 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15776 {
15777 if (p) {
15778 switch (mode) {
15779 case TRANSFER:
15780 p->fake_event = DAHDI_EVENT_WINKFLASH;
15781 break;
15782 case HANGUP:
15783 p->fake_event = DAHDI_EVENT_ONHOOK;
15784 break;
15785 default:
15786 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15787 }
15788 }
15789 return 0;
15790 }
15791 static struct dahdi_pvt *find_channel(int channel)
15792 {
15793 struct dahdi_pvt *p;
15794
15795 ast_mutex_lock(&iflock);
15796 for (p = iflist; p; p = p->next) {
15797 if (p->channel == channel) {
15798 break;
15799 }
15800 }
15801 ast_mutex_unlock(&iflock);
15802 return p;
15803 }
15804
15805
15806
15807
15808
15809
15810
15811
15812
15813
15814 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15815 {
15816 int chan_num;
15817
15818 if (sscanf(channel, "%30d", &chan_num) != 1) {
15819
15820 return NULL;
15821 }
15822
15823 return find_channel(chan_num);
15824 }
15825
15826 static int action_dahdidndon(struct mansession *s, const struct message *m)
15827 {
15828 struct dahdi_pvt *p;
15829 const char *channel = astman_get_header(m, "DAHDIChannel");
15830
15831 if (ast_strlen_zero(channel)) {
15832 astman_send_error(s, m, "No channel specified");
15833 return 0;
15834 }
15835 p = find_channel_from_str(channel);
15836 if (!p) {
15837 astman_send_error(s, m, "No such channel");
15838 return 0;
15839 }
15840 dahdi_dnd(p, 1);
15841 astman_send_ack(s, m, "DND Enabled");
15842 return 0;
15843 }
15844
15845 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15846 {
15847 struct dahdi_pvt *p;
15848 const char *channel = astman_get_header(m, "DAHDIChannel");
15849
15850 if (ast_strlen_zero(channel)) {
15851 astman_send_error(s, m, "No channel specified");
15852 return 0;
15853 }
15854 p = find_channel_from_str(channel);
15855 if (!p) {
15856 astman_send_error(s, m, "No such channel");
15857 return 0;
15858 }
15859 dahdi_dnd(p, 0);
15860 astman_send_ack(s, m, "DND Disabled");
15861 return 0;
15862 }
15863
15864 static int action_transfer(struct mansession *s, const struct message *m)
15865 {
15866 struct dahdi_pvt *p;
15867 const char *channel = astman_get_header(m, "DAHDIChannel");
15868
15869 if (ast_strlen_zero(channel)) {
15870 astman_send_error(s, m, "No channel specified");
15871 return 0;
15872 }
15873 p = find_channel_from_str(channel);
15874 if (!p) {
15875 astman_send_error(s, m, "No such channel");
15876 return 0;
15877 }
15878 if (!analog_lib_handles(p->sig, 0, 0)) {
15879 astman_send_error(s, m, "Channel signaling is not analog");
15880 return 0;
15881 }
15882 dahdi_fake_event(p,TRANSFER);
15883 astman_send_ack(s, m, "DAHDITransfer");
15884 return 0;
15885 }
15886
15887 static int action_transferhangup(struct mansession *s, const struct message *m)
15888 {
15889 struct dahdi_pvt *p;
15890 const char *channel = astman_get_header(m, "DAHDIChannel");
15891
15892 if (ast_strlen_zero(channel)) {
15893 astman_send_error(s, m, "No channel specified");
15894 return 0;
15895 }
15896 p = find_channel_from_str(channel);
15897 if (!p) {
15898 astman_send_error(s, m, "No such channel");
15899 return 0;
15900 }
15901 if (!analog_lib_handles(p->sig, 0, 0)) {
15902 astman_send_error(s, m, "Channel signaling is not analog");
15903 return 0;
15904 }
15905 dahdi_fake_event(p,HANGUP);
15906 astman_send_ack(s, m, "DAHDIHangup");
15907 return 0;
15908 }
15909
15910 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15911 {
15912 struct dahdi_pvt *p;
15913 const char *channel = astman_get_header(m, "DAHDIChannel");
15914 const char *number = astman_get_header(m, "Number");
15915 int i;
15916
15917 if (ast_strlen_zero(channel)) {
15918 astman_send_error(s, m, "No channel specified");
15919 return 0;
15920 }
15921 if (ast_strlen_zero(number)) {
15922 astman_send_error(s, m, "No number specified");
15923 return 0;
15924 }
15925 p = find_channel_from_str(channel);
15926 if (!p) {
15927 astman_send_error(s, m, "No such channel");
15928 return 0;
15929 }
15930 if (!p->owner) {
15931 astman_send_error(s, m, "Channel does not have it's owner");
15932 return 0;
15933 }
15934 for (i = 0; i < strlen(number); i++) {
15935 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15936 dahdi_queue_frame(p, &f);
15937 }
15938 astman_send_ack(s, m, "DAHDIDialOffhook");
15939 return 0;
15940 }
15941
15942 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15943 {
15944 struct dahdi_pvt *tmp = NULL;
15945 const char *id = astman_get_header(m, "ActionID");
15946 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15947 char idText[256] = "";
15948 int channels = 0;
15949 int dahdichanquery;
15950
15951 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15952
15953 dahdichanquery = -1;
15954 }
15955
15956 astman_send_ack(s, m, "DAHDI channel status will follow");
15957 if (!ast_strlen_zero(id))
15958 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15959
15960 ast_mutex_lock(&iflock);
15961
15962 for (tmp = iflist; tmp; tmp = tmp->next) {
15963 if (tmp->channel > 0) {
15964 int alm;
15965
15966
15967 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15968 continue;
15969
15970 alm = get_alarms(tmp);
15971 channels++;
15972 if (tmp->owner) {
15973
15974 astman_append(s,
15975 "Event: DAHDIShowChannels\r\n"
15976 "DAHDIChannel: %d\r\n"
15977 "Channel: %s\r\n"
15978 "Uniqueid: %s\r\n"
15979 "AccountCode: %s\r\n"
15980 "Signalling: %s\r\n"
15981 "SignallingCode: %d\r\n"
15982 "Context: %s\r\n"
15983 "DND: %s\r\n"
15984 "Alarm: %s\r\n"
15985 "%s"
15986 "\r\n",
15987 tmp->channel,
15988 tmp->owner->name,
15989 tmp->owner->uniqueid,
15990 tmp->owner->accountcode,
15991 sig2str(tmp->sig),
15992 tmp->sig,
15993 tmp->context,
15994 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15995 alarm2str(alm), idText);
15996 } else {
15997 astman_append(s,
15998 "Event: DAHDIShowChannels\r\n"
15999 "DAHDIChannel: %d\r\n"
16000 "Signalling: %s\r\n"
16001 "SignallingCode: %d\r\n"
16002 "Context: %s\r\n"
16003 "DND: %s\r\n"
16004 "Alarm: %s\r\n"
16005 "%s"
16006 "\r\n",
16007 tmp->channel, sig2str(tmp->sig), tmp->sig,
16008 tmp->context,
16009 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16010 alarm2str(alm), idText);
16011 }
16012 }
16013 }
16014
16015 ast_mutex_unlock(&iflock);
16016
16017 astman_append(s,
16018 "Event: DAHDIShowChannelsComplete\r\n"
16019 "%s"
16020 "Items: %d\r\n"
16021 "\r\n",
16022 idText,
16023 channels);
16024 return 0;
16025 }
16026
16027 #if defined(HAVE_SS7)
16028 static int linkset_addsigchan(int sigchan)
16029 {
16030 struct dahdi_ss7 *link;
16031 int res;
16032 int curfd;
16033 struct dahdi_params params;
16034 struct dahdi_bufferinfo bi;
16035 struct dahdi_spaninfo si;
16036
16037 if (sigchan < 0) {
16038 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16039 return -1;
16040 }
16041 if (cur_ss7type < 0) {
16042 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16043 return -1;
16044 }
16045 if (cur_pointcode < 0) {
16046 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16047 return -1;
16048 }
16049 if (cur_adjpointcode < 0) {
16050 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16051 return -1;
16052 }
16053 if (cur_defaultdpc < 0) {
16054 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16055 return -1;
16056 }
16057 if (cur_networkindicator < 0) {
16058 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16059 return -1;
16060 }
16061 link = ss7_resolve_linkset(cur_linkset);
16062 if (!link) {
16063 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16064 return -1;
16065 }
16066 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16067 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16068 return -1;
16069 }
16070
16071 curfd = link->ss7.numsigchans;
16072
16073
16074 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16075 if (link->ss7.fds[curfd] < 0) {
16076 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16077 strerror(errno));
16078 return -1;
16079 }
16080 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16081 dahdi_close_ss7_fd(link, curfd);
16082 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16083 strerror(errno));
16084 return -1;
16085 }
16086
16087
16088 memset(¶ms, 0, sizeof(params));
16089 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16090 if (res) {
16091 dahdi_close_ss7_fd(link, curfd);
16092 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16093 strerror(errno));
16094 return -1;
16095 }
16096 if (params.sigtype != DAHDI_SIG_HDLCFCS
16097 && params.sigtype != DAHDI_SIG_HARDHDLC
16098 && params.sigtype != DAHDI_SIG_MTP2) {
16099 dahdi_close_ss7_fd(link, curfd);
16100 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16101 return -1;
16102 }
16103
16104
16105 memset(&bi, 0, sizeof(bi));
16106 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16107 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16108 bi.numbufs = 32;
16109 bi.bufsize = 512;
16110 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16111 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16112 sigchan, strerror(errno));
16113 dahdi_close_ss7_fd(link, curfd);
16114 return -1;
16115 }
16116
16117
16118 memset(&si, 0, sizeof(si));
16119 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16120 if (res) {
16121 dahdi_close_ss7_fd(link, curfd);
16122 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16123 strerror(errno));
16124 }
16125
16126 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16127 (params.sigtype == DAHDI_SIG_MTP2)
16128 ? SS7_TRANSPORT_DAHDIMTP2
16129 : SS7_TRANSPORT_DAHDIDCHAN,
16130 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16131 if (res) {
16132 dahdi_close_ss7_fd(link, curfd);
16133 return -1;
16134 }
16135
16136 ++link->ss7.numsigchans;
16137
16138 return 0;
16139 }
16140 #endif
16141
16142 #if defined(HAVE_SS7)
16143 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16144 {
16145 int span;
16146 switch (cmd) {
16147 case CLI_INIT:
16148 e->command = "ss7 set debug {on|off} linkset";
16149 e->usage =
16150 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16151 " Enables debugging on a given SS7 linkset\n";
16152 return NULL;
16153 case CLI_GENERATE:
16154 return NULL;
16155 }
16156 if (a->argc < 6)
16157 return CLI_SHOWUSAGE;
16158 span = atoi(a->argv[5]);
16159 if ((span < 1) || (span > NUM_SPANS)) {
16160 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16161 return CLI_SUCCESS;
16162 }
16163 if (!linksets[span-1].ss7.ss7) {
16164 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16165 } else {
16166 if (!strcasecmp(a->argv[3], "on")) {
16167 linksets[span - 1].ss7.debug = 1;
16168 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16169 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16170 } else {
16171 linksets[span - 1].ss7.debug = 0;
16172 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16173 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16174 }
16175 }
16176
16177 return CLI_SUCCESS;
16178 }
16179 #endif
16180
16181 #if defined(HAVE_SS7)
16182 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16183 {
16184 int linkset, cic;
16185 int blocked = -1, i;
16186 switch (cmd) {
16187 case CLI_INIT:
16188 e->command = "ss7 block cic";
16189 e->usage =
16190 "Usage: ss7 block cic <linkset> <CIC>\n"
16191 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16192 return NULL;
16193 case CLI_GENERATE:
16194 return NULL;
16195 }
16196 if (a->argc == 5)
16197 linkset = atoi(a->argv[3]);
16198 else
16199 return CLI_SHOWUSAGE;
16200
16201 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16202 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16203 return CLI_SUCCESS;
16204 }
16205
16206 if (!linksets[linkset-1].ss7.ss7) {
16207 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16208 return CLI_SUCCESS;
16209 }
16210
16211 cic = atoi(a->argv[4]);
16212
16213 if (cic < 1) {
16214 ast_cli(a->fd, "Invalid CIC specified!\n");
16215 return CLI_SUCCESS;
16216 }
16217
16218 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16219 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16220 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16221 if (!blocked) {
16222 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16223 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16224 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16225 }
16226 }
16227 }
16228
16229 if (blocked < 0) {
16230 ast_cli(a->fd, "Invalid CIC specified!\n");
16231 return CLI_SUCCESS;
16232 }
16233
16234 if (!blocked)
16235 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16236 else
16237 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16238
16239
16240 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16241
16242 return CLI_SUCCESS;
16243 }
16244 #endif
16245
16246 #if defined(HAVE_SS7)
16247 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16248 {
16249 int linkset;
16250 int i;
16251 switch (cmd) {
16252 case CLI_INIT:
16253 e->command = "ss7 block linkset";
16254 e->usage =
16255 "Usage: ss7 block linkset <linkset number>\n"
16256 " Sends a remote blocking request for all CICs on the given linkset\n";
16257 return NULL;
16258 case CLI_GENERATE:
16259 return NULL;
16260 }
16261 if (a->argc == 4)
16262 linkset = atoi(a->argv[3]);
16263 else
16264 return CLI_SHOWUSAGE;
16265
16266 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16267 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16268 return CLI_SUCCESS;
16269 }
16270
16271 if (!linksets[linkset-1].ss7.ss7) {
16272 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16273 return CLI_SUCCESS;
16274 }
16275
16276 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16277 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16278 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16279 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16280 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16281 }
16282
16283
16284 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16285
16286 return CLI_SUCCESS;
16287 }
16288 #endif
16289
16290 #if defined(HAVE_SS7)
16291 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16292 {
16293 int linkset, cic;
16294 int i, blocked = -1;
16295 switch (cmd) {
16296 case CLI_INIT:
16297 e->command = "ss7 unblock cic";
16298 e->usage =
16299 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16300 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16301 return NULL;
16302 case CLI_GENERATE:
16303 return NULL;
16304 }
16305
16306 if (a->argc == 5)
16307 linkset = atoi(a->argv[3]);
16308 else
16309 return CLI_SHOWUSAGE;
16310
16311 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16312 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16313 return CLI_SUCCESS;
16314 }
16315
16316 if (!linksets[linkset-1].ss7.ss7) {
16317 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16318 return CLI_SUCCESS;
16319 }
16320
16321 cic = atoi(a->argv[4]);
16322
16323 if (cic < 1) {
16324 ast_cli(a->fd, "Invalid CIC specified!\n");
16325 return CLI_SUCCESS;
16326 }
16327
16328 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16329 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16330 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16331 if (blocked) {
16332 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16333 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16334 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16335 }
16336 }
16337 }
16338
16339 if (blocked > 0)
16340 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16341
16342
16343 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16344
16345 return CLI_SUCCESS;
16346 }
16347 #endif
16348
16349 #if defined(HAVE_SS7)
16350 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16351 {
16352 int linkset;
16353 int i;
16354 switch (cmd) {
16355 case CLI_INIT:
16356 e->command = "ss7 unblock linkset";
16357 e->usage =
16358 "Usage: ss7 unblock linkset <linkset number>\n"
16359 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16360 return NULL;
16361 case CLI_GENERATE:
16362 return NULL;
16363 }
16364
16365 if (a->argc == 4)
16366 linkset = atoi(a->argv[3]);
16367 else
16368 return CLI_SHOWUSAGE;
16369
16370 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16371 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16372 return CLI_SUCCESS;
16373 }
16374
16375 if (!linksets[linkset-1].ss7.ss7) {
16376 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16377 return CLI_SUCCESS;
16378 }
16379
16380 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16381 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16382 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16383 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16384 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16385 }
16386
16387
16388 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16389
16390 return CLI_SUCCESS;
16391 }
16392 #endif
16393
16394 #if defined(HAVE_SS7)
16395 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16396 {
16397 int linkset;
16398 struct sig_ss7_linkset *ss7;
16399 switch (cmd) {
16400 case CLI_INIT:
16401 e->command = "ss7 show linkset";
16402 e->usage =
16403 "Usage: ss7 show linkset <span>\n"
16404 " Shows the status of an SS7 linkset.\n";
16405 return NULL;
16406 case CLI_GENERATE:
16407 return NULL;
16408 }
16409
16410 if (a->argc < 4)
16411 return CLI_SHOWUSAGE;
16412 linkset = atoi(a->argv[3]);
16413 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16414 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16415 return CLI_SUCCESS;
16416 }
16417 ss7 = &linksets[linkset - 1].ss7;
16418 if (!ss7->ss7) {
16419 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16420 return CLI_SUCCESS;
16421 }
16422
16423 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16424
16425 return CLI_SUCCESS;
16426 }
16427 #endif
16428
16429 #if defined(HAVE_SS7)
16430 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16431 {
16432 int linkset;
16433
16434 switch (cmd) {
16435 case CLI_INIT:
16436 e->command = "ss7 show channels";
16437 e->usage =
16438 "Usage: ss7 show channels\n"
16439 " Displays SS7 channel information at a glance.\n";
16440 return NULL;
16441 case CLI_GENERATE:
16442 return NULL;
16443 }
16444
16445 if (a->argc != 3)
16446 return CLI_SHOWUSAGE;
16447
16448 sig_ss7_cli_show_channels_header(a->fd);
16449 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16450 if (linksets[linkset].ss7.ss7) {
16451 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16452 }
16453 }
16454 return CLI_SUCCESS;
16455 }
16456 #endif
16457
16458 #if defined(HAVE_SS7)
16459 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16460 {
16461 switch (cmd) {
16462 case CLI_INIT:
16463 e->command = "ss7 show version";
16464 e->usage =
16465 "Usage: ss7 show version\n"
16466 " Show the libss7 version\n";
16467 return NULL;
16468 case CLI_GENERATE:
16469 return NULL;
16470 }
16471
16472 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16473
16474 return CLI_SUCCESS;
16475 }
16476 #endif
16477
16478 #if defined(HAVE_SS7)
16479 static struct ast_cli_entry dahdi_ss7_cli[] = {
16480 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16481 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16482 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16483 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16484 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16485 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16486 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16487 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16488 };
16489 #endif
16490
16491 #if defined(HAVE_PRI)
16492 #if defined(HAVE_PRI_CCSS)
16493
16494
16495
16496
16497
16498
16499
16500
16501
16502
16503
16504
16505
16506
16507
16508
16509
16510 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16511 {
16512 struct dahdi_pvt *pvt;
16513 struct sig_pri_chan *pvt_chan;
16514 int res;
16515
16516 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16517
16518 pvt = chan->tech_pvt;
16519 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16520 pvt_chan = pvt->sig_pvt;
16521 } else {
16522 pvt_chan = NULL;
16523 }
16524 if (!pvt_chan) {
16525 return -1;
16526 }
16527
16528 ast_module_ref(ast_module_info->self);
16529
16530 res = sig_pri_cc_agent_init(agent, pvt_chan);
16531 if (res) {
16532 ast_module_unref(ast_module_info->self);
16533 }
16534 return res;
16535 }
16536 #endif
16537 #endif
16538
16539 #if defined(HAVE_PRI)
16540 #if defined(HAVE_PRI_CCSS)
16541
16542
16543
16544
16545
16546
16547
16548
16549
16550
16551
16552
16553
16554 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16555 {
16556 sig_pri_cc_agent_destructor(agent);
16557
16558 ast_module_unref(ast_module_info->self);
16559 }
16560 #endif
16561 #endif
16562
16563 #if defined(HAVE_PRI)
16564 #if defined(HAVE_PRI_CCSS)
16565 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16566 .type = dahdi_pri_cc_type,
16567 .init = dahdi_pri_cc_agent_init,
16568 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16569 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16570 .respond = sig_pri_cc_agent_req_rsp,
16571 .status_request = sig_pri_cc_agent_status_req,
16572 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16573 .party_b_free = sig_pri_cc_agent_party_b_free,
16574 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16575 .callee_available = sig_pri_cc_agent_callee_available,
16576 .destructor = dahdi_pri_cc_agent_destructor,
16577 };
16578 #endif
16579 #endif
16580
16581 #if defined(HAVE_PRI)
16582 #if defined(HAVE_PRI_CCSS)
16583 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16584 .type = dahdi_pri_cc_type,
16585 .request_cc = sig_pri_cc_monitor_req_cc,
16586 .suspend = sig_pri_cc_monitor_suspend,
16587 .unsuspend = sig_pri_cc_monitor_unsuspend,
16588 .status_response = sig_pri_cc_monitor_status_rsp,
16589 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16590 .destructor = sig_pri_cc_monitor_destructor,
16591 };
16592 #endif
16593 #endif
16594
16595 static int __unload_module(void)
16596 {
16597 struct dahdi_pvt *p;
16598 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16599 int i, j;
16600 #endif
16601
16602 #ifdef HAVE_PRI
16603 for (i = 0; i < NUM_SPANS; i++) {
16604 if (pris[i].pri.master != AST_PTHREADT_NULL)
16605 pthread_cancel(pris[i].pri.master);
16606 }
16607 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16608 ast_unregister_application(dahdi_send_keypad_facility_app);
16609 #ifdef HAVE_PRI_PROG_W_CAUSE
16610 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16611 #endif
16612 #endif
16613 #if defined(HAVE_SS7)
16614 for (i = 0; i < NUM_SPANS; i++) {
16615 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16616 pthread_cancel(linksets[i].ss7.master);
16617 }
16618 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16619 #endif
16620 #if defined(HAVE_OPENR2)
16621 dahdi_r2_destroy_links();
16622 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16623 ast_unregister_application(dahdi_accept_r2_call_app);
16624 #endif
16625
16626 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16627 ast_manager_unregister("DAHDIDialOffhook");
16628 ast_manager_unregister("DAHDIHangup");
16629 ast_manager_unregister("DAHDITransfer");
16630 ast_manager_unregister("DAHDIDNDoff");
16631 ast_manager_unregister("DAHDIDNDon");
16632 ast_manager_unregister("DAHDIShowChannels");
16633 ast_manager_unregister("DAHDIRestart");
16634 ast_data_unregister(NULL);
16635 ast_channel_unregister(&dahdi_tech);
16636
16637
16638 ast_mutex_lock(&iflock);
16639 for (p = iflist; p; p = p->next) {
16640 if (p->owner)
16641 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16642 }
16643 ast_mutex_unlock(&iflock);
16644
16645 ast_mutex_lock(&monlock);
16646 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16647 pthread_cancel(monitor_thread);
16648 pthread_kill(monitor_thread, SIGURG);
16649 pthread_join(monitor_thread, NULL);
16650 }
16651 monitor_thread = AST_PTHREADT_STOP;
16652 ast_mutex_unlock(&monlock);
16653
16654 destroy_all_channels();
16655
16656 #if defined(HAVE_PRI)
16657 for (i = 0; i < NUM_SPANS; i++) {
16658 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16659 pthread_join(pris[i].pri.master, NULL);
16660 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16661 dahdi_close_pri_fd(&(pris[i]), j);
16662 }
16663 sig_pri_stop_pri(&pris[i].pri);
16664 }
16665 #if defined(HAVE_PRI_CCSS)
16666 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16667 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16668 #endif
16669 sig_pri_unload();
16670 #endif
16671
16672 #if defined(HAVE_SS7)
16673 for (i = 0; i < NUM_SPANS; i++) {
16674 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16675 pthread_join(linksets[i].ss7.master, NULL);
16676 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16677 dahdi_close_ss7_fd(&(linksets[i]), j);
16678 }
16679 }
16680 #endif
16681 ast_cond_destroy(&ss_thread_complete);
16682 return 0;
16683 }
16684
16685 static int unload_module(void)
16686 {
16687 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16688 int y;
16689 #endif
16690 #ifdef HAVE_PRI
16691 for (y = 0; y < NUM_SPANS; y++)
16692 ast_mutex_destroy(&pris[y].pri.lock);
16693 #endif
16694 #if defined(HAVE_SS7)
16695 for (y = 0; y < NUM_SPANS; y++)
16696 ast_mutex_destroy(&linksets[y].ss7.lock);
16697 #endif
16698 return __unload_module();
16699 }
16700
16701 static void string_replace(char *str, int char1, int char2)
16702 {
16703 for (; *str; str++) {
16704 if (*str == char1) {
16705 *str = char2;
16706 }
16707 }
16708 }
16709
16710 static char *parse_spanchan(char *chanstr, char **subdir)
16711 {
16712 char *p;
16713
16714 if ((p = strrchr(chanstr, '!')) == NULL) {
16715 *subdir = NULL;
16716 return chanstr;
16717 }
16718 *p++ = '\0';
16719 string_replace(chanstr, '!', '/');
16720 *subdir = chanstr;
16721 return p;
16722 }
16723
16724 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16725 {
16726 char *c, *chan;
16727 char *subdir;
16728 int x, start, finish;
16729 struct dahdi_pvt *tmp;
16730
16731 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16732 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16733 return -1;
16734 }
16735
16736 c = ast_strdupa(value);
16737 c = parse_spanchan(c, &subdir);
16738
16739 while ((chan = strsep(&c, ","))) {
16740 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16741
16742 } else if (sscanf(chan, "%30d", &start)) {
16743
16744 finish = start;
16745 } else if (!strcasecmp(chan, "pseudo")) {
16746 finish = start = CHAN_PSEUDO;
16747 if (found_pseudo)
16748 *found_pseudo = 1;
16749 } else {
16750 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16751 return -1;
16752 }
16753 if (finish < start) {
16754 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16755 x = finish;
16756 finish = start;
16757 start = x;
16758 }
16759
16760 for (x = start; x <= finish; x++) {
16761 char fn[PATH_MAX];
16762 int real_channel = x;
16763
16764 if (!ast_strlen_zero(subdir)) {
16765 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16766 if (real_channel < 0) {
16767 if (conf->ignore_failed_channels) {
16768 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16769 subdir, x, real_channel);
16770 continue;
16771 } else {
16772 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16773 subdir, x, real_channel);
16774 return -1;
16775 }
16776 }
16777 }
16778 tmp = mkintf(real_channel, conf, reload);
16779
16780 if (tmp) {
16781 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16782 } else {
16783 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16784 (reload == 1) ? "reconfigure" : "register", value);
16785 return -1;
16786 }
16787 }
16788 }
16789
16790 return 0;
16791 }
16792
16793
16794
16795 #define MAX_CHANLIST_LEN 80
16796
16797 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16798 {
16799 char *parse = ast_strdupa(data);
16800 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16801 unsigned int param_count;
16802 unsigned int x;
16803
16804 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16805 return;
16806
16807 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16808
16809
16810
16811 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16812
16813 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16814 confp->chan.echocancel.head.tap_length = x;
16815 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16816 confp->chan.echocancel.head.tap_length = 128;
16817
16818
16819
16820 for (x = 1; x < param_count; x++) {
16821 struct {
16822 char *name;
16823 char *value;
16824 } param;
16825
16826 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16827 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16828 continue;
16829 }
16830
16831 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16832 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16833 continue;
16834 }
16835
16836 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16837
16838 if (param.value) {
16839 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16840 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16841 continue;
16842 }
16843 }
16844 confp->chan.echocancel.head.param_count++;
16845 }
16846 }
16847
16848
16849 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16850
16851 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16852
16853 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16854 {
16855 struct dahdi_pvt *tmp;
16856 int y;
16857 int found_pseudo = 0;
16858 struct ast_variable *dahdichan = NULL;
16859
16860 for (; v; v = v->next) {
16861 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16862 continue;
16863
16864
16865 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16866 if (options & PROC_DAHDI_OPT_NOCHAN) {
16867 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16868 continue;
16869 }
16870 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16871 if (confp->ignore_failed_channels) {
16872 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16873 continue;
16874 } else {
16875 return -1;
16876 }
16877 }
16878 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16879 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16880 confp->ignore_failed_channels = ast_true(v->value);
16881 } else if (!strcasecmp(v->name, "buffers")) {
16882 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16883 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16884 confp->chan.buf_no = numbufs;
16885 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16886 }
16887 } else if (!strcasecmp(v->name, "faxbuffers")) {
16888 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16889 confp->chan.usefaxbuffers = 1;
16890 }
16891 } else if (!strcasecmp(v->name, "dahdichan")) {
16892
16893 dahdichan = v;
16894 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16895 usedistinctiveringdetection = ast_true(v->value);
16896 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16897 distinctiveringaftercid = ast_true(v->value);
16898 } else if (!strcasecmp(v->name, "dring1context")) {
16899 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16900 } else if (!strcasecmp(v->name, "dring2context")) {
16901 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16902 } else if (!strcasecmp(v->name, "dring3context")) {
16903 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16904 } else if (!strcasecmp(v->name, "dring1range")) {
16905 confp->chan.drings.ringnum[0].range = atoi(v->value);
16906 } else if (!strcasecmp(v->name, "dring2range")) {
16907 confp->chan.drings.ringnum[1].range = atoi(v->value);
16908 } else if (!strcasecmp(v->name, "dring3range")) {
16909 confp->chan.drings.ringnum[2].range = atoi(v->value);
16910 } else if (!strcasecmp(v->name, "dring1")) {
16911 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]);
16912 } else if (!strcasecmp(v->name, "dring2")) {
16913 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]);
16914 } else if (!strcasecmp(v->name, "dring3")) {
16915 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]);
16916 } else if (!strcasecmp(v->name, "usecallerid")) {
16917 confp->chan.use_callerid = ast_true(v->value);
16918 } else if (!strcasecmp(v->name, "cidsignalling")) {
16919 if (!strcasecmp(v->value, "bell"))
16920 confp->chan.cid_signalling = CID_SIG_BELL;
16921 else if (!strcasecmp(v->value, "v23"))
16922 confp->chan.cid_signalling = CID_SIG_V23;
16923 else if (!strcasecmp(v->value, "dtmf"))
16924 confp->chan.cid_signalling = CID_SIG_DTMF;
16925 else if (!strcasecmp(v->value, "smdi"))
16926 confp->chan.cid_signalling = CID_SIG_SMDI;
16927 else if (!strcasecmp(v->value, "v23_jp"))
16928 confp->chan.cid_signalling = CID_SIG_V23_JP;
16929 else if (ast_true(v->value))
16930 confp->chan.cid_signalling = CID_SIG_BELL;
16931 } else if (!strcasecmp(v->name, "cidstart")) {
16932 if (!strcasecmp(v->value, "ring"))
16933 confp->chan.cid_start = CID_START_RING;
16934 else if (!strcasecmp(v->value, "polarity_in"))
16935 confp->chan.cid_start = CID_START_POLARITY_IN;
16936 else if (!strcasecmp(v->value, "polarity"))
16937 confp->chan.cid_start = CID_START_POLARITY;
16938 else if (!strcasecmp(v->value, "dtmf"))
16939 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16940 else if (ast_true(v->value))
16941 confp->chan.cid_start = CID_START_RING;
16942 } else if (!strcasecmp(v->name, "threewaycalling")) {
16943 confp->chan.threewaycalling = ast_true(v->value);
16944 } else if (!strcasecmp(v->name, "cancallforward")) {
16945 confp->chan.cancallforward = ast_true(v->value);
16946 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16947 if (ast_true(v->value))
16948 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16949 else
16950 confp->chan.dtmfrelax = 0;
16951 } else if (!strcasecmp(v->name, "mailbox")) {
16952 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16953 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16954 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16955 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16956 }
16957 } else if (!strcasecmp(v->name, "adsi")) {
16958 confp->chan.adsi = ast_true(v->value);
16959 } else if (!strcasecmp(v->name, "usesmdi")) {
16960 confp->chan.use_smdi = ast_true(v->value);
16961 } else if (!strcasecmp(v->name, "smdiport")) {
16962 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16963 } else if (!strcasecmp(v->name, "transfer")) {
16964 confp->chan.transfer = ast_true(v->value);
16965 } else if (!strcasecmp(v->name, "canpark")) {
16966 confp->chan.canpark = ast_true(v->value);
16967 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16968 confp->chan.echocanbridged = ast_true(v->value);
16969 } else if (!strcasecmp(v->name, "busydetect")) {
16970 confp->chan.busydetect = ast_true(v->value);
16971 } else if (!strcasecmp(v->name, "busycount")) {
16972 confp->chan.busycount = atoi(v->value);
16973 } else if (!strcasecmp(v->name, "busypattern")) {
16974 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16975 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16976 }
16977 } else if (!strcasecmp(v->name, "callprogress")) {
16978 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16979 if (ast_true(v->value))
16980 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16981 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16982 confp->chan.waitfordialtone = atoi(v->value);
16983 } else if (!strcasecmp(v->name, "faxdetect")) {
16984 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16985 if (!strcasecmp(v->value, "incoming")) {
16986 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16987 } else if (!strcasecmp(v->value, "outgoing")) {
16988 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16989 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16990 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16991 } else if (!strcasecmp(v->name, "echocancel")) {
16992 process_echocancel(confp, v->value, v->lineno);
16993 } else if (!strcasecmp(v->name, "echotraining")) {
16994 if (sscanf(v->value, "%30d", &y) == 1) {
16995 if ((y < 10) || (y > 4000)) {
16996 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16997 } else {
16998 confp->chan.echotraining = y;
16999 }
17000 } else if (ast_true(v->value)) {
17001 confp->chan.echotraining = 400;
17002 } else
17003 confp->chan.echotraining = 0;
17004 } else if (!strcasecmp(v->name, "hidecallerid")) {
17005 confp->chan.hidecallerid = ast_true(v->value);
17006 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17007 confp->chan.hidecalleridname = ast_true(v->value);
17008 } else if (!strcasecmp(v->name, "pulsedial")) {
17009 confp->chan.pulse = ast_true(v->value);
17010 } else if (!strcasecmp(v->name, "callreturn")) {
17011 confp->chan.callreturn = ast_true(v->value);
17012 } else if (!strcasecmp(v->name, "callwaiting")) {
17013 confp->chan.callwaiting = ast_true(v->value);
17014 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17015 confp->chan.callwaitingcallerid = ast_true(v->value);
17016 } else if (!strcasecmp(v->name, "context")) {
17017 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17018 } else if (!strcasecmp(v->name, "language")) {
17019 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17020 } else if (!strcasecmp(v->name, "progzone")) {
17021 ast_copy_string(progzone, v->value, sizeof(progzone));
17022 } else if (!strcasecmp(v->name, "mohinterpret")
17023 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17024 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17025 } else if (!strcasecmp(v->name, "mohsuggest")) {
17026 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17027 } else if (!strcasecmp(v->name, "parkinglot")) {
17028 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17029 } else if (!strcasecmp(v->name, "stripmsd")) {
17030 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17031 confp->chan.stripmsd = atoi(v->value);
17032 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17033 numbufs = atoi(v->value);
17034 } else if (!strcasecmp(v->name, "group")) {
17035 confp->chan.group = ast_get_group(v->value);
17036 } else if (!strcasecmp(v->name, "callgroup")) {
17037 if (!strcasecmp(v->value, "none"))
17038 confp->chan.callgroup = 0;
17039 else
17040 confp->chan.callgroup = ast_get_group(v->value);
17041 } else if (!strcasecmp(v->name, "pickupgroup")) {
17042 if (!strcasecmp(v->value, "none"))
17043 confp->chan.pickupgroup = 0;
17044 else
17045 confp->chan.pickupgroup = ast_get_group(v->value);
17046 } else if (!strcasecmp(v->name, "setvar")) {
17047 char *varname = ast_strdupa(v->value), *varval = NULL;
17048 struct ast_variable *tmpvar;
17049 if (varname && (varval = strchr(varname, '='))) {
17050 *varval++ = '\0';
17051 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17052 tmpvar->next = confp->chan.vars;
17053 confp->chan.vars = tmpvar;
17054 }
17055 }
17056 } else if (!strcasecmp(v->name, "immediate")) {
17057 confp->chan.immediate = ast_true(v->value);
17058 } else if (!strcasecmp(v->name, "transfertobusy")) {
17059 confp->chan.transfertobusy = ast_true(v->value);
17060 } else if (!strcasecmp(v->name, "mwimonitor")) {
17061 confp->chan.mwimonitor_neon = 0;
17062 confp->chan.mwimonitor_fsk = 0;
17063 confp->chan.mwimonitor_rpas = 0;
17064 if (strcasestr(v->value, "fsk")) {
17065 confp->chan.mwimonitor_fsk = 1;
17066 }
17067 if (strcasestr(v->value, "rpas")) {
17068 confp->chan.mwimonitor_rpas = 1;
17069 }
17070 if (strcasestr(v->value, "neon")) {
17071 confp->chan.mwimonitor_neon = 1;
17072 }
17073
17074 if (ast_true(v->value)) {
17075 confp->chan.mwimonitor_fsk = 1;
17076 }
17077 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17078 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17079 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17080 }
17081 } else if (!strcasecmp(v->name, "rxgain")) {
17082 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17083 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17084 }
17085 } else if (!strcasecmp(v->name, "txgain")) {
17086 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17087 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17088 }
17089 } else if (!strcasecmp(v->name, "txdrc")) {
17090 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17091 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17092 }
17093 } else if (!strcasecmp(v->name, "rxdrc")) {
17094 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17095 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17096 }
17097 } else if (!strcasecmp(v->name, "tonezone")) {
17098 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17099 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17100 }
17101 } else if (!strcasecmp(v->name, "callerid")) {
17102 if (!strcasecmp(v->value, "asreceived")) {
17103 confp->chan.cid_num[0] = '\0';
17104 confp->chan.cid_name[0] = '\0';
17105 } else {
17106 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17107 }
17108 } else if (!strcasecmp(v->name, "fullname")) {
17109 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17110 } else if (!strcasecmp(v->name, "cid_number")) {
17111 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17112 } else if (!strcasecmp(v->name, "cid_tag")) {
17113 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17114 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17115 confp->chan.dahditrcallerid = ast_true(v->value);
17116 } else if (!strcasecmp(v->name, "restrictcid")) {
17117 confp->chan.restrictcid = ast_true(v->value);
17118 } else if (!strcasecmp(v->name, "usecallingpres")) {
17119 confp->chan.use_callingpres = ast_true(v->value);
17120 } else if (!strcasecmp(v->name, "accountcode")) {
17121 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17122 } else if (!strcasecmp(v->name, "amaflags")) {
17123 y = ast_cdr_amaflags2int(v->value);
17124 if (y < 0)
17125 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17126 else
17127 confp->chan.amaflags = y;
17128 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17129 confp->chan.polarityonanswerdelay = atoi(v->value);
17130 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17131 confp->chan.answeronpolarityswitch = ast_true(v->value);
17132 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17133 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17134 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17135 confp->chan.sendcalleridafter = atoi(v->value);
17136 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17137 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17138 } else if (ast_cc_is_config_param(v->name)) {
17139 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17140 } else if (!strcasecmp(v->name, "mwisendtype")) {
17141 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17142 if (!strcasecmp(v->value, "rpas")) {
17143 mwisend_rpas = 1;
17144 } else {
17145 mwisend_rpas = 0;
17146 }
17147 #else
17148
17149 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17150 if (strcasestr(v->value, "nofsk")) {
17151 confp->chan.mwisend_fsk = 0;
17152 } else {
17153 confp->chan.mwisend_fsk = 1;
17154 }
17155 if (strcasestr(v->value, "rpas")) {
17156 confp->chan.mwisend_rpas = 1;
17157 } else {
17158 confp->chan.mwisend_rpas = 0;
17159 }
17160 if (strcasestr(v->value, "lrev")) {
17161 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17162 }
17163 if (strcasestr(v->value, "hvdc")) {
17164 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17165 }
17166 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17167 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17168 }
17169 #endif
17170 } else if (reload != 1) {
17171 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17172 int orig_radio = confp->chan.radio;
17173 int orig_outsigmod = confp->chan.outsigmod;
17174 int orig_auto = confp->is_sig_auto;
17175
17176 confp->chan.radio = 0;
17177 confp->chan.outsigmod = -1;
17178 confp->is_sig_auto = 0;
17179 if (!strcasecmp(v->value, "em")) {
17180 confp->chan.sig = SIG_EM;
17181 } else if (!strcasecmp(v->value, "em_e1")) {
17182 confp->chan.sig = SIG_EM_E1;
17183 } else if (!strcasecmp(v->value, "em_w")) {
17184 confp->chan.sig = SIG_EMWINK;
17185 } else if (!strcasecmp(v->value, "fxs_ls")) {
17186 confp->chan.sig = SIG_FXSLS;
17187 } else if (!strcasecmp(v->value, "fxs_gs")) {
17188 confp->chan.sig = SIG_FXSGS;
17189 } else if (!strcasecmp(v->value, "fxs_ks")) {
17190 confp->chan.sig = SIG_FXSKS;
17191 } else if (!strcasecmp(v->value, "fxo_ls")) {
17192 confp->chan.sig = SIG_FXOLS;
17193 } else if (!strcasecmp(v->value, "fxo_gs")) {
17194 confp->chan.sig = SIG_FXOGS;
17195 } else if (!strcasecmp(v->value, "fxo_ks")) {
17196 confp->chan.sig = SIG_FXOKS;
17197 } else if (!strcasecmp(v->value, "fxs_rx")) {
17198 confp->chan.sig = SIG_FXSKS;
17199 confp->chan.radio = 1;
17200 } else if (!strcasecmp(v->value, "fxo_rx")) {
17201 confp->chan.sig = SIG_FXOLS;
17202 confp->chan.radio = 1;
17203 } else if (!strcasecmp(v->value, "fxs_tx")) {
17204 confp->chan.sig = SIG_FXSLS;
17205 confp->chan.radio = 1;
17206 } else if (!strcasecmp(v->value, "fxo_tx")) {
17207 confp->chan.sig = SIG_FXOGS;
17208 confp->chan.radio = 1;
17209 } else if (!strcasecmp(v->value, "em_rx")) {
17210 confp->chan.sig = SIG_EM;
17211 confp->chan.radio = 1;
17212 } else if (!strcasecmp(v->value, "em_tx")) {
17213 confp->chan.sig = SIG_EM;
17214 confp->chan.radio = 1;
17215 } else if (!strcasecmp(v->value, "em_rxtx")) {
17216 confp->chan.sig = SIG_EM;
17217 confp->chan.radio = 2;
17218 } else if (!strcasecmp(v->value, "em_txrx")) {
17219 confp->chan.sig = SIG_EM;
17220 confp->chan.radio = 2;
17221 } else if (!strcasecmp(v->value, "sf")) {
17222 confp->chan.sig = SIG_SF;
17223 } else if (!strcasecmp(v->value, "sf_w")) {
17224 confp->chan.sig = SIG_SFWINK;
17225 } else if (!strcasecmp(v->value, "sf_featd")) {
17226 confp->chan.sig = SIG_FEATD;
17227 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17228 confp->chan.sig = SIG_FEATDMF;
17229 } else if (!strcasecmp(v->value, "sf_featb")) {
17230 confp->chan.sig = SIG_SF_FEATB;
17231 } else if (!strcasecmp(v->value, "sf")) {
17232 confp->chan.sig = SIG_SF;
17233 } else if (!strcasecmp(v->value, "sf_rx")) {
17234 confp->chan.sig = SIG_SF;
17235 confp->chan.radio = 1;
17236 } else if (!strcasecmp(v->value, "sf_tx")) {
17237 confp->chan.sig = SIG_SF;
17238 confp->chan.radio = 1;
17239 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17240 confp->chan.sig = SIG_SF;
17241 confp->chan.radio = 2;
17242 } else if (!strcasecmp(v->value, "sf_txrx")) {
17243 confp->chan.sig = SIG_SF;
17244 confp->chan.radio = 2;
17245 } else if (!strcasecmp(v->value, "featd")) {
17246 confp->chan.sig = SIG_FEATD;
17247 } else if (!strcasecmp(v->value, "featdmf")) {
17248 confp->chan.sig = SIG_FEATDMF;
17249 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17250 confp->chan.sig = SIG_FEATDMF_TA;
17251 } else if (!strcasecmp(v->value, "e911")) {
17252 confp->chan.sig = SIG_E911;
17253 } else if (!strcasecmp(v->value, "fgccama")) {
17254 confp->chan.sig = SIG_FGC_CAMA;
17255 } else if (!strcasecmp(v->value, "fgccamamf")) {
17256 confp->chan.sig = SIG_FGC_CAMAMF;
17257 } else if (!strcasecmp(v->value, "featb")) {
17258 confp->chan.sig = SIG_FEATB;
17259 #ifdef HAVE_PRI
17260 } else if (!strcasecmp(v->value, "pri_net")) {
17261 confp->chan.sig = SIG_PRI;
17262 confp->pri.pri.nodetype = PRI_NETWORK;
17263 } else if (!strcasecmp(v->value, "pri_cpe")) {
17264 confp->chan.sig = SIG_PRI;
17265 confp->pri.pri.nodetype = PRI_CPE;
17266 } else if (!strcasecmp(v->value, "bri_cpe")) {
17267 confp->chan.sig = SIG_BRI;
17268 confp->pri.pri.nodetype = PRI_CPE;
17269 } else if (!strcasecmp(v->value, "bri_net")) {
17270 confp->chan.sig = SIG_BRI;
17271 confp->pri.pri.nodetype = PRI_NETWORK;
17272 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17273 confp->chan.sig = SIG_BRI_PTMP;
17274 confp->pri.pri.nodetype = PRI_CPE;
17275 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17276 #if defined(HAVE_PRI_CALL_HOLD)
17277 confp->chan.sig = SIG_BRI_PTMP;
17278 confp->pri.pri.nodetype = PRI_NETWORK;
17279 #else
17280 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17281 #endif
17282 #endif
17283 #if defined(HAVE_SS7)
17284 } else if (!strcasecmp(v->value, "ss7")) {
17285 confp->chan.sig = SIG_SS7;
17286 #endif
17287 #ifdef HAVE_OPENR2
17288 } else if (!strcasecmp(v->value, "mfcr2")) {
17289 confp->chan.sig = SIG_MFCR2;
17290 #endif
17291 } else if (!strcasecmp(v->value, "auto")) {
17292 confp->is_sig_auto = 1;
17293 } else {
17294 confp->chan.outsigmod = orig_outsigmod;
17295 confp->chan.radio = orig_radio;
17296 confp->is_sig_auto = orig_auto;
17297 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17298 }
17299 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17300 if (!strcasecmp(v->value, "em")) {
17301 confp->chan.outsigmod = SIG_EM;
17302 } else if (!strcasecmp(v->value, "em_e1")) {
17303 confp->chan.outsigmod = SIG_EM_E1;
17304 } else if (!strcasecmp(v->value, "em_w")) {
17305 confp->chan.outsigmod = SIG_EMWINK;
17306 } else if (!strcasecmp(v->value, "sf")) {
17307 confp->chan.outsigmod = SIG_SF;
17308 } else if (!strcasecmp(v->value, "sf_w")) {
17309 confp->chan.outsigmod = SIG_SFWINK;
17310 } else if (!strcasecmp(v->value, "sf_featd")) {
17311 confp->chan.outsigmod = SIG_FEATD;
17312 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17313 confp->chan.outsigmod = SIG_FEATDMF;
17314 } else if (!strcasecmp(v->value, "sf_featb")) {
17315 confp->chan.outsigmod = SIG_SF_FEATB;
17316 } else if (!strcasecmp(v->value, "sf")) {
17317 confp->chan.outsigmod = SIG_SF;
17318 } else if (!strcasecmp(v->value, "featd")) {
17319 confp->chan.outsigmod = SIG_FEATD;
17320 } else if (!strcasecmp(v->value, "featdmf")) {
17321 confp->chan.outsigmod = SIG_FEATDMF;
17322 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17323 confp->chan.outsigmod = SIG_FEATDMF_TA;
17324 } else if (!strcasecmp(v->value, "e911")) {
17325 confp->chan.outsigmod = SIG_E911;
17326 } else if (!strcasecmp(v->value, "fgccama")) {
17327 confp->chan.outsigmod = SIG_FGC_CAMA;
17328 } else if (!strcasecmp(v->value, "fgccamamf")) {
17329 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17330 } else if (!strcasecmp(v->value, "featb")) {
17331 confp->chan.outsigmod = SIG_FEATB;
17332 } else {
17333 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17334 }
17335 #ifdef HAVE_PRI
17336 } else if (!strcasecmp(v->name, "pridialplan")) {
17337 if (!strcasecmp(v->value, "national")) {
17338 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17339 } else if (!strcasecmp(v->value, "unknown")) {
17340 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17341 } else if (!strcasecmp(v->value, "private")) {
17342 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17343 } else if (!strcasecmp(v->value, "international")) {
17344 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17345 } else if (!strcasecmp(v->value, "local")) {
17346 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17347 } else if (!strcasecmp(v->value, "dynamic")) {
17348 confp->pri.pri.dialplan = -1;
17349 } else if (!strcasecmp(v->value, "redundant")) {
17350 confp->pri.pri.dialplan = -2;
17351 } else {
17352 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17353 }
17354 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17355 if (!strcasecmp(v->value, "national")) {
17356 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17357 } else if (!strcasecmp(v->value, "unknown")) {
17358 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17359 } else if (!strcasecmp(v->value, "private")) {
17360 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17361 } else if (!strcasecmp(v->value, "international")) {
17362 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17363 } else if (!strcasecmp(v->value, "local")) {
17364 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17365 } else if (!strcasecmp(v->value, "dynamic")) {
17366 confp->pri.pri.localdialplan = -1;
17367 } else if (!strcasecmp(v->value, "redundant")) {
17368 confp->pri.pri.localdialplan = -2;
17369 } else {
17370 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17371 }
17372 } else if (!strcasecmp(v->name, "switchtype")) {
17373 if (!strcasecmp(v->value, "national"))
17374 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17375 else if (!strcasecmp(v->value, "ni1"))
17376 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17377 else if (!strcasecmp(v->value, "dms100"))
17378 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17379 else if (!strcasecmp(v->value, "4ess"))
17380 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17381 else if (!strcasecmp(v->value, "5ess"))
17382 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17383 else if (!strcasecmp(v->value, "euroisdn"))
17384 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17385 else if (!strcasecmp(v->value, "qsig"))
17386 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17387 else {
17388 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17389 return -1;
17390 }
17391 } else if (!strcasecmp(v->name, "msn")) {
17392 ast_copy_string(confp->pri.pri.msn_list, v->value,
17393 sizeof(confp->pri.pri.msn_list));
17394 } else if (!strcasecmp(v->name, "nsf")) {
17395 if (!strcasecmp(v->value, "sdn"))
17396 confp->pri.pri.nsf = PRI_NSF_SDN;
17397 else if (!strcasecmp(v->value, "megacom"))
17398 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17399 else if (!strcasecmp(v->value, "tollfreemegacom"))
17400 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17401 else if (!strcasecmp(v->value, "accunet"))
17402 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17403 else if (!strcasecmp(v->value, "none"))
17404 confp->pri.pri.nsf = PRI_NSF_NONE;
17405 else {
17406 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17407 confp->pri.pri.nsf = PRI_NSF_NONE;
17408 }
17409 } else if (!strcasecmp(v->name, "priindication")) {
17410 if (!strcasecmp(v->value, "outofband"))
17411 confp->chan.priindication_oob = 1;
17412 else if (!strcasecmp(v->value, "inband"))
17413 confp->chan.priindication_oob = 0;
17414 else
17415 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17416 v->value, v->lineno);
17417 } else if (!strcasecmp(v->name, "priexclusive")) {
17418 confp->chan.priexclusive = ast_true(v->value);
17419 } else if (!strcasecmp(v->name, "internationalprefix")) {
17420 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17421 } else if (!strcasecmp(v->name, "nationalprefix")) {
17422 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17423 } else if (!strcasecmp(v->name, "localprefix")) {
17424 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17425 } else if (!strcasecmp(v->name, "privateprefix")) {
17426 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17427 } else if (!strcasecmp(v->name, "unknownprefix")) {
17428 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17429 } else if (!strcasecmp(v->name, "resetinterval")) {
17430 if (!strcasecmp(v->value, "never"))
17431 confp->pri.pri.resetinterval = -1;
17432 else if (atoi(v->value) >= 60)
17433 confp->pri.pri.resetinterval = atoi(v->value);
17434 else
17435 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17436 v->value, v->lineno);
17437 } else if (!strcasecmp(v->name, "minunused")) {
17438 confp->pri.pri.minunused = atoi(v->value);
17439 } else if (!strcasecmp(v->name, "minidle")) {
17440 confp->pri.pri.minidle = atoi(v->value);
17441 } else if (!strcasecmp(v->name, "idleext")) {
17442 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17443 } else if (!strcasecmp(v->name, "idledial")) {
17444 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17445 } else if (!strcasecmp(v->name, "overlapdial")) {
17446 if (ast_true(v->value)) {
17447 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17448 } else if (!strcasecmp(v->value, "incoming")) {
17449 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17450 } else if (!strcasecmp(v->value, "outgoing")) {
17451 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17452 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17453 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17454 } else {
17455 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17456 }
17457 #ifdef HAVE_PRI_PROG_W_CAUSE
17458 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17459 if (!strcasecmp(v->value, "logical")) {
17460 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17461 } else if (!strcasecmp(v->value, "physical")) {
17462 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17463 } else {
17464 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17465 }
17466 #endif
17467 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17468 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17469 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17470 } else if (!strcasecmp(v->name, "service_message_support")) {
17471
17472 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17473 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17474 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17475 confp->pri.pri.enable_service_message_support = 1;
17476 } else {
17477 confp->pri.pri.enable_service_message_support = 0;
17478 }
17479 #endif
17480 #ifdef HAVE_PRI_INBANDDISCONNECT
17481 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17482 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17483 #endif
17484 } else if (!strcasecmp(v->name, "pritimer")) {
17485 #ifdef PRI_GETSET_TIMERS
17486 char tmp[20];
17487 char *timerc;
17488 char *c;
17489 int timer;
17490 int timeridx;
17491
17492 ast_copy_string(tmp, v->value, sizeof(tmp));
17493 c = tmp;
17494 timerc = strsep(&c, ",");
17495 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17496 timeridx = pri_timer2idx(timerc);
17497 timer = atoi(c);
17498 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17499 ast_log(LOG_WARNING,
17500 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17501 v->lineno);
17502 } else if (!timer) {
17503 ast_log(LOG_WARNING,
17504 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17505 c, timerc, v->lineno);
17506 } else {
17507 confp->pri.pri.pritimers[timeridx] = timer;
17508 }
17509 } else {
17510 ast_log(LOG_WARNING,
17511 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17512 v->value, v->lineno);
17513 }
17514 #endif
17515 } else if (!strcasecmp(v->name, "facilityenable")) {
17516 confp->pri.pri.facilityenable = ast_true(v->value);
17517 #if defined(HAVE_PRI_AOC_EVENTS)
17518 } else if (!strcasecmp(v->name, "aoc_enable")) {
17519 confp->pri.pri.aoc_passthrough_flag = 0;
17520 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17521 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17522 }
17523 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17524 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17525 }
17526 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17527 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17528 }
17529 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17530 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17531 #endif
17532 #if defined(HAVE_PRI_CALL_HOLD)
17533 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17534 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17535 #endif
17536 #if defined(HAVE_PRI_CCSS)
17537 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17538 if (!strcasecmp(v->value, "global")) {
17539 confp->pri.pri.cc_ptmp_recall_mode = 0;
17540 } else if (!strcasecmp(v->value, "specific")) {
17541 confp->pri.pri.cc_ptmp_recall_mode = 1;
17542 } else {
17543 confp->pri.pri.cc_ptmp_recall_mode = 1;
17544 }
17545 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17546 if (!strcasecmp(v->value, "release")) {
17547 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17548 } else if (!strcasecmp(v->value, "retain")) {
17549 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17550 } else if (!strcasecmp(v->value, "do_not_care")) {
17551 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17552 } else {
17553 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17554 }
17555 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17556 if (!strcasecmp(v->value, "release")) {
17557 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17558 } else if (!strcasecmp(v->value, "retain")) {
17559 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17560 } else {
17561 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17562 }
17563 #endif
17564 #if defined(HAVE_PRI_CALL_WAITING)
17565 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17566 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17567 if (confp->pri.pri.max_call_waiting_calls < 0) {
17568
17569 confp->pri.pri.max_call_waiting_calls = 0;
17570 }
17571 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17572 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17573 #endif
17574 #if defined(HAVE_PRI_MWI)
17575 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17576 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17577 sizeof(confp->pri.pri.mwi_mailboxes));
17578 #endif
17579 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17580 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17581 #if defined(HAVE_PRI_L2_PERSISTENCE)
17582 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17583 if (!strcasecmp(v->value, "keep_up")) {
17584 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17585 } else if (!strcasecmp(v->value, "leave_down")) {
17586 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17587 } else {
17588 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17589 }
17590 #endif
17591 #endif
17592 #if defined(HAVE_SS7)
17593 } else if (!strcasecmp(v->name, "ss7type")) {
17594 if (!strcasecmp(v->value, "itu")) {
17595 cur_ss7type = SS7_ITU;
17596 } else if (!strcasecmp(v->value, "ansi")) {
17597 cur_ss7type = SS7_ANSI;
17598 } else
17599 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17600 } else if (!strcasecmp(v->name, "linkset")) {
17601 cur_linkset = atoi(v->value);
17602 } else if (!strcasecmp(v->name, "pointcode")) {
17603 cur_pointcode = parse_pointcode(v->value);
17604 } else if (!strcasecmp(v->name, "adjpointcode")) {
17605 cur_adjpointcode = parse_pointcode(v->value);
17606 } else if (!strcasecmp(v->name, "defaultdpc")) {
17607 cur_defaultdpc = parse_pointcode(v->value);
17608 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17609 cur_cicbeginswith = atoi(v->value);
17610 } else if (!strcasecmp(v->name, "networkindicator")) {
17611 if (!strcasecmp(v->value, "national"))
17612 cur_networkindicator = SS7_NI_NAT;
17613 else if (!strcasecmp(v->value, "national_spare"))
17614 cur_networkindicator = SS7_NI_NAT_SPARE;
17615 else if (!strcasecmp(v->value, "international"))
17616 cur_networkindicator = SS7_NI_INT;
17617 else if (!strcasecmp(v->value, "international_spare"))
17618 cur_networkindicator = SS7_NI_INT_SPARE;
17619 else
17620 cur_networkindicator = -1;
17621 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17622 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17623 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17624 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17625 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17626 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17627 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17628 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17629 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17630 if (!strcasecmp(v->value, "national")) {
17631 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17632 } else if (!strcasecmp(v->value, "international")) {
17633 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17634 } else if (!strcasecmp(v->value, "subscriber")) {
17635 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17636 } else if (!strcasecmp(v->value, "unknown")) {
17637 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17638 } else if (!strcasecmp(v->value, "dynamic")) {
17639 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17640 } else {
17641 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17642 }
17643 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17644 if (!strcasecmp(v->value, "national")) {
17645 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17646 } else if (!strcasecmp(v->value, "international")) {
17647 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17648 } else if (!strcasecmp(v->value, "subscriber")) {
17649 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17650 } else if (!strcasecmp(v->value, "unknown")) {
17651 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17652 } else if (!strcasecmp(v->value, "dynamic")) {
17653 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17654 } else {
17655 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17656 }
17657 } else if (!strcasecmp(v->name, "sigchan")) {
17658 int sigchan, res;
17659 sigchan = atoi(v->value);
17660 res = linkset_addsigchan(sigchan);
17661 if (res < 0)
17662 return -1;
17663
17664 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17665 struct dahdi_ss7 *link;
17666 link = ss7_resolve_linkset(cur_linkset);
17667 if (!link) {
17668 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17669 return -1;
17670 }
17671 if (ast_true(v->value))
17672 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17673 #endif
17674 #ifdef HAVE_OPENR2
17675 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17676 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17677 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);
17678 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17679 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17680 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17681 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17682 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17683 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17684 confp->mfcr2.variant = OR2_VAR_ITU;
17685 }
17686 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17687 confp->mfcr2.mfback_timeout = atoi(v->value);
17688 if (!confp->mfcr2.mfback_timeout) {
17689 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17690 confp->mfcr2.mfback_timeout = -1;
17691 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17692 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17693 }
17694 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17695 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17696 if (confp->mfcr2.metering_pulse_timeout > 500) {
17697 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17698 }
17699 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17700 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17701 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17702 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17703 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17704 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17705 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17706 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17707 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17708 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17709 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17710 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17711 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17712 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17713 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17714 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17715 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17716 #endif
17717 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17718 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17719 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17720 confp->mfcr2.max_ani = atoi(v->value);
17721 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17722 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17723 }
17724 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17725 confp->mfcr2.max_dnis = atoi(v->value);
17726 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17727 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17728 }
17729 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17730 confp->mfcr2.category = openr2_proto_get_category(v->value);
17731 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17732 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17733 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17734 v->value, v->lineno);
17735 }
17736 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17737 openr2_log_level_t tmplevel;
17738 char *clevel;
17739 char *logval = ast_strdupa(v->value);
17740 while (logval) {
17741 clevel = strsep(&logval,",");
17742 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17743 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17744 continue;
17745 }
17746 confp->mfcr2.loglevel |= tmplevel;
17747 }
17748 #endif
17749 } else if (!strcasecmp(v->name, "cadence")) {
17750
17751 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17752 int i;
17753 struct dahdi_ring_cadence new_cadence;
17754 int cid_location = -1;
17755 int firstcadencepos = 0;
17756 char original_args[80];
17757 int cadence_is_ok = 1;
17758
17759 ast_copy_string(original_args, v->value, sizeof(original_args));
17760
17761 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]);
17762
17763
17764 if (element_count % 2 == 1) {
17765 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17766 cadence_is_ok = 0;
17767 }
17768
17769
17770 for (i = 0; i < element_count; i++) {
17771 if (c[i] == 0) {
17772 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17773 cadence_is_ok = 0;
17774 break;
17775 } else if (c[i] < 0) {
17776 if (i % 2 == 1) {
17777
17778 if (cid_location == -1) {
17779 cid_location = i;
17780 c[i] *= -1;
17781 } else {
17782 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17783 cadence_is_ok = 0;
17784 break;
17785 }
17786 } else {
17787 if (firstcadencepos == 0) {
17788 firstcadencepos = i;
17789
17790 } else {
17791 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17792 cadence_is_ok = 0;
17793 break;
17794 }
17795 }
17796 }
17797 }
17798
17799
17800 for (i = 0; i < 16; i++) {
17801 new_cadence.ringcadence[i] = c[i];
17802 }
17803
17804 if (cadence_is_ok) {
17805
17806 if (element_count < 2) {
17807 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17808 } else {
17809 if (cid_location == -1) {
17810
17811 cid_location = 1;
17812 } else {
17813
17814 cid_location = (cid_location + 1) / 2;
17815 }
17816
17817 if (!user_has_defined_cadences++)
17818
17819 num_cadence = 0;
17820 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17821 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17822 else {
17823 cadences[num_cadence] = new_cadence;
17824 cidrings[num_cadence++] = cid_location;
17825 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17826 }
17827 }
17828 }
17829 } else if (!strcasecmp(v->name, "ringtimeout")) {
17830 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17831 } else if (!strcasecmp(v->name, "prewink")) {
17832 confp->timing.prewinktime = atoi(v->value);
17833 } else if (!strcasecmp(v->name, "preflash")) {
17834 confp->timing.preflashtime = atoi(v->value);
17835 } else if (!strcasecmp(v->name, "wink")) {
17836 confp->timing.winktime = atoi(v->value);
17837 } else if (!strcasecmp(v->name, "flash")) {
17838 confp->timing.flashtime = atoi(v->value);
17839 } else if (!strcasecmp(v->name, "start")) {
17840 confp->timing.starttime = atoi(v->value);
17841 } else if (!strcasecmp(v->name, "rxwink")) {
17842 confp->timing.rxwinktime = atoi(v->value);
17843 } else if (!strcasecmp(v->name, "rxflash")) {
17844 confp->timing.rxflashtime = atoi(v->value);
17845 } else if (!strcasecmp(v->name, "debounce")) {
17846 confp->timing.debouncetime = atoi(v->value);
17847 } else if (!strcasecmp(v->name, "toneduration")) {
17848 int toneduration;
17849 int ctlfd;
17850 int res;
17851 struct dahdi_dialparams dps;
17852
17853 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17854 if (ctlfd == -1) {
17855 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17856 return -1;
17857 }
17858
17859 toneduration = atoi(v->value);
17860 if (toneduration > -1) {
17861 memset(&dps, 0, sizeof(dps));
17862
17863 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17864 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17865 if (res < 0) {
17866 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17867 close(ctlfd);
17868 return -1;
17869 }
17870 }
17871 close(ctlfd);
17872 } else if (!strcasecmp(v->name, "defaultcic")) {
17873 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17874 } else if (!strcasecmp(v->name, "defaultozz")) {
17875 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17876 } else if (!strcasecmp(v->name, "mwilevel")) {
17877 mwilevel = atoi(v->value);
17878 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17879 dtmfcid_level = atoi(v->value);
17880 } else if (!strcasecmp(v->name, "reportalarms")) {
17881 if (!strcasecmp(v->value, "all"))
17882 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17883 if (!strcasecmp(v->value, "none"))
17884 report_alarms = 0;
17885 else if (!strcasecmp(v->value, "channels"))
17886 report_alarms = REPORT_CHANNEL_ALARMS;
17887 else if (!strcasecmp(v->value, "spans"))
17888 report_alarms = REPORT_SPAN_ALARMS;
17889 }
17890 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17891 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17892 }
17893
17894
17895 if (confp->chan.vars) {
17896 ast_variables_destroy(confp->chan.vars);
17897 confp->chan.vars = NULL;
17898 }
17899
17900 if (dahdichan) {
17901
17902 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17903 &found_pseudo)) {
17904 if (confp->ignore_failed_channels) {
17905 ast_log(LOG_WARNING,
17906 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17907 dahdichan->value);
17908 } else {
17909 return -1;
17910 }
17911 }
17912 }
17913
17914
17915 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17916 if (!tmp->destroy && tmp->span != y) {
17917 tmp->manages_span_alarms = 1;
17918 y = tmp->span;
17919 } else {
17920 tmp->manages_span_alarms = 0;
17921 }
17922 }
17923
17924
17925
17926 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17927
17928
17929
17930
17931 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17932
17933 if (conf.chan.cc_params) {
17934 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17935 } else {
17936 tmp = NULL;
17937 }
17938 if (tmp) {
17939 ast_verb(3, "Automatically generated pseudo channel\n");
17940 } else {
17941 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17942 }
17943 ast_cc_config_params_destroy(conf.chan.cc_params);
17944 }
17945 return 0;
17946 }
17947
17948
17949
17950
17951
17952
17953
17954
17955
17956
17957
17958 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17959 {
17960 struct ast_cc_config_params *cc_params;
17961
17962 cc_params = dest->chan.cc_params;
17963 *dest = *src;
17964 dest->chan.cc_params = cc_params;
17965 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17966 }
17967
17968
17969
17970
17971
17972
17973
17974
17975
17976
17977
17978
17979
17980 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17981 {
17982 struct ast_config *cfg;
17983 struct ast_config *ucfg;
17984 struct ast_variable *v;
17985 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17986 const char *chans;
17987 const char *cat;
17988 int res;
17989
17990 #ifdef HAVE_PRI
17991 char *c;
17992 int spanno;
17993 int i;
17994 int logicalspan;
17995 int trunkgroup;
17996 int dchannels[SIG_PRI_NUM_DCHANS];
17997 #endif
17998 int have_cfg_now;
17999 static int had_cfg_before = 1;
18000
18001 cfg = ast_config_load(config, config_flags);
18002 have_cfg_now = !!cfg;
18003 if (!cfg) {
18004
18005 if (had_cfg_before) {
18006 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18007 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18008 }
18009 cfg = ast_config_new();
18010 if (!cfg) {
18011 return 0;
18012 }
18013 ucfg = ast_config_load("users.conf", config_flags);
18014 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18015 ast_config_destroy(cfg);
18016 return 0;
18017 }
18018 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18019 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18020 ast_config_destroy(cfg);
18021 return 0;
18022 }
18023 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18024 ucfg = ast_config_load("users.conf", config_flags);
18025 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18026 return 0;
18027 }
18028 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18029 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18030 return 0;
18031 }
18032 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18033 cfg = ast_config_load(config, config_flags);
18034 have_cfg_now = !!cfg;
18035 if (!cfg) {
18036 if (had_cfg_before) {
18037
18038 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18039 ast_config_destroy(ucfg);
18040 return 0;
18041 }
18042 cfg = ast_config_new();
18043 if (!cfg) {
18044 ast_config_destroy(ucfg);
18045 return 0;
18046 }
18047 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18048 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18049 ast_config_destroy(ucfg);
18050 return 0;
18051 }
18052 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18053 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18054 return 0;
18055 } else {
18056 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18057 ucfg = ast_config_load("users.conf", config_flags);
18058 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18059 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18060 ast_config_destroy(cfg);
18061 return 0;
18062 }
18063 }
18064 had_cfg_before = have_cfg_now;
18065
18066
18067 ast_mutex_lock(&iflock);
18068 #ifdef HAVE_PRI
18069 if (reload != 1) {
18070
18071 v = ast_variable_browse(cfg, "trunkgroups");
18072 while (v) {
18073 if (!strcasecmp(v->name, "trunkgroup")) {
18074 trunkgroup = atoi(v->value);
18075 if (trunkgroup > 0) {
18076 if ((c = strchr(v->value, ','))) {
18077 i = 0;
18078 memset(dchannels, 0, sizeof(dchannels));
18079 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18080 dchannels[i] = atoi(c + 1);
18081 if (dchannels[i] < 0) {
18082 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);
18083 } else
18084 i++;
18085 c = strchr(c + 1, ',');
18086 }
18087 if (i) {
18088 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18089 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);
18090 } else
18091 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");
18092 } else
18093 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18094 } else
18095 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18096 } else
18097 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18098 } else if (!strcasecmp(v->name, "spanmap")) {
18099 spanno = atoi(v->value);
18100 if (spanno > 0) {
18101 if ((c = strchr(v->value, ','))) {
18102 trunkgroup = atoi(c + 1);
18103 if (trunkgroup > 0) {
18104 if ((c = strchr(c + 1, ',')))
18105 logicalspan = atoi(c + 1);
18106 else
18107 logicalspan = 0;
18108 if (logicalspan >= 0) {
18109 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18110 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18111 } else
18112 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18113 } else
18114 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);
18115 } else
18116 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18117 } else
18118 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18119 } else
18120 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18121 } else {
18122 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18123 }
18124 v = v->next;
18125 }
18126 }
18127 #endif
18128
18129
18130 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18131
18132 mwimonitornotify[0] = '\0';
18133
18134 v = ast_variable_browse(cfg, "channels");
18135 if ((res = process_dahdi(base_conf,
18136 "" ,
18137 v, reload, 0))) {
18138 ast_mutex_unlock(&iflock);
18139 ast_config_destroy(cfg);
18140 if (ucfg) {
18141 ast_config_destroy(ucfg);
18142 }
18143 return res;
18144 }
18145
18146
18147 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18148
18149
18150
18151 if (!strcasecmp(cat, "general") ||
18152 !strcasecmp(cat, "trunkgroups") ||
18153 !strcasecmp(cat, "globals") ||
18154 !strcasecmp(cat, "channels")) {
18155 continue;
18156 }
18157
18158 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18159 if (ast_strlen_zero(chans)) {
18160
18161 continue;
18162 }
18163
18164
18165 deep_copy_dahdi_chan_conf(conf, base_conf);
18166
18167 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18168 ast_mutex_unlock(&iflock);
18169 ast_config_destroy(cfg);
18170 if (ucfg) {
18171 ast_config_destroy(ucfg);
18172 }
18173 return res;
18174 }
18175 }
18176
18177 ast_config_destroy(cfg);
18178
18179 if (ucfg) {
18180
18181 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18182 process_dahdi(base_conf,
18183 "" ,
18184 ast_variable_browse(ucfg, "general"), 1, 0);
18185
18186 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18187 if (!strcasecmp(cat, "general")) {
18188 continue;
18189 }
18190
18191 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18192 if (ast_strlen_zero(chans)) {
18193
18194 continue;
18195 }
18196
18197
18198 deep_copy_dahdi_chan_conf(conf, base_conf);
18199
18200 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18201 ast_config_destroy(ucfg);
18202 ast_mutex_unlock(&iflock);
18203 return res;
18204 }
18205 }
18206 ast_config_destroy(ucfg);
18207 }
18208 ast_mutex_unlock(&iflock);
18209
18210 #ifdef HAVE_PRI
18211 if (reload != 1) {
18212 int x;
18213 for (x = 0; x < NUM_SPANS; x++) {
18214 if (pris[x].pri.pvts[0]) {
18215 prepare_pri(pris + x);
18216 if (sig_pri_start_pri(&pris[x].pri)) {
18217 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18218 return -1;
18219 } else
18220 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18221 }
18222 }
18223 }
18224 #endif
18225 #if defined(HAVE_SS7)
18226 if (reload != 1) {
18227 int x;
18228 for (x = 0; x < NUM_SPANS; x++) {
18229 if (linksets[x].ss7.ss7) {
18230 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18231 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18232 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18233 return -1;
18234 } else
18235 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18236 }
18237 }
18238 }
18239 #endif
18240 #ifdef HAVE_OPENR2
18241 if (reload != 1) {
18242 int x;
18243 for (x = 0; x < r2links_count; x++) {
18244 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18245 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18246 return -1;
18247 } else {
18248 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18249 }
18250 }
18251 }
18252 #endif
18253
18254 restart_monitor();
18255 return 0;
18256 }
18257
18258
18259
18260
18261
18262
18263
18264
18265
18266
18267 static int setup_dahdi(int reload)
18268 {
18269 int res;
18270 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18271 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18272 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18273
18274 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18275 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18276 } else {
18277 res = -1;
18278 }
18279 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18280 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18281 ast_cc_config_params_destroy(conf.chan.cc_params);
18282
18283 return res;
18284 }
18285
18286
18287
18288
18289
18290
18291
18292
18293 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18294 struct ast_data *data_root)
18295 {
18296 int ctl, res, span;
18297 struct ast_data *data_span, *data_alarms;
18298 struct dahdi_spaninfo s;
18299
18300 ctl = open("/dev/dahdi/ctl", O_RDWR);
18301 if (ctl < 0) {
18302 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18303 return -1;
18304 }
18305 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18306 s.spanno = span;
18307 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18308 if (res) {
18309 continue;
18310 }
18311
18312 data_span = ast_data_add_node(data_root, "span");
18313 if (!data_span) {
18314 continue;
18315 }
18316 ast_data_add_str(data_span, "description", s.desc);
18317
18318
18319 data_alarms = ast_data_add_node(data_span, "alarms");
18320 if (!data_alarms) {
18321 continue;
18322 }
18323
18324 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18325 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18326 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18327 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18328 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18329 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18330
18331 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18332 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18333 ast_data_add_int(data_span, "crc4", s.crc4count);
18334 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18335 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18336 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18337 "CAS");
18338 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18339 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18340 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18341 "Unknown");
18342 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18343 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18344 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18345 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18346
18347
18348 if (!ast_data_search_match(search, data_span)) {
18349 ast_data_remove_node(data_root, data_span);
18350 }
18351 }
18352 close(ctl);
18353
18354 return 0;
18355 }
18356
18357
18358
18359
18360
18361
18362
18363
18364 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18365 struct ast_data *data_root)
18366 {
18367 struct dahdi_pvt *tmp;
18368 struct ast_data *data_channel;
18369
18370 ast_mutex_lock(&iflock);
18371 for (tmp = iflist; tmp; tmp = tmp->next) {
18372 data_channel = ast_data_add_node(data_root, "channel");
18373 if (!data_channel) {
18374 continue;
18375 }
18376
18377 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18378
18379
18380 if (!ast_data_search_match(search, data_channel)) {
18381 ast_data_remove_node(data_root, data_channel);
18382 }
18383 }
18384 ast_mutex_unlock(&iflock);
18385
18386 return 0;
18387 }
18388
18389
18390
18391
18392
18393
18394
18395
18396 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18397 struct ast_data *data_root)
18398 {
18399 int pseudo_fd = -1;
18400 struct dahdi_versioninfo vi = {
18401 .version = "Unknown",
18402 .echo_canceller = "Unknown"
18403 };
18404
18405 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18406 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18407 return -1;
18408 }
18409
18410 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18411 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18412 }
18413
18414 close(pseudo_fd);
18415
18416 ast_data_add_str(data_root, "value", vi.version);
18417 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18418
18419 return 0;
18420 }
18421
18422 static const struct ast_data_handler dahdi_status_data_provider = {
18423 .version = AST_DATA_HANDLER_VERSION,
18424 .get = dahdi_status_data_provider_get
18425 };
18426
18427 static const struct ast_data_handler dahdi_channels_data_provider = {
18428 .version = AST_DATA_HANDLER_VERSION,
18429 .get = dahdi_channels_data_provider_get
18430 };
18431
18432 static const struct ast_data_handler dahdi_version_data_provider = {
18433 .version = AST_DATA_HANDLER_VERSION,
18434 .get = dahdi_version_data_provider_get
18435 };
18436
18437 static const struct ast_data_entry dahdi_data_providers[] = {
18438 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18439 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18440 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18441 };
18442
18443 static int load_module(void)
18444 {
18445 int res;
18446 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18447 int y;
18448 #endif
18449
18450 #ifdef HAVE_PRI
18451 memset(pris, 0, sizeof(pris));
18452 for (y = 0; y < NUM_SPANS; y++) {
18453 sig_pri_init_pri(&pris[y].pri);
18454 }
18455 pri_set_error(dahdi_pri_error);
18456 pri_set_message(dahdi_pri_message);
18457 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18458 #ifdef HAVE_PRI_PROG_W_CAUSE
18459 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18460 #endif
18461 #if defined(HAVE_PRI_CCSS)
18462 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18463 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18464 __unload_module();
18465 return AST_MODULE_LOAD_FAILURE;
18466 }
18467 #endif
18468 if (sig_pri_load(
18469 #if defined(HAVE_PRI_CCSS)
18470 dahdi_pri_cc_type
18471 #else
18472 NULL
18473 #endif
18474 )) {
18475 __unload_module();
18476 return AST_MODULE_LOAD_FAILURE;
18477 }
18478 #endif
18479 #if defined(HAVE_SS7)
18480 memset(linksets, 0, sizeof(linksets));
18481 for (y = 0; y < NUM_SPANS; y++) {
18482 sig_ss7_init_linkset(&linksets[y].ss7);
18483 }
18484 ss7_set_error(dahdi_ss7_error);
18485 ss7_set_message(dahdi_ss7_message);
18486 #endif
18487 res = setup_dahdi(0);
18488
18489 if (res)
18490 return AST_MODULE_LOAD_DECLINE;
18491 if (ast_channel_register(&dahdi_tech)) {
18492 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18493 __unload_module();
18494 return AST_MODULE_LOAD_FAILURE;
18495 }
18496 #ifdef HAVE_PRI
18497 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18498 #endif
18499 #if defined(HAVE_SS7)
18500 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18501 #endif
18502 #ifdef HAVE_OPENR2
18503 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18504 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18505 #endif
18506
18507 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18508
18509 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18510 memset(round_robin, 0, sizeof(round_robin));
18511 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18512 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18513 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18514 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18515 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18516 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18517 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18518
18519 ast_cond_init(&ss_thread_complete, NULL);
18520
18521 return res;
18522 }
18523
18524 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18525 {
18526 #define END_SILENCE_LEN 400
18527 #define HEADER_MS 50
18528 #define TRAILER_MS 5
18529 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18530 #define ASCII_BYTES_PER_CHAR 80
18531
18532 unsigned char *buf,*mybuf;
18533 struct dahdi_pvt *p = c->tech_pvt;
18534 struct pollfd fds[1];
18535 int size,res,fd,len,x;
18536 int bytes=0;
18537
18538 float cr = 1.0;
18539 float ci = 0.0;
18540 float scont = 0.0;
18541 int idx;
18542
18543 idx = dahdi_get_index(c, p, 0);
18544 if (idx < 0) {
18545 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18546 return -1;
18547 }
18548 if (!text[0]) return(0);
18549 if ((!p->tdd) && (!p->mate)) return(0);
18550 if (p->mate)
18551 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18552 else
18553 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18554 if (!buf)
18555 return -1;
18556 mybuf = buf;
18557 if (p->mate) {
18558 int codec = AST_LAW(p);
18559 for (x = 0; x < HEADER_MS; x++) {
18560 PUT_CLID_MARKMS;
18561 }
18562
18563 for (x = 0; text[x]; x++) {
18564 PUT_CLID(text[x]);
18565 }
18566 for (x = 0; x < TRAILER_MS; x++) {
18567 PUT_CLID_MARKMS;
18568 }
18569 len = bytes;
18570 buf = mybuf;
18571 } else {
18572 len = tdd_generate(p->tdd, buf, text);
18573 if (len < 1) {
18574 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18575 ast_free(mybuf);
18576 return -1;
18577 }
18578 }
18579 memset(buf + len, 0x7f, END_SILENCE_LEN);
18580 len += END_SILENCE_LEN;
18581 fd = p->subs[idx].dfd;
18582 while (len) {
18583 if (ast_check_hangup(c)) {
18584 ast_free(mybuf);
18585 return -1;
18586 }
18587 size = len;
18588 if (size > READ_SIZE)
18589 size = READ_SIZE;
18590 fds[0].fd = fd;
18591 fds[0].events = POLLOUT | POLLPRI;
18592 fds[0].revents = 0;
18593 res = poll(fds, 1, -1);
18594 if (!res) {
18595 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18596 continue;
18597 }
18598
18599 if (fds[0].revents & POLLPRI) {
18600 ast_free(mybuf);
18601 return -1;
18602 }
18603 if (!(fds[0].revents & POLLOUT)) {
18604 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18605 continue;
18606 }
18607 res = write(fd, buf, size);
18608 if (res != size) {
18609 if (res == -1) {
18610 ast_free(mybuf);
18611 return -1;
18612 }
18613 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18614 break;
18615 }
18616 len -= size;
18617 buf += size;
18618 }
18619 ast_free(mybuf);
18620 return(0);
18621 }
18622
18623
18624 static int reload(void)
18625 {
18626 int res = 0;
18627
18628 res = setup_dahdi(1);
18629 if (res) {
18630 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18631 return -1;
18632 }
18633 return 0;
18634 }
18635
18636
18637
18638
18639
18640 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18641 .load = load_module,
18642 .unload = unload_module,
18643 .reload = reload,
18644 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18645 .nonoptreq = "res_smdi",
18646 );