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: 417957 $")
00053
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068
00069
00070
00071
00072
00073
00074 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif
00080
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif
00087
00088 #ifdef HAVE_OPENR2
00089
00090 #define SIG_MFCR2_MAX_CHANNELS 672
00091 #include <openr2.h>
00092 #endif
00093
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 #define SMDI_MD_WAIT_TIMEOUT 1500
00296
00297 static const char * const lbostr[] = {
00298 "0 db (CSU)/0-133 feet (DSX-1)",
00299 "133-266 feet (DSX-1)",
00300 "266-399 feet (DSX-1)",
00301 "399-533 feet (DSX-1)",
00302 "533-655 feet (DSX-1)",
00303 "-7.5db (CSU)",
00304 "-15db (CSU)",
00305 "-22.5db (CSU)"
00306 };
00307
00308
00309
00310 static struct ast_jb_conf default_jbconf =
00311 {
00312 .flags = 0,
00313 .max_size = 200,
00314 .resync_threshold = 1000,
00315 .impl = "fixed",
00316 .target_extra = 40,
00317 };
00318 static struct ast_jb_conf global_jbconf;
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 #define DEFAULT_CIDRINGS 1
00333
00334 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00335
00336
00337
00338 #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))
00339
00340 static const char tdesc[] = "DAHDI Telephony Driver"
00341 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00342 " w/"
00343 #if defined(HAVE_PRI)
00344 "PRI"
00345 #endif
00346 #if defined(HAVE_SS7)
00347 #if defined(HAVE_PRI)
00348 " & "
00349 #endif
00350 "SS7"
00351 #endif
00352 #if defined(HAVE_OPENR2)
00353 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00354 " & "
00355 #endif
00356 "MFC/R2"
00357 #endif
00358 #endif
00359 ;
00360
00361 static const char config[] = "chan_dahdi.conf";
00362
00363 #define SIG_EM DAHDI_SIG_EM
00364 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00365 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00366 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00367 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00368 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00369 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00370 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00371 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00372 #define SIG_FXSLS DAHDI_SIG_FXSLS
00373 #define SIG_FXSGS DAHDI_SIG_FXSGS
00374 #define SIG_FXSKS DAHDI_SIG_FXSKS
00375 #define SIG_FXOLS DAHDI_SIG_FXOLS
00376 #define SIG_FXOGS DAHDI_SIG_FXOGS
00377 #define SIG_FXOKS DAHDI_SIG_FXOKS
00378 #define SIG_PRI DAHDI_SIG_CLEAR
00379 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00380 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00381 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00382 #define SIG_MFCR2 DAHDI_SIG_CAS
00383 #define SIG_SF DAHDI_SIG_SF
00384 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00385 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00386 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00387 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00388 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00389
00390 #ifdef LOTS_OF_SPANS
00391 #define NUM_SPANS DAHDI_MAX_SPANS
00392 #else
00393 #define NUM_SPANS 32
00394 #endif
00395
00396 #define CHAN_PSEUDO -2
00397
00398 #define CALLPROGRESS_PROGRESS 1
00399 #define CALLPROGRESS_FAX_OUTGOING 2
00400 #define CALLPROGRESS_FAX_INCOMING 4
00401 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00402
00403 #define NUM_CADENCE_MAX 25
00404 static int num_cadence = 4;
00405 static int user_has_defined_cadences = 0;
00406
00407 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00408 { { 125, 125, 2000, 4000 } },
00409 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00410 { { 125, 125, 125, 125, 125, 4000 } },
00411 { { 1000, 500, 2500, 5000 } },
00412 };
00413
00414
00415
00416
00417
00418 static int cidrings[NUM_CADENCE_MAX] = {
00419 2,
00420 4,
00421 3,
00422 2,
00423 };
00424
00425
00426 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00427
00428 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00429 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00430
00431 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00432 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00433
00434 static char defaultcic[64] = "";
00435 static char defaultozz[64] = "";
00436
00437
00438 static char mwimonitornotify[PATH_MAX] = "";
00439 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00440 static int mwisend_rpas = 0;
00441 #endif
00442
00443 static char progzone[10] = "";
00444
00445 static int usedistinctiveringdetection = 0;
00446 static int distinctiveringaftercid = 0;
00447
00448 static int numbufs = 4;
00449
00450 static int mwilevel = 512;
00451 static int dtmfcid_level = 256;
00452
00453 #define REPORT_CHANNEL_ALARMS 1
00454 #define REPORT_SPAN_ALARMS 2
00455 static int report_alarms = REPORT_CHANNEL_ALARMS;
00456
00457 #ifdef HAVE_PRI
00458 static int pridebugfd = -1;
00459 static char pridebugfilename[1024] = "";
00460 #endif
00461
00462
00463 static int firstdigittimeout = 16000;
00464
00465
00466 static int gendigittimeout = 8000;
00467
00468
00469 static int matchdigittimeout = 3000;
00470
00471
00472 AST_MUTEX_DEFINE_STATIC(iflock);
00473
00474
00475 static int ifcount = 0;
00476
00477 #ifdef HAVE_PRI
00478 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00479 #endif
00480
00481
00482
00483 AST_MUTEX_DEFINE_STATIC(monlock);
00484
00485
00486
00487 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00488 static ast_cond_t ss_thread_complete;
00489 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00490 AST_MUTEX_DEFINE_STATIC(restart_lock);
00491 static int ss_thread_count = 0;
00492 static int num_restart_pending = 0;
00493
00494 static int restart_monitor(void);
00495
00496 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);
00497
00498 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00499
00500 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00501 {
00502
00503
00504
00505
00506 }
00507
00508
00509 static inline int dahdi_get_event(int fd)
00510 {
00511 int j;
00512 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00513 return -1;
00514 return j;
00515 }
00516
00517
00518 static inline int dahdi_wait_event(int fd)
00519 {
00520 int i, j = 0;
00521 i = DAHDI_IOMUX_SIGEVENT;
00522 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00523 return -1;
00524 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00525 return -1;
00526 return j;
00527 }
00528
00529
00530 #define READ_SIZE 160
00531
00532 #define MASK_AVAIL (1 << 0)
00533 #define MASK_INUSE (1 << 1)
00534
00535 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00536 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00537 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00538 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00539 #define MIN_MS_SINCE_FLASH ((2000) )
00540 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00541 #define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE)
00542
00543 struct dahdi_pvt;
00544
00545
00546
00547
00548
00549 static int ringt_base = DEFAULT_RINGT;
00550
00551 #if defined(HAVE_SS7)
00552
00553 struct dahdi_ss7 {
00554 struct sig_ss7_linkset ss7;
00555 };
00556
00557 static struct dahdi_ss7 linksets[NUM_SPANS];
00558
00559 static int cur_ss7type = -1;
00560 static int cur_linkset = -1;
00561 static int cur_pointcode = -1;
00562 static int cur_cicbeginswith = -1;
00563 static int cur_adjpointcode = -1;
00564 static int cur_networkindicator = -1;
00565 static int cur_defaultdpc = -1;
00566 #endif
00567
00568 #ifdef HAVE_OPENR2
00569 struct dahdi_mfcr2_conf {
00570 openr2_variant_t variant;
00571 int mfback_timeout;
00572 int metering_pulse_timeout;
00573 int max_ani;
00574 int max_dnis;
00575 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00576 int dtmf_time_on;
00577 int dtmf_time_off;
00578 #endif
00579 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
00580 int dtmf_end_timeout;
00581 #endif
00582 signed int get_ani_first:2;
00583 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00584 signed int skip_category_request:2;
00585 #endif
00586 unsigned int call_files:1;
00587 unsigned int allow_collect_calls:1;
00588 unsigned int charge_calls:1;
00589 unsigned int accept_on_offer:1;
00590 unsigned int forced_release:1;
00591 unsigned int double_answer:1;
00592 signed int immediate_accept:2;
00593 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
00594 signed int dtmf_dialing:2;
00595 signed int dtmf_detection:2;
00596 #endif
00597 char logdir[OR2_MAX_PATH];
00598 char r2proto_file[OR2_MAX_PATH];
00599 openr2_log_level_t loglevel;
00600 openr2_calling_party_category_t category;
00601 };
00602
00603
00604 struct dahdi_mfcr2 {
00605 pthread_t r2master;
00606 openr2_context_t *protocol_context;
00607 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00608 int numchans;
00609 struct dahdi_mfcr2_conf conf;
00610 };
00611
00612
00613 static struct dahdi_mfcr2 **r2links;
00614
00615 static int r2links_count = 0;
00616
00617 #endif
00618
00619 #ifdef HAVE_PRI
00620
00621 struct dahdi_pri {
00622 int dchannels[SIG_PRI_NUM_DCHANS];
00623 int mastertrunkgroup;
00624 int prilogicalspan;
00625 struct sig_pri_span pri;
00626 };
00627
00628 static struct dahdi_pri pris[NUM_SPANS];
00629
00630 #if defined(HAVE_PRI_CCSS)
00631
00632 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00633 #endif
00634
00635 #else
00636
00637 struct dahdi_pri;
00638 #endif
00639
00640 #define SUB_REAL 0
00641 #define SUB_CALLWAIT 1
00642 #define SUB_THREEWAY 2
00643
00644
00645 #define POLARITY_IDLE 0
00646 #define POLARITY_REV 1
00647
00648
00649 struct distRingData {
00650 int ring[3];
00651 int range;
00652 };
00653 struct ringContextData {
00654 char contextData[AST_MAX_CONTEXT];
00655 };
00656 struct dahdi_distRings {
00657 struct distRingData ringnum[3];
00658 struct ringContextData ringContext[3];
00659 };
00660
00661 static const char * const subnames[] = {
00662 "Real",
00663 "Callwait",
00664 "Threeway"
00665 };
00666
00667 struct dahdi_subchannel {
00668 int dfd;
00669 struct ast_channel *owner;
00670 int chan;
00671 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00672 struct ast_frame f;
00673 unsigned int needringing:1;
00674 unsigned int needbusy:1;
00675 unsigned int needcongestion:1;
00676 unsigned int needanswer:1;
00677 unsigned int needflash:1;
00678 unsigned int needhold:1;
00679 unsigned int needunhold:1;
00680 unsigned int linear:1;
00681 unsigned int inthreeway:1;
00682 struct dahdi_confinfo curconf;
00683 };
00684
00685 #define CONF_USER_REAL (1 << 0)
00686 #define CONF_USER_THIRDCALL (1 << 1)
00687
00688 #define MAX_SLAVES 4
00689
00690
00691
00692
00693 typedef enum {
00694 MWI_SEND_NULL = 0,
00695 MWI_SEND_SA,
00696 MWI_SEND_SA_WAIT,
00697 MWI_SEND_PAUSE,
00698 MWI_SEND_SPILL,
00699 MWI_SEND_CLEANUP,
00700 MWI_SEND_DONE,
00701 } mwisend_states;
00702
00703 struct mwisend_info {
00704 struct timeval pause;
00705 mwisend_states mwisend_current;
00706 };
00707
00708
00709 enum DAHDI_IFLIST {
00710 DAHDI_IFLIST_NONE,
00711 DAHDI_IFLIST_MAIN,
00712 #if defined(HAVE_PRI)
00713 DAHDI_IFLIST_NO_B_CHAN,
00714 #endif
00715 };
00716
00717 struct dahdi_pvt {
00718 ast_mutex_t lock;
00719 struct callerid_state *cs;
00720 struct ast_channel *owner;
00721
00722
00723 struct dahdi_subchannel sub_unused;
00724 struct dahdi_subchannel subs[3];
00725 struct dahdi_confinfo saveconf;
00726
00727 struct dahdi_pvt *slaves[MAX_SLAVES];
00728 struct dahdi_pvt *master;
00729 int inconference;
00730
00731 int bufsize;
00732 int buf_no;
00733 int buf_policy;
00734 int faxbuf_no;
00735 int faxbuf_policy;
00736 int sig;
00737
00738
00739
00740
00741 int radio;
00742 int outsigmod;
00743 int oprmode;
00744 struct dahdi_pvt *oprpeer;
00745
00746 float cid_rxgain;
00747
00748 float rxgain;
00749
00750 float txgain;
00751
00752 float txdrc;
00753 float rxdrc;
00754
00755 int tonezone;
00756 enum DAHDI_IFLIST which_iflist;
00757 struct dahdi_pvt *next;
00758 struct dahdi_pvt *prev;
00759
00760
00761
00762
00763
00764
00765
00766 unsigned int adsi:1;
00767
00768
00769
00770
00771
00772 unsigned int answeronpolarityswitch:1;
00773
00774
00775
00776
00777
00778 unsigned int busydetect:1;
00779
00780
00781
00782
00783
00784 unsigned int callreturn:1;
00785
00786
00787
00788
00789
00790
00791 unsigned int callwaiting:1;
00792
00793
00794
00795
00796 unsigned int callwaitingcallerid:1;
00797
00798
00799
00800
00801
00802
00803 unsigned int cancallforward:1;
00804
00805
00806
00807
00808 unsigned int canpark:1;
00809
00810 unsigned int confirmanswer:1;
00811
00812
00813
00814
00815 unsigned int destroy:1;
00816 unsigned int didtdd:1;
00817
00818 unsigned int dialednone:1;
00819
00820
00821
00822
00823 unsigned int dialing:1;
00824
00825 unsigned int digital:1;
00826
00827 unsigned int dnd:1;
00828
00829 unsigned int echobreak:1;
00830
00831
00832
00833
00834
00835 unsigned int echocanbridged:1;
00836
00837 unsigned int echocanon:1;
00838
00839 unsigned int faxhandled:1;
00840
00841 unsigned int usefaxbuffers:1;
00842
00843 unsigned int bufferoverrideinuse:1;
00844
00845 unsigned int firstradio:1;
00846
00847
00848
00849
00850 unsigned int hanguponpolarityswitch:1;
00851
00852 unsigned int hardwaredtmf:1;
00853
00854
00855
00856
00857
00858
00859 unsigned int hidecallerid:1;
00860
00861
00862
00863
00864
00865 unsigned int hidecalleridname:1;
00866
00867 unsigned int ignoredtmf:1;
00868
00869
00870
00871
00872
00873 unsigned int immediate:1;
00874
00875 unsigned int inalarm:1;
00876
00877 unsigned int mate:1;
00878
00879 unsigned int outgoing:1;
00880
00881
00882
00883
00884
00885
00886 unsigned int permcallwaiting:1;
00887
00888
00889
00890
00891 unsigned int permhidecallerid:1;
00892
00893
00894
00895
00896 unsigned int priindication_oob:1;
00897
00898
00899
00900
00901 unsigned int priexclusive:1;
00902
00903
00904
00905
00906 unsigned int pulse:1;
00907
00908 unsigned int pulsedial:1;
00909 unsigned int restartpending:1;
00910
00911
00912
00913
00914
00915 unsigned int restrictcid:1;
00916
00917
00918
00919
00920 unsigned int threewaycalling:1;
00921
00922
00923
00924
00925
00926
00927
00928
00929 unsigned int transfer:1;
00930
00931
00932
00933
00934
00935
00936
00937 unsigned int use_callerid:1;
00938
00939
00940
00941
00942
00943
00944 unsigned int use_callingpres:1;
00945
00946
00947
00948
00949
00950 unsigned int usedistinctiveringdetection:1;
00951
00952
00953
00954
00955 unsigned int dahditrcallerid:1;
00956
00957
00958
00959
00960 unsigned int transfertobusy:1;
00961
00962
00963
00964
00965 unsigned int mwimonitor_neon:1;
00966
00967
00968
00969
00970 unsigned int mwimonitor_fsk:1;
00971
00972
00973
00974
00975
00976 unsigned int mwimonitor_rpas:1;
00977
00978 unsigned int mwimonitoractive:1;
00979
00980 unsigned int mwisendactive:1;
00981
00982
00983
00984
00985 unsigned int inservice:1;
00986
00987
00988
00989
00990 unsigned int locallyblocked:1;
00991
00992
00993
00994
00995 unsigned int remotelyblocked:1;
00996
00997
00998
00999
01000 unsigned int manages_span_alarms:1;
01001
01002 #if defined(HAVE_PRI)
01003 struct sig_pri_span *pri;
01004 int logicalspan;
01005 #endif
01006
01007
01008
01009
01010 unsigned int use_smdi:1;
01011 struct mwisend_info mwisend_data;
01012
01013 struct ast_smdi_interface *smdi_iface;
01014
01015
01016 struct dahdi_distRings drings;
01017
01018
01019
01020
01021
01022 char context[AST_MAX_CONTEXT];
01023
01024
01025
01026
01027 char description[32];
01028
01029
01030
01031 char defcontext[AST_MAX_CONTEXT];
01032
01033 char exten[AST_MAX_EXTENSION];
01034
01035
01036
01037
01038 char language[MAX_LANGUAGE];
01039
01040
01041
01042
01043 char mohinterpret[MAX_MUSICCLASS];
01044
01045
01046
01047
01048 char mohsuggest[MAX_MUSICCLASS];
01049 char parkinglot[AST_MAX_EXTENSION];
01050 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01051
01052 char cid_ani[AST_MAX_EXTENSION];
01053 #endif
01054
01055 int cid_ani2;
01056
01057 char cid_num[AST_MAX_EXTENSION];
01058
01059
01060
01061
01062 char cid_tag[AST_MAX_EXTENSION];
01063
01064 int cid_ton;
01065
01066 char cid_name[AST_MAX_EXTENSION];
01067
01068 char cid_subaddr[AST_MAX_EXTENSION];
01069 char *origcid_num;
01070 char *origcid_name;
01071
01072 char callwait_num[AST_MAX_EXTENSION];
01073
01074 char callwait_name[AST_MAX_EXTENSION];
01075
01076 char rdnis[AST_MAX_EXTENSION];
01077
01078 char dnid[AST_MAX_EXTENSION];
01079
01080
01081
01082
01083 ast_group_t group;
01084
01085 int law_default;
01086
01087 int law;
01088 int confno;
01089 int confusers;
01090 int propconfno;
01091
01092
01093
01094
01095 ast_group_t callgroup;
01096
01097
01098
01099
01100 ast_group_t pickupgroup;
01101
01102
01103
01104
01105 struct ast_namedgroups *named_callgroups;
01106
01107
01108
01109
01110 struct ast_namedgroups *named_pickupgroups;
01111
01112
01113
01114
01115 struct ast_variable *vars;
01116 int channel;
01117 int span;
01118 time_t guardtime;
01119 int cid_signalling;
01120 int cid_start;
01121 int dtmfcid_holdoff_state;
01122 struct timeval dtmfcid_delay;
01123 int callingpres;
01124 int callwaitingrepeat;
01125 int cidcwexpire;
01126 int cid_suppress_expire;
01127
01128 unsigned char *cidspill;
01129
01130 int cidpos;
01131
01132 int cidlen;
01133
01134 int ringt;
01135
01136
01137
01138
01139 int ringt_base;
01140
01141
01142
01143
01144
01145
01146 int stripmsd;
01147
01148
01149
01150
01151
01152
01153 int callwaitcas;
01154
01155 int callwaitrings;
01156
01157 struct {
01158 struct dahdi_echocanparams head;
01159 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01160 } echocancel;
01161
01162
01163
01164
01165 int echotraining;
01166
01167 char echorest[20];
01168
01169
01170
01171
01172 int busycount;
01173
01174
01175
01176
01177 struct ast_dsp_busy_pattern busy_cadence;
01178
01179
01180
01181
01182 int callprogress;
01183
01184
01185
01186
01187 int waitfordialtone;
01188
01189
01190
01191
01192 int dialtone_detect;
01193 int dialtone_scanning_time_elapsed;
01194 struct timeval waitingfordt;
01195 struct timeval flashtime;
01196
01197 struct ast_dsp *dsp;
01198
01199 struct dahdi_dialoperation dop;
01200 int whichwink;
01201
01202 char finaldial[64];
01203 char accountcode[AST_MAX_ACCOUNT_CODE];
01204 int amaflags;
01205 struct tdd_state *tdd;
01206
01207 char call_forward[AST_MAX_EXTENSION];
01208
01209
01210
01211
01212 char mailbox[AST_MAX_EXTENSION];
01213
01214 struct ast_event_sub *mwi_event_sub;
01215
01216 char dialdest[256];
01217 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01218 struct dahdi_vmwi_info mwisend_setting;
01219 unsigned int mwisend_fsk: 1;
01220 unsigned int mwisend_rpas:1;
01221 #endif
01222 int distinctivering;
01223 int dtmfrelax;
01224
01225 int fake_event;
01226
01227
01228
01229
01230 int polarityonanswerdelay;
01231
01232 struct timeval polaritydelaytv;
01233
01234
01235
01236
01237 int sendcalleridafter;
01238
01239 int polarity;
01240
01241 int dsp_features;
01242 #if defined(HAVE_SS7)
01243
01244 struct sig_ss7_linkset *ss7;
01245 #endif
01246 #ifdef HAVE_OPENR2
01247 struct dahdi_mfcr2 *mfcr2;
01248 openr2_chan_t *r2chan;
01249 openr2_calling_party_category_t mfcr2_recvd_category;
01250 openr2_calling_party_category_t mfcr2_category;
01251 int mfcr2_dnis_index;
01252 int mfcr2_ani_index;
01253 int mfcr2call:1;
01254 int mfcr2_answer_pending:1;
01255 int mfcr2_charge_calls:1;
01256 int mfcr2_allow_collect_calls:1;
01257 int mfcr2_forced_release:1;
01258 int mfcr2_dnis_matched:1;
01259 int mfcr2_call_accepted:1;
01260 int mfcr2_accept_on_offer:1;
01261 int mfcr2_progress_sent:1;
01262 #endif
01263
01264 char begindigit;
01265
01266 int muting;
01267 void *sig_pvt;
01268 struct ast_cc_config_params *cc_params;
01269
01270
01271
01272
01273
01274
01275 char dialstring[AST_CHANNEL_NAME];
01276 };
01277
01278 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01279 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01280 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01281 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01282 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01283 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01284 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01298 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01299 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01300 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01301 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01302 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01303 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01304 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01305 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01306 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01307 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01308 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01309 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01310 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01311 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01312 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01313 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01314 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01315 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01316 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01317 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01318 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01319 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01320 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01321 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01322 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01323 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01324 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01325 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01326 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01327 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01328 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01329 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01330 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01331 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01332 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01333 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01334 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01335 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01336 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01337 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01338 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01339 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01340 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01341 MEMBER(dahdi_pvt, description, AST_DATA_STRING) \
01342 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01343 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01344 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01345 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01346 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01347
01348 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01349
01350 static struct dahdi_pvt *iflist = NULL;
01351 static struct dahdi_pvt *ifend = NULL;
01352
01353 #if defined(HAVE_PRI)
01354 static struct dahdi_parms_pseudo {
01355 int buf_no;
01356 int buf_policy;
01357 int faxbuf_no;
01358 int faxbuf_policy;
01359 } dahdi_pseudo_parms;
01360 #endif
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372 struct dahdi_chan_conf {
01373 struct dahdi_pvt chan;
01374 #ifdef HAVE_PRI
01375 struct dahdi_pri pri;
01376 #endif
01377
01378 #if defined(HAVE_SS7)
01379 struct dahdi_ss7 ss7;
01380 #endif
01381
01382 #ifdef HAVE_OPENR2
01383 struct dahdi_mfcr2_conf mfcr2;
01384 #endif
01385 struct dahdi_params timing;
01386 int is_sig_auto;
01387
01388 int ignore_failed_channels;
01389
01390
01391
01392
01393
01394 char smdi_port[SMDI_MAX_FILENAME_LEN];
01395 };
01396
01397
01398 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01399 {
01400
01401
01402
01403 struct dahdi_chan_conf conf = {
01404 #ifdef HAVE_PRI
01405 .pri.pri = {
01406 .nsf = PRI_NSF_NONE,
01407 .switchtype = PRI_SWITCH_NI2,
01408 .dialplan = PRI_UNKNOWN + 1,
01409 .localdialplan = PRI_NATIONAL_ISDN + 1,
01410 .nodetype = PRI_CPE,
01411 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01412 .inband_on_setup_ack = 1,
01413 .inband_on_proceeding = 1,
01414
01415 #if defined(HAVE_PRI_CCSS)
01416 .cc_ptmp_recall_mode = 1,
01417 .cc_qsig_signaling_link_req = 1,
01418 .cc_qsig_signaling_link_rsp = 1,
01419 #endif
01420
01421 .minunused = 2,
01422 .idleext = "",
01423 .idledial = "",
01424 .internationalprefix = "",
01425 .nationalprefix = "",
01426 .localprefix = "",
01427 .privateprefix = "",
01428 .unknownprefix = "",
01429 .colp_send = SIG_PRI_COLP_UPDATE,
01430 .resetinterval = -1,
01431 },
01432 #endif
01433 #if defined(HAVE_SS7)
01434 .ss7.ss7 = {
01435 .called_nai = SS7_NAI_NATIONAL,
01436 .calling_nai = SS7_NAI_NATIONAL,
01437 .internationalprefix = "",
01438 .nationalprefix = "",
01439 .subscriberprefix = "",
01440 .unknownprefix = ""
01441 },
01442 #endif
01443 #ifdef HAVE_OPENR2
01444 .mfcr2 = {
01445 .variant = OR2_VAR_ITU,
01446 .mfback_timeout = -1,
01447 .metering_pulse_timeout = -1,
01448 .max_ani = 10,
01449 .max_dnis = 4,
01450 .get_ani_first = -1,
01451 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01452 .skip_category_request = -1,
01453 #endif
01454 .call_files = 0,
01455 .allow_collect_calls = 0,
01456 .charge_calls = 1,
01457 .accept_on_offer = 1,
01458 .forced_release = 0,
01459 .double_answer = 0,
01460 .immediate_accept = -1,
01461 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01462 .dtmf_dialing = -1,
01463 .dtmf_detection = -1,
01464 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01465 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01466 #endif
01467 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01468 .dtmf_end_timeout = -1,
01469 #endif
01470 .logdir = "",
01471 .r2proto_file = "",
01472 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01473 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01474 },
01475 #endif
01476 .chan = {
01477 .context = "default",
01478 .cid_num = "",
01479 .cid_name = "",
01480 .cid_tag = "",
01481 .mohinterpret = "default",
01482 .mohsuggest = "",
01483 .parkinglot = "",
01484 .transfertobusy = 1,
01485
01486 .cid_signalling = CID_SIG_BELL,
01487 .cid_start = CID_START_RING,
01488 .dahditrcallerid = 0,
01489 .use_callerid = 1,
01490 .sig = -1,
01491 .outsigmod = -1,
01492
01493 .cid_rxgain = +5.0,
01494
01495 .tonezone = -1,
01496
01497 .echocancel.head.tap_length = 1,
01498
01499 .busycount = 3,
01500
01501 .accountcode = "",
01502
01503 .mailbox = "",
01504
01505 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01506 .mwisend_fsk = 1,
01507 #endif
01508 .polarityonanswerdelay = 600,
01509
01510 .sendcalleridafter = DEFAULT_CIDRINGS,
01511
01512 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01513 .buf_no = numbufs,
01514 .usefaxbuffers = 0,
01515 .cc_params = ast_cc_config_params_init(),
01516 },
01517 .timing = {
01518 .prewinktime = -1,
01519 .preflashtime = -1,
01520 .winktime = -1,
01521 .flashtime = -1,
01522 .starttime = -1,
01523 .rxwinktime = -1,
01524 .rxflashtime = -1,
01525 .debouncetime = -1
01526 },
01527 .is_sig_auto = 1,
01528 .smdi_port = "/dev/ttyS0",
01529 };
01530
01531 return conf;
01532 }
01533
01534
01535 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01536 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01537 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01538 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01539 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01540 static int dahdi_hangup(struct ast_channel *ast);
01541 static int dahdi_answer(struct ast_channel *ast);
01542 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01543 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01544 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01545 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01546 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01547 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01548 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01549 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01550 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01551 static int dahdi_devicestate(const char *data);
01552 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01553
01554 static struct ast_channel_tech dahdi_tech = {
01555 .type = "DAHDI",
01556 .description = tdesc,
01557 .requester = dahdi_request,
01558 .send_digit_begin = dahdi_digit_begin,
01559 .send_digit_end = dahdi_digit_end,
01560 .send_text = dahdi_sendtext,
01561 .call = dahdi_call,
01562 .hangup = dahdi_hangup,
01563 .answer = dahdi_answer,
01564 .read = dahdi_read,
01565 .write = dahdi_write,
01566 .bridge = dahdi_bridge,
01567 .exception = dahdi_exception,
01568 .indicate = dahdi_indicate,
01569 .fixup = dahdi_fixup,
01570 .setoption = dahdi_setoption,
01571 .queryoption = dahdi_queryoption,
01572 .func_channel_read = dahdi_func_read,
01573 .func_channel_write = dahdi_func_write,
01574 .devicestate = dahdi_devicestate,
01575 .cc_callback = dahdi_cc_callback,
01576 };
01577
01578 #define GET_CHANNEL(p) ((p)->channel)
01579
01580 #define SIG_PRI_LIB_HANDLE_CASES \
01581 SIG_PRI: \
01582 case SIG_BRI: \
01583 case SIG_BRI_PTMP
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 static inline int dahdi_sig_pri_lib_handles(int signaling)
01595 {
01596 int handles;
01597
01598 switch (signaling) {
01599 case SIG_PRI_LIB_HANDLE_CASES:
01600 handles = 1;
01601 break;
01602 default:
01603 handles = 0;
01604 break;
01605 }
01606
01607 return handles;
01608 }
01609
01610 static int analog_lib_handles(int signalling, int radio, int oprmode)
01611 {
01612 switch (signalling) {
01613 case SIG_FXOLS:
01614 case SIG_FXOGS:
01615 case SIG_FXOKS:
01616 case SIG_FXSLS:
01617 case SIG_FXSGS:
01618 case SIG_FXSKS:
01619 case SIG_EMWINK:
01620 case SIG_EM:
01621 case SIG_EM_E1:
01622 case SIG_FEATD:
01623 case SIG_FEATDMF:
01624 case SIG_E911:
01625 case SIG_FGC_CAMA:
01626 case SIG_FGC_CAMAMF:
01627 case SIG_FEATB:
01628 case SIG_SFWINK:
01629 case SIG_SF:
01630 case SIG_SF_FEATD:
01631 case SIG_SF_FEATDMF:
01632 case SIG_FEATDMF_TA:
01633 case SIG_SF_FEATB:
01634 break;
01635 default:
01636
01637 return 0;
01638 }
01639
01640 if (radio) {
01641 return 0;
01642 }
01643
01644 if (oprmode) {
01645 return 0;
01646 }
01647
01648 return 1;
01649 }
01650
01651 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01652 {
01653 switch (sig) {
01654 case SIG_FXOLS:
01655 return ANALOG_SIG_FXOLS;
01656 case SIG_FXOGS:
01657 return ANALOG_SIG_FXOGS;
01658 case SIG_FXOKS:
01659 return ANALOG_SIG_FXOKS;
01660 case SIG_FXSLS:
01661 return ANALOG_SIG_FXSLS;
01662 case SIG_FXSGS:
01663 return ANALOG_SIG_FXSGS;
01664 case SIG_FXSKS:
01665 return ANALOG_SIG_FXSKS;
01666 case SIG_EMWINK:
01667 return ANALOG_SIG_EMWINK;
01668 case SIG_EM:
01669 return ANALOG_SIG_EM;
01670 case SIG_EM_E1:
01671 return ANALOG_SIG_EM_E1;
01672 case SIG_FEATD:
01673 return ANALOG_SIG_FEATD;
01674 case SIG_FEATDMF:
01675 return ANALOG_SIG_FEATDMF;
01676 case SIG_E911:
01677 return SIG_E911;
01678 case SIG_FGC_CAMA:
01679 return ANALOG_SIG_FGC_CAMA;
01680 case SIG_FGC_CAMAMF:
01681 return ANALOG_SIG_FGC_CAMAMF;
01682 case SIG_FEATB:
01683 return ANALOG_SIG_FEATB;
01684 case SIG_SFWINK:
01685 return ANALOG_SIG_SFWINK;
01686 case SIG_SF:
01687 return ANALOG_SIG_SF;
01688 case SIG_SF_FEATD:
01689 return ANALOG_SIG_SF_FEATD;
01690 case SIG_SF_FEATDMF:
01691 return ANALOG_SIG_SF_FEATDMF;
01692 case SIG_FEATDMF_TA:
01693 return ANALOG_SIG_FEATDMF_TA;
01694 case SIG_SF_FEATB:
01695 return ANALOG_SIG_FEATB;
01696 default:
01697 return -1;
01698 }
01699 }
01700
01701
01702 static int analog_tone_to_dahditone(enum analog_tone tone)
01703 {
01704 switch (tone) {
01705 case ANALOG_TONE_RINGTONE:
01706 return DAHDI_TONE_RINGTONE;
01707 case ANALOG_TONE_STUTTER:
01708 return DAHDI_TONE_STUTTER;
01709 case ANALOG_TONE_CONGESTION:
01710 return DAHDI_TONE_CONGESTION;
01711 case ANALOG_TONE_DIALTONE:
01712 return DAHDI_TONE_DIALTONE;
01713 case ANALOG_TONE_DIALRECALL:
01714 return DAHDI_TONE_DIALRECALL;
01715 case ANALOG_TONE_INFO:
01716 return DAHDI_TONE_INFO;
01717 default:
01718 return -1;
01719 }
01720 }
01721
01722 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01723 {
01724 int index;
01725
01726 switch (analogsub) {
01727 case ANALOG_SUB_REAL:
01728 index = SUB_REAL;
01729 break;
01730 case ANALOG_SUB_CALLWAIT:
01731 index = SUB_CALLWAIT;
01732 break;
01733 case ANALOG_SUB_THREEWAY:
01734 index = SUB_THREEWAY;
01735 break;
01736 default:
01737 ast_log(LOG_ERROR, "Unidentified sub!\n");
01738 index = SUB_REAL;
01739 }
01740
01741 return index;
01742 }
01743
01744 static enum analog_event dahdievent_to_analogevent(int event);
01745 static int bump_gains(struct dahdi_pvt *p);
01746 static int dahdi_setlinear(int dfd, int linear);
01747
01748 static int my_start_cid_detect(void *pvt, int cid_signalling)
01749 {
01750 struct dahdi_pvt *p = pvt;
01751 int index = SUB_REAL;
01752 p->cs = callerid_new(cid_signalling);
01753 if (!p->cs) {
01754 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01755 return -1;
01756 }
01757 bump_gains(p);
01758 dahdi_setlinear(p->subs[index].dfd, 0);
01759
01760 return 0;
01761 }
01762
01763 static int my_stop_cid_detect(void *pvt)
01764 {
01765 struct dahdi_pvt *p = pvt;
01766 int index = SUB_REAL;
01767 if (p->cs)
01768 callerid_free(p->cs);
01769 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01770 return 0;
01771 }
01772
01773 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01774 {
01775 struct dahdi_pvt *p = pvt;
01776 struct analog_pvt *analog_p = p->sig_pvt;
01777 struct pollfd poller;
01778 char *name, *num;
01779 int index = SUB_REAL;
01780 int res;
01781 unsigned char buf[256];
01782 int flags;
01783 struct ast_format tmpfmt;
01784
01785 poller.fd = p->subs[SUB_REAL].dfd;
01786 poller.events = POLLPRI | POLLIN;
01787 poller.revents = 0;
01788
01789 res = poll(&poller, 1, timeout);
01790
01791 if (poller.revents & POLLPRI) {
01792 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01793 return 1;
01794 }
01795
01796 if (poller.revents & POLLIN) {
01797
01798
01799
01800
01801
01802 res = read(p->subs[index].dfd, buf, sizeof(buf));
01803 if (res < 0) {
01804 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01805 return -1;
01806 }
01807
01808 if (analog_p->ringt > 0) {
01809 if (!(--analog_p->ringt)) {
01810
01811 return -1;
01812 }
01813 }
01814
01815 if (p->cid_signalling == CID_SIG_V23_JP) {
01816 res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01817 } else {
01818 res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01819 }
01820 if (res < 0) {
01821
01822
01823
01824
01825 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01826 return -1;
01827 }
01828
01829 if (res == 1) {
01830 callerid_get(p->cs, &name, &num, &flags);
01831 if (name)
01832 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01833 if (num)
01834 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01835
01836 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01837 return 0;
01838 }
01839 }
01840
01841 *ev = ANALOG_EVENT_NONE;
01842 return 2;
01843 }
01844
01845 static const char *event2str(int event);
01846 static int restore_gains(struct dahdi_pvt *p);
01847
01848 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01849 {
01850 unsigned char buf[256];
01851 int distMatches;
01852 int curRingData[RING_PATTERNS];
01853 int receivedRingT;
01854 int counter1;
01855 int counter;
01856 int i;
01857 int res;
01858 int checkaftercid = 0;
01859
01860 struct dahdi_pvt *p = pvt;
01861 struct analog_pvt *analog_p = p->sig_pvt;
01862
01863 if (ringdata == NULL) {
01864 ringdata = curRingData;
01865 } else {
01866 checkaftercid = 1;
01867 }
01868
01869
01870
01871 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01872
01873 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01874 ringdata[receivedRingT] = 0;
01875 receivedRingT = 0;
01876 if (checkaftercid && distinctiveringaftercid)
01877 ast_verb(3, "Detecting post-CID distinctive ring\n");
01878
01879 else if (strcmp(p->context,p->defcontext) != 0) {
01880 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01881 ast_channel_context_set(chan, p->defcontext);
01882 }
01883
01884 for (;;) {
01885 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01886 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01887 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01888 ast_hangup(chan);
01889 return 1;
01890 }
01891 if (i & DAHDI_IOMUX_SIGEVENT) {
01892 res = dahdi_get_event(p->subs[idx].dfd);
01893 if (res == DAHDI_EVENT_NOALARM) {
01894 p->inalarm = 0;
01895 analog_p->inalarm = 0;
01896 }
01897 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01898 res = 0;
01899
01900
01901 ringdata[receivedRingT] = analog_p->ringt;
01902
01903 if (analog_p->ringt < analog_p->ringt_base/2)
01904 break;
01905
01906
01907 if (++receivedRingT == RING_PATTERNS)
01908 break;
01909 } else if (i & DAHDI_IOMUX_READ) {
01910 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01911 if (res < 0) {
01912 if (errno != ELAST) {
01913 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01914 ast_hangup(chan);
01915 return 1;
01916 }
01917 break;
01918 }
01919 if (analog_p->ringt > 0) {
01920 if (!(--analog_p->ringt)) {
01921 res = -1;
01922 break;
01923 }
01924 }
01925 }
01926 }
01927 }
01928 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01929
01930 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01931 for (counter = 0; counter < 3; counter++) {
01932
01933 distMatches = 0;
01934
01935 ast_verb(3, "Checking %d,%d,%d\n",
01936 p->drings.ringnum[counter].ring[0],
01937 p->drings.ringnum[counter].ring[1],
01938 p->drings.ringnum[counter].ring[2]);
01939 for (counter1 = 0; counter1 < 3; counter1++) {
01940 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01941 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01942 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01943 ringdata[counter1]);
01944 distMatches++;
01945 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01946 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01947 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01948 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01949 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01950 distMatches++;
01951 }
01952 }
01953
01954 if (distMatches == 3) {
01955
01956 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01957 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
01958 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01959 break;
01960 }
01961 }
01962 }
01963
01964 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01965 restore_gains(p);
01966
01967 return 0;
01968 }
01969
01970 static int my_stop_callwait(void *pvt)
01971 {
01972 struct dahdi_pvt *p = pvt;
01973 p->callwaitingrepeat = 0;
01974 p->cidcwexpire = 0;
01975 p->cid_suppress_expire = 0;
01976
01977 return 0;
01978 }
01979
01980 static int send_callerid(struct dahdi_pvt *p);
01981 static int save_conference(struct dahdi_pvt *p);
01982 static int restore_conference(struct dahdi_pvt *p);
01983
01984 static int my_callwait(void *pvt)
01985 {
01986 struct dahdi_pvt *p = pvt;
01987 struct ast_format tmpfmt;
01988 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01989 if (p->cidspill) {
01990 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01991 ast_free(p->cidspill);
01992 }
01993
01994
01995
01996
01997
01998 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01999 return -1;
02000 save_conference(p);
02001
02002 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02003 if (!p->callwaitrings && p->callwaitingcallerid) {
02004 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02005 p->callwaitcas = 1;
02006 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02007 } else {
02008 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02009 p->callwaitcas = 0;
02010 p->cidlen = 2400 + READ_SIZE * 4;
02011 }
02012 p->cidpos = 0;
02013 send_callerid(p);
02014
02015 return 0;
02016 }
02017
02018 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
02019 {
02020 struct dahdi_pvt *p = pvt;
02021 struct ast_format tmpfmt;
02022
02023 ast_debug(2, "Starting cid spill\n");
02024
02025 if (p->cidspill) {
02026 ast_log(LOG_WARNING, "cidspill already exists??\n");
02027 ast_free(p->cidspill);
02028 }
02029
02030 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02031 if (cwcid == 0) {
02032 p->cidlen = ast_callerid_generate(p->cidspill,
02033 caller->id.name.str,
02034 caller->id.number.str,
02035 ast_format_set(&tmpfmt, AST_LAW(p), 0));
02036 } else {
02037 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
02038 caller->id.name.str, caller->id.number.str);
02039 p->callwaitcas = 0;
02040 p->cidcwexpire = 0;
02041 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02042 caller->id.name.str,
02043 caller->id.number.str,
02044 ast_format_set(&tmpfmt, AST_LAW(p), 0));
02045 p->cidlen += READ_SIZE * 4;
02046 }
02047 p->cidpos = 0;
02048 p->cid_suppress_expire = 0;
02049 send_callerid(p);
02050 }
02051 return 0;
02052 }
02053
02054 static int my_dsp_reset_and_flush_digits(void *pvt)
02055 {
02056 struct dahdi_pvt *p = pvt;
02057 if (p->dsp)
02058 ast_dsp_digitreset(p->dsp);
02059
02060 return 0;
02061 }
02062
02063 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02064 {
02065 struct dahdi_pvt *p = pvt;
02066
02067 if (p->channel == CHAN_PSEUDO)
02068 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02069
02070 if (mode == ANALOG_DIGITMODE_DTMF) {
02071
02072 if (p->hardwaredtmf) {
02073 if (p->dsp) {
02074 ast_dsp_free(p->dsp);
02075 p->dsp = NULL;
02076 }
02077 return 0;
02078 }
02079
02080 if (!p->dsp) {
02081 p->dsp = ast_dsp_new();
02082 if (!p->dsp) {
02083 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02084 return -1;
02085 }
02086 }
02087
02088 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02089 } else if (mode == ANALOG_DIGITMODE_MF) {
02090 if (!p->dsp) {
02091 p->dsp = ast_dsp_new();
02092 if (!p->dsp) {
02093 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02094 return -1;
02095 }
02096 }
02097 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02098 }
02099 return 0;
02100 }
02101
02102 static int dahdi_wink(struct dahdi_pvt *p, int index);
02103
02104 static int my_wink(void *pvt, enum analog_sub sub)
02105 {
02106 struct dahdi_pvt *p = pvt;
02107 int index = analogsub_to_dahdisub(sub);
02108 if (index != SUB_REAL) {
02109 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02110 }
02111 return dahdi_wink(p, index);
02112 }
02113
02114 static void wakeup_sub(struct dahdi_pvt *p, int a);
02115
02116 static int reset_conf(struct dahdi_pvt *p);
02117
02118 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02119
02120 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02121 {
02122 struct ast_frame *f = *dest;
02123 struct dahdi_pvt *p = pvt;
02124 int idx = analogsub_to_dahdisub(analog_index);
02125
02126 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02127 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02128 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02129
02130 if (f->subclass.integer == 'f') {
02131 if (f->frametype == AST_FRAME_DTMF_END) {
02132
02133 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02134
02135 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02136 struct dahdi_bufferinfo bi = {
02137 .txbufpolicy = p->faxbuf_policy,
02138 .bufsize = p->bufsize,
02139 .numbufs = p->faxbuf_no
02140 };
02141 int res;
02142
02143 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02144 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02145 } else {
02146 p->bufferoverrideinuse = 1;
02147 }
02148 }
02149 p->faxhandled = 1;
02150 if (p->dsp) {
02151 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02152 ast_dsp_set_features(p->dsp, p->dsp_features);
02153 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02154 }
02155 if (strcmp(ast_channel_exten(ast), "fax")) {
02156 const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
02157
02158
02159
02160
02161
02162 ast_mutex_unlock(&p->lock);
02163 ast_channel_unlock(ast);
02164 if (ast_exists_extension(ast, target_context, "fax", 1,
02165 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
02166 ast_channel_lock(ast);
02167 ast_mutex_lock(&p->lock);
02168 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02169
02170 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
02171 if (ast_async_goto(ast, target_context, "fax", 1))
02172 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02173 } else {
02174 ast_channel_lock(ast);
02175 ast_mutex_lock(&p->lock);
02176 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02177 }
02178 } else {
02179 ast_debug(1, "Already in a fax extension, not redirecting\n");
02180 }
02181 } else {
02182 ast_debug(1, "Fax already handled\n");
02183 }
02184 dahdi_confmute(p, 0);
02185 }
02186 p->subs[idx].f.frametype = AST_FRAME_NULL;
02187 p->subs[idx].f.subclass.integer = 0;
02188 *dest = &p->subs[idx].f;
02189 }
02190 }
02191
02192 static void my_lock_private(void *pvt)
02193 {
02194 struct dahdi_pvt *p = pvt;
02195 ast_mutex_lock(&p->lock);
02196 }
02197
02198 static void my_unlock_private(void *pvt)
02199 {
02200 struct dahdi_pvt *p = pvt;
02201 ast_mutex_unlock(&p->lock);
02202 }
02203
02204 static void my_deadlock_avoidance_private(void *pvt)
02205 {
02206 struct dahdi_pvt *p = pvt;
02207
02208 DEADLOCK_AVOIDANCE(&p->lock);
02209 }
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02222 {
02223 char ch_name[20];
02224
02225 if (p->channel < CHAN_PSEUDO) {
02226
02227 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02228 } else if (p->channel == CHAN_PSEUDO) {
02229
02230 strcpy(ch_name, "pseudo");
02231 } else {
02232
02233 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02234 }
02235
02236
02237
02238
02239
02240 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02241 "Channel: %s\r\n"
02242 "Uniqueid: %s\r\n"
02243 "DAHDISpan: %d\r\n"
02244 "DAHDIChannel: %s\r\n",
02245 ast_channel_name(chan),
02246 ast_channel_uniqueid(chan),
02247 p->span,
02248 ch_name);
02249 }
02250
02251 #ifdef HAVE_PRI
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02263 {
02264 struct dahdi_pvt *p = pvt;
02265
02266 dahdi_ami_channel_event(p, chan);
02267 }
02268 #endif
02269
02270
02271
02272
02273 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02274 {
02275 struct dahdi_pvt *p = pvt;
02276 int oldval;
02277 int idx = analogsub_to_dahdisub(sub);
02278
02279 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02280 oldval = p->subs[idx].linear;
02281 p->subs[idx].linear = linear_mode ? 1 : 0;
02282 return oldval;
02283 }
02284
02285 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02286 {
02287 struct dahdi_pvt *p = pvt;
02288 int idx = analogsub_to_dahdisub(sub);
02289
02290 p->subs[idx].inthreeway = inthreeway;
02291 }
02292
02293 static int get_alarms(struct dahdi_pvt *p);
02294 static void handle_alarms(struct dahdi_pvt *p, int alms);
02295 static void my_get_and_handle_alarms(void *pvt)
02296 {
02297 int res;
02298 struct dahdi_pvt *p = pvt;
02299
02300 res = get_alarms(p);
02301 handle_alarms(p, res);
02302 }
02303
02304 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02305 {
02306 struct ast_channel *bridged = ast_bridged_channel(chan);
02307
02308 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
02309 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
02310
02311 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02312 return p->sig_pvt;
02313 }
02314 }
02315 return NULL;
02316 }
02317
02318 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02319 {
02320 struct dahdi_pvt *p = pvt;
02321 int dahdi_sub = analogsub_to_dahdisub(sub);
02322 return p->subs[dahdi_sub].dfd;
02323 }
02324
02325 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02326 {
02327 struct dahdi_pvt *p = pvt;
02328
02329
02330 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02331 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02332 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02333 *cid_rings = cidrings[p->distinctivering - 1];
02334 } else {
02335 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02336 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02337 *cid_rings = p->sendcalleridafter;
02338 }
02339 }
02340
02341 static void my_set_alarm(void *pvt, int in_alarm)
02342 {
02343 struct dahdi_pvt *p = pvt;
02344
02345 p->inalarm = in_alarm;
02346 }
02347
02348 static void my_set_dialing(void *pvt, int is_dialing)
02349 {
02350 struct dahdi_pvt *p = pvt;
02351
02352 p->dialing = is_dialing;
02353 }
02354
02355 static void my_set_outgoing(void *pvt, int is_outgoing)
02356 {
02357 struct dahdi_pvt *p = pvt;
02358
02359 p->outgoing = is_outgoing;
02360 }
02361
02362 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02363 static void my_set_digital(void *pvt, int is_digital)
02364 {
02365 struct dahdi_pvt *p = pvt;
02366
02367 p->digital = is_digital;
02368 }
02369 #endif
02370
02371 #if defined(HAVE_SS7)
02372 static void my_set_inservice(void *pvt, int is_inservice)
02373 {
02374 struct dahdi_pvt *p = pvt;
02375
02376 p->inservice = is_inservice;
02377 }
02378 #endif
02379
02380 #if defined(HAVE_SS7)
02381 static void my_set_locallyblocked(void *pvt, int is_blocked)
02382 {
02383 struct dahdi_pvt *p = pvt;
02384
02385 p->locallyblocked = is_blocked;
02386 }
02387 #endif
02388
02389 #if defined(HAVE_SS7)
02390 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02391 {
02392 struct dahdi_pvt *p = pvt;
02393
02394 p->remotelyblocked = is_blocked;
02395 }
02396 #endif
02397
02398 static void my_set_ringtimeout(void *pvt, int ringt)
02399 {
02400 struct dahdi_pvt *p = pvt;
02401 p->ringt = ringt;
02402 }
02403
02404 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02405 {
02406 struct dahdi_pvt *p = pvt;
02407
02408 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02409 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02410 gettimeofday(&p->waitingfordt, NULL);
02411 ast_setstate(ast, AST_STATE_OFFHOOK);
02412 }
02413 }
02414
02415 static int my_check_waitingfordt(void *pvt)
02416 {
02417 struct dahdi_pvt *p = pvt;
02418
02419 if (p->waitingfordt.tv_sec) {
02420 return 1;
02421 }
02422
02423 return 0;
02424 }
02425
02426 static void my_set_confirmanswer(void *pvt, int flag)
02427 {
02428 struct dahdi_pvt *p = pvt;
02429 p->confirmanswer = flag;
02430 }
02431
02432 static int my_check_confirmanswer(void *pvt)
02433 {
02434 struct dahdi_pvt *p = pvt;
02435 if (p->confirmanswer) {
02436 return 1;
02437 }
02438
02439 return 0;
02440 }
02441
02442 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02443 {
02444 struct dahdi_pvt *p = pvt;
02445
02446 p->callwaiting = callwaiting_enable;
02447 }
02448
02449 static void my_cancel_cidspill(void *pvt)
02450 {
02451 struct dahdi_pvt *p = pvt;
02452
02453 ast_free(p->cidspill);
02454 p->cidspill = NULL;
02455 restore_conference(p);
02456 }
02457
02458 static int my_confmute(void *pvt, int mute)
02459 {
02460 struct dahdi_pvt *p = pvt;
02461 return dahdi_confmute(p, mute);
02462 }
02463
02464 static void my_set_pulsedial(void *pvt, int flag)
02465 {
02466 struct dahdi_pvt *p = pvt;
02467 p->pulsedial = flag;
02468 }
02469
02470 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02471 {
02472 struct dahdi_pvt *p = pvt;
02473
02474 p->owner = new_owner;
02475 }
02476
02477 static const char *my_get_orig_dialstring(void *pvt)
02478 {
02479 struct dahdi_pvt *p = pvt;
02480
02481 return p->dialstring;
02482 }
02483
02484 static void my_increase_ss_count(void)
02485 {
02486 ast_mutex_lock(&ss_thread_lock);
02487 ss_thread_count++;
02488 ast_mutex_unlock(&ss_thread_lock);
02489 }
02490
02491 static void my_decrease_ss_count(void)
02492 {
02493 ast_mutex_lock(&ss_thread_lock);
02494 ss_thread_count--;
02495 ast_cond_signal(&ss_thread_complete);
02496 ast_mutex_unlock(&ss_thread_lock);
02497 }
02498
02499 static void my_all_subchannels_hungup(void *pvt)
02500 {
02501 struct dahdi_pvt *p = pvt;
02502 int res, law;
02503
02504 p->faxhandled = 0;
02505 p->didtdd = 0;
02506
02507 if (p->dsp) {
02508 ast_dsp_free(p->dsp);
02509 p->dsp = NULL;
02510 }
02511
02512 p->law = p->law_default;
02513 law = p->law_default;
02514 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02515 if (res < 0)
02516 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02517
02518 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02519
02520 #if 1
02521 {
02522 int i;
02523 p->owner = NULL;
02524
02525 for (i = 0; i < 3; i++) {
02526 p->subs[i].owner = NULL;
02527 }
02528 }
02529 #endif
02530
02531 reset_conf(p);
02532 if (num_restart_pending == 0) {
02533 restart_monitor();
02534 }
02535 }
02536
02537 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02538
02539 static int my_conf_del(void *pvt, enum analog_sub sub)
02540 {
02541 struct dahdi_pvt *p = pvt;
02542 int x = analogsub_to_dahdisub(sub);
02543
02544 return conf_del(p, &p->subs[x], x);
02545 }
02546
02547 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02548
02549 static int my_conf_add(void *pvt, enum analog_sub sub)
02550 {
02551 struct dahdi_pvt *p = pvt;
02552 int x = analogsub_to_dahdisub(sub);
02553
02554 return conf_add(p, &p->subs[x], x, 0);
02555 }
02556
02557 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02558
02559 static int my_complete_conference_update(void *pvt, int needconference)
02560 {
02561 struct dahdi_pvt *p = pvt;
02562 int needconf = needconference;
02563 int x;
02564 int useslavenative;
02565 struct dahdi_pvt *slave = NULL;
02566
02567 useslavenative = isslavenative(p, &slave);
02568
02569
02570
02571 for (x = 0; x < MAX_SLAVES; x++) {
02572 if (p->slaves[x]) {
02573 if (useslavenative)
02574 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02575 else {
02576 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02577 needconf++;
02578 }
02579 }
02580 }
02581
02582 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02583 if (useslavenative)
02584 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02585 else {
02586 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02587 needconf++;
02588 }
02589 }
02590
02591 if (p->master) {
02592 if (isslavenative(p->master, NULL)) {
02593 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02594 } else {
02595 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02596 }
02597 }
02598 if (!needconf) {
02599
02600
02601 p->confno = -1;
02602 }
02603
02604 return 0;
02605 }
02606
02607 static int check_for_conference(struct dahdi_pvt *p);
02608
02609 static int my_check_for_conference(void *pvt)
02610 {
02611 struct dahdi_pvt *p = pvt;
02612 return check_for_conference(p);
02613 }
02614
02615 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)
02616 {
02617 struct dahdi_pvt *p = pvt;
02618 int da, db;
02619 int tchan;
02620 int tinthreeway;
02621
02622 da = analogsub_to_dahdisub(a);
02623 db = analogsub_to_dahdisub(b);
02624
02625 tchan = p->subs[da].chan;
02626 p->subs[da].chan = p->subs[db].chan;
02627 p->subs[db].chan = tchan;
02628
02629 tinthreeway = p->subs[da].inthreeway;
02630 p->subs[da].inthreeway = p->subs[db].inthreeway;
02631 p->subs[db].inthreeway = tinthreeway;
02632
02633 p->subs[da].owner = ast_a;
02634 p->subs[db].owner = ast_b;
02635
02636 if (ast_a)
02637 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02638 if (ast_b)
02639 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02640
02641 wakeup_sub(p, a);
02642 wakeup_sub(p, b);
02643
02644 return;
02645 }
02646
02647
02648
02649
02650
02651
02652
02653
02654 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linked, struct ast_callid *callid, int callid_created);
02655
02656 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid);
02657
02658 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02659 {
02660 struct ast_callid *callid = NULL;
02661 int callid_created = ast_callid_threadstorage_auto(&callid);
02662 struct dahdi_pvt *p = pvt;
02663 int dsub = analogsub_to_dahdisub(sub);
02664
02665 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02666 }
02667
02668 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02669 static int dahdi_setlaw(int dfd, int law)
02670 {
02671 int res;
02672 res = ioctl(dfd, DAHDI_SETLAW, &law);
02673 if (res)
02674 return res;
02675 return 0;
02676 }
02677 #endif
02678
02679 #if defined(HAVE_PRI)
02680 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)
02681 {
02682 struct dahdi_pvt *p = pvt;
02683 int audio;
02684 int newlaw = -1;
02685 struct ast_callid *callid = NULL;
02686 int callid_created = ast_callid_threadstorage_auto(&callid);
02687
02688 switch (p->sig) {
02689 case SIG_PRI_LIB_HANDLE_CASES:
02690 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02691
02692 break;
02693 }
02694
02695 default:
02696
02697 audio = 1;
02698 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02699 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02700 p->channel, audio, strerror(errno));
02701 }
02702 break;
02703 }
02704
02705 if (law != SIG_PRI_DEFLAW) {
02706 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02707 }
02708
02709 ast_copy_string(p->exten, exten, sizeof(p->exten));
02710
02711 switch (law) {
02712 case SIG_PRI_DEFLAW:
02713 newlaw = 0;
02714 break;
02715 case SIG_PRI_ALAW:
02716 newlaw = DAHDI_LAW_ALAW;
02717 break;
02718 case SIG_PRI_ULAW:
02719 newlaw = DAHDI_LAW_MULAW;
02720 break;
02721 }
02722
02723 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02724 }
02725 #endif
02726
02727 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02728
02729 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739 static void my_pri_ss7_open_media(void *p)
02740 {
02741 struct dahdi_pvt *pvt = p;
02742 int res;
02743 int dfd;
02744 int set_val;
02745
02746 dfd = pvt->subs[SUB_REAL].dfd;
02747
02748
02749 set_val = 1;
02750 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02751 if (res < 0) {
02752 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02753 pvt->channel, strerror(errno));
02754 }
02755
02756
02757 res = dahdi_setlaw(dfd, pvt->law);
02758 if (res < 0) {
02759 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02760 }
02761
02762
02763 if (pvt->digital) {
02764 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02765 } else {
02766 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02767 pvt->law);
02768 }
02769 if (res < 0) {
02770 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02771 }
02772
02773 if (pvt->dsp_features && pvt->dsp) {
02774 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02775 pvt->dsp_features = 0;
02776 }
02777 }
02778 #endif
02779
02780 #if defined(HAVE_PRI)
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793 static void my_pri_dial_digits(void *p, const char *dial_string)
02794 {
02795 struct dahdi_dialoperation zo = {
02796 .op = DAHDI_DIAL_OP_APPEND,
02797 };
02798 struct dahdi_pvt *pvt = p;
02799 int res;
02800
02801 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02802 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02803 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02804 if (res) {
02805 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02806 pvt->channel, dial_string, strerror(errno));
02807 } else {
02808 pvt->dialing = 1;
02809 }
02810 }
02811 #endif
02812
02813 static int unalloc_sub(struct dahdi_pvt *p, int x);
02814
02815 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02816 {
02817 struct dahdi_pvt *p = pvt;
02818
02819 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02820 }
02821
02822 static int alloc_sub(struct dahdi_pvt *p, int x);
02823
02824 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02825 {
02826 struct dahdi_pvt *p = pvt;
02827
02828 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02829 }
02830
02831 static int has_voicemail(struct dahdi_pvt *p);
02832
02833 static int my_has_voicemail(void *pvt)
02834 {
02835 struct dahdi_pvt *p = pvt;
02836
02837 return has_voicemail(p);
02838 }
02839
02840 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02841 {
02842 struct dahdi_pvt *p = pvt;
02843 int index;
02844
02845 index = analogsub_to_dahdisub(sub);
02846
02847 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02848 }
02849
02850 static enum analog_event dahdievent_to_analogevent(int event)
02851 {
02852 enum analog_event res;
02853
02854 switch (event) {
02855 case DAHDI_EVENT_ONHOOK:
02856 res = ANALOG_EVENT_ONHOOK;
02857 break;
02858 case DAHDI_EVENT_RINGOFFHOOK:
02859 res = ANALOG_EVENT_RINGOFFHOOK;
02860 break;
02861 case DAHDI_EVENT_WINKFLASH:
02862 res = ANALOG_EVENT_WINKFLASH;
02863 break;
02864 case DAHDI_EVENT_ALARM:
02865 res = ANALOG_EVENT_ALARM;
02866 break;
02867 case DAHDI_EVENT_NOALARM:
02868 res = ANALOG_EVENT_NOALARM;
02869 break;
02870 case DAHDI_EVENT_DIALCOMPLETE:
02871 res = ANALOG_EVENT_DIALCOMPLETE;
02872 break;
02873 case DAHDI_EVENT_RINGERON:
02874 res = ANALOG_EVENT_RINGERON;
02875 break;
02876 case DAHDI_EVENT_RINGEROFF:
02877 res = ANALOG_EVENT_RINGEROFF;
02878 break;
02879 case DAHDI_EVENT_HOOKCOMPLETE:
02880 res = ANALOG_EVENT_HOOKCOMPLETE;
02881 break;
02882 case DAHDI_EVENT_PULSE_START:
02883 res = ANALOG_EVENT_PULSE_START;
02884 break;
02885 case DAHDI_EVENT_POLARITY:
02886 res = ANALOG_EVENT_POLARITY;
02887 break;
02888 case DAHDI_EVENT_RINGBEGIN:
02889 res = ANALOG_EVENT_RINGBEGIN;
02890 break;
02891 case DAHDI_EVENT_EC_DISABLED:
02892 res = ANALOG_EVENT_EC_DISABLED;
02893 break;
02894 case DAHDI_EVENT_REMOVED:
02895 res = ANALOG_EVENT_REMOVED;
02896 break;
02897 case DAHDI_EVENT_NEONMWI_ACTIVE:
02898 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02899 break;
02900 case DAHDI_EVENT_NEONMWI_INACTIVE:
02901 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02902 break;
02903 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02904 case DAHDI_EVENT_TX_CED_DETECTED:
02905 res = ANALOG_EVENT_TX_CED_DETECTED;
02906 break;
02907 case DAHDI_EVENT_RX_CED_DETECTED:
02908 res = ANALOG_EVENT_RX_CED_DETECTED;
02909 break;
02910 case DAHDI_EVENT_EC_NLP_DISABLED:
02911 res = ANALOG_EVENT_EC_NLP_DISABLED;
02912 break;
02913 case DAHDI_EVENT_EC_NLP_ENABLED:
02914 res = ANALOG_EVENT_EC_NLP_ENABLED;
02915 break;
02916 #endif
02917 case DAHDI_EVENT_PULSEDIGIT:
02918 res = ANALOG_EVENT_PULSEDIGIT;
02919 break;
02920 case DAHDI_EVENT_DTMFDOWN:
02921 res = ANALOG_EVENT_DTMFDOWN;
02922 break;
02923 case DAHDI_EVENT_DTMFUP:
02924 res = ANALOG_EVENT_DTMFUP;
02925 break;
02926 default:
02927 switch(event & 0xFFFF0000) {
02928 case DAHDI_EVENT_PULSEDIGIT:
02929 case DAHDI_EVENT_DTMFDOWN:
02930 case DAHDI_EVENT_DTMFUP:
02931
02932
02933
02934
02935 return event;
02936 }
02937
02938 res = ANALOG_EVENT_ERROR;
02939 break;
02940 }
02941
02942 return res;
02943 }
02944
02945 static inline int dahdi_wait_event(int fd);
02946
02947 static int my_wait_event(void *pvt)
02948 {
02949 struct dahdi_pvt *p = pvt;
02950
02951 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02952 }
02953
02954 static int my_get_event(void *pvt)
02955 {
02956 struct dahdi_pvt *p = pvt;
02957 int res;
02958
02959 if (p->fake_event) {
02960 res = p->fake_event;
02961 p->fake_event = 0;
02962 } else
02963 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02964
02965 return dahdievent_to_analogevent(res);
02966 }
02967
02968 static int my_is_off_hook(void *pvt)
02969 {
02970 struct dahdi_pvt *p = pvt;
02971 int res;
02972 struct dahdi_params par;
02973
02974 memset(&par, 0, sizeof(par));
02975
02976 if (p->subs[SUB_REAL].dfd > -1)
02977 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02978 else {
02979
02980 res = 0;
02981 par.rxisoffhook = 0;
02982 }
02983 if (res) {
02984 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02985 }
02986
02987 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02988
02989
02990
02991 return (par.rxbits > -1) || par.rxisoffhook;
02992 }
02993
02994 return par.rxisoffhook;
02995 }
02996
02997 static void dahdi_enable_ec(struct dahdi_pvt *p);
02998 static void dahdi_disable_ec(struct dahdi_pvt *p);
02999
03000 static int my_set_echocanceller(void *pvt, int enable)
03001 {
03002 struct dahdi_pvt *p = pvt;
03003
03004 if (enable)
03005 dahdi_enable_ec(p);
03006 else
03007 dahdi_disable_ec(p);
03008
03009 return 0;
03010 }
03011
03012 static int dahdi_ring_phone(struct dahdi_pvt *p);
03013
03014 static int my_ring(void *pvt)
03015 {
03016 struct dahdi_pvt *p = pvt;
03017
03018 return dahdi_ring_phone(p);
03019 }
03020
03021 static int my_flash(void *pvt)
03022 {
03023 struct dahdi_pvt *p = pvt;
03024 int func = DAHDI_FLASH;
03025 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
03026 }
03027
03028 static inline int dahdi_set_hook(int fd, int hs);
03029
03030 static int my_off_hook(void *pvt)
03031 {
03032 struct dahdi_pvt *p = pvt;
03033 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03034 }
03035
03036 static void my_set_needringing(void *pvt, int value)
03037 {
03038 struct dahdi_pvt *p = pvt;
03039 p->subs[SUB_REAL].needringing = value;
03040 }
03041
03042 static void my_set_polarity(void *pvt, int value)
03043 {
03044 struct dahdi_pvt *p = pvt;
03045
03046 if (p->channel == CHAN_PSEUDO) {
03047 return;
03048 }
03049 p->polarity = value;
03050 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
03051 }
03052
03053 static void my_start_polarityswitch(void *pvt)
03054 {
03055 struct dahdi_pvt *p = pvt;
03056
03057 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03058 my_set_polarity(pvt, 0);
03059 }
03060 }
03061
03062 static void my_answer_polarityswitch(void *pvt)
03063 {
03064 struct dahdi_pvt *p = pvt;
03065
03066 if (!p->answeronpolarityswitch) {
03067 return;
03068 }
03069
03070 my_set_polarity(pvt, 1);
03071 }
03072
03073 static void my_hangup_polarityswitch(void *pvt)
03074 {
03075 struct dahdi_pvt *p = pvt;
03076
03077 if (!p->hanguponpolarityswitch) {
03078 return;
03079 }
03080
03081 if (p->answeronpolarityswitch) {
03082 my_set_polarity(pvt, 0);
03083 } else {
03084 my_set_polarity(pvt, 1);
03085 }
03086 }
03087
03088 static int my_start(void *pvt)
03089 {
03090 struct dahdi_pvt *p = pvt;
03091 int x = DAHDI_START;
03092
03093 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03094 }
03095
03096 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03097 {
03098 int index = analogsub_to_dahdisub(sub);
03099 int res;
03100 struct dahdi_pvt *p = pvt;
03101 struct dahdi_dialoperation ddop;
03102
03103 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03104 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03105 return -1;
03106 }
03107
03108 if (sub != ANALOG_SUB_REAL) {
03109 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %u\n",
03110 dop->dialstr, p->channel, sub);
03111 return -1;
03112 }
03113
03114 ddop.op = DAHDI_DIAL_OP_REPLACE;
03115 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03116
03117 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03118
03119 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03120 if (res == -1) {
03121 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03122 }
03123
03124 return res;
03125 }
03126
03127 static void dahdi_train_ec(struct dahdi_pvt *p);
03128
03129 static int my_train_echocanceller(void *pvt)
03130 {
03131 struct dahdi_pvt *p = pvt;
03132
03133 dahdi_train_ec(p);
03134
03135 return 0;
03136 }
03137
03138 static int my_is_dialing(void *pvt, enum analog_sub sub)
03139 {
03140 struct dahdi_pvt *p = pvt;
03141 int index;
03142 int x;
03143
03144 index = analogsub_to_dahdisub(sub);
03145
03146 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03147 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03148 return -1;
03149 }
03150
03151 return x;
03152 }
03153
03154 static int my_on_hook(void *pvt)
03155 {
03156 struct dahdi_pvt *p = pvt;
03157 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03158 }
03159
03160 #if defined(HAVE_PRI)
03161 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03162 {
03163 struct dahdi_pvt *old_chan = chan_old;
03164 struct dahdi_pvt *new_chan = chan_new;
03165
03166 new_chan->owner = old_chan->owner;
03167 old_chan->owner = NULL;
03168 if (new_chan->owner) {
03169 ast_channel_tech_pvt_set(new_chan->owner, new_chan);
03170 ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
03171 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03172 old_chan->subs[SUB_REAL].owner = NULL;
03173 }
03174
03175 new_chan->dsp = old_chan->dsp;
03176 new_chan->dsp_features = old_chan->dsp_features;
03177 old_chan->dsp = NULL;
03178 old_chan->dsp_features = 0;
03179
03180
03181 new_chan->dialing = old_chan->dialing;
03182 new_chan->digital = old_chan->digital;
03183 new_chan->outgoing = old_chan->outgoing;
03184 old_chan->dialing = 0;
03185 old_chan->digital = 0;
03186 old_chan->outgoing = 0;
03187
03188
03189 new_chan->law = old_chan->law;
03190 strcpy(new_chan->dialstring, old_chan->dialstring);
03191 }
03192 #endif
03193
03194 #if defined(HAVE_PRI)
03195 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03196 {
03197 switch (tone) {
03198 case SIG_PRI_TONE_RINGTONE:
03199 return DAHDI_TONE_RINGTONE;
03200 case SIG_PRI_TONE_STUTTER:
03201 return DAHDI_TONE_STUTTER;
03202 case SIG_PRI_TONE_CONGESTION:
03203 return DAHDI_TONE_CONGESTION;
03204 case SIG_PRI_TONE_DIALTONE:
03205 return DAHDI_TONE_DIALTONE;
03206 case SIG_PRI_TONE_DIALRECALL:
03207 return DAHDI_TONE_DIALRECALL;
03208 case SIG_PRI_TONE_INFO:
03209 return DAHDI_TONE_INFO;
03210 case SIG_PRI_TONE_BUSY:
03211 return DAHDI_TONE_BUSY;
03212 default:
03213 return -1;
03214 }
03215 }
03216 #endif
03217
03218 #if defined(HAVE_PRI)
03219 static int pri_destroy_dchan(struct sig_pri_span *pri);
03220
03221 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03222 {
03223 int x;
03224
03225 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03226 switch (x) {
03227 case DAHDI_EVENT_NONE:
03228 break;
03229 case DAHDI_EVENT_ALARM:
03230 case DAHDI_EVENT_NOALARM:
03231 if (sig_pri_is_alarm_ignored(pri)) {
03232 break;
03233 }
03234
03235 default:
03236 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03237 event2str(x), x, pri->span);
03238 break;
03239 }
03240
03241 switch (x) {
03242 case DAHDI_EVENT_ALARM:
03243 pri_event_alarm(pri, index, 0);
03244 break;
03245 case DAHDI_EVENT_NOALARM:
03246 pri_event_noalarm(pri, index, 0);
03247 break;
03248 case DAHDI_EVENT_REMOVED:
03249 pri_destroy_dchan(pri);
03250 break;
03251 default:
03252 break;
03253 }
03254 }
03255 #endif
03256
03257 #if defined(HAVE_PRI)
03258 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03259 {
03260 struct dahdi_pvt *p = pvt;
03261
03262 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03263 }
03264 #endif
03265
03266 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03278 {
03279 struct dahdi_pvt *p = pvt;
03280
03281 ast_copy_string(p->cid_num,
03282 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03283 sizeof(p->cid_num));
03284 ast_copy_string(p->cid_name,
03285 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03286 sizeof(p->cid_name));
03287 ast_copy_string(p->cid_subaddr,
03288 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03289 sizeof(p->cid_subaddr));
03290 p->cid_ton = caller->id.number.plan;
03291 p->callingpres = ast_party_id_presentation(&caller->id);
03292 if (caller->id.tag) {
03293 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03294 }
03295 ast_copy_string(p->cid_ani,
03296 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03297 sizeof(p->cid_ani));
03298 p->cid_ani2 = caller->ani2;
03299 }
03300 #endif
03301
03302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313 static void my_set_dnid(void *pvt, const char *dnid)
03314 {
03315 struct dahdi_pvt *p = pvt;
03316
03317 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03318 }
03319 #endif
03320
03321 #if defined(HAVE_PRI)
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332 static void my_set_rdnis(void *pvt, const char *rdnis)
03333 {
03334 struct dahdi_pvt *p = pvt;
03335
03336 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03337 }
03338 #endif
03339
03340 #if defined(HAVE_PRI)
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03366 {
03367 char *dial;
03368 struct dahdi_pvt *pvt;
03369 AST_DECLARE_APP_ARGS(args,
03370 AST_APP_ARG(tech);
03371 AST_APP_ARG(group);
03372
03373
03374
03375 );
03376
03377 pvt = priv;
03378 dial = ast_strdupa(pvt->dialstring);
03379 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03380 if (!args.tech) {
03381 ast_copy_string(buf, pvt->dialstring, buf_size);
03382 return;
03383 }
03384 if (!args.group) {
03385
03386 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03387 return;
03388 }
03389 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03390
03391
03392 ast_copy_string(buf, pvt->dialstring, buf_size);
03393 return;
03394 }
03395
03396 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03397 }
03398 #endif
03399
03400 #if defined(HAVE_PRI)
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03413 {
03414 unsigned idx;
03415 unsigned num_b_chans;
03416 unsigned in_use;
03417 unsigned in_alarm;
03418 enum ast_device_state new_state;
03419
03420
03421 num_b_chans = 0;
03422 in_use = 0;
03423 in_alarm = 1;
03424 for (idx = pri->numchans; idx--;) {
03425 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03426
03427 ++num_b_chans;
03428 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03429 ++in_use;
03430 }
03431 if (!pri->pvts[idx]->inalarm) {
03432
03433 in_alarm = 0;
03434 }
03435 }
03436 }
03437
03438
03439 if (in_alarm) {
03440 new_state = AST_DEVICE_UNAVAILABLE;
03441 } else {
03442 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03443 }
03444 if (pri->congestion_devstate != new_state) {
03445 pri->congestion_devstate = new_state;
03446 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03447 }
03448 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03449
03450 if (in_alarm) {
03451 new_state = AST_DEVICE_UNAVAILABLE;
03452 } else if (!in_use) {
03453 new_state = AST_DEVICE_NOT_INUSE;
03454 } else if (!pri->user_busy_threshold) {
03455 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03456 } else {
03457 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03458 : AST_DEVICE_BUSY;
03459 }
03460 if (pri->threshold_devstate != new_state) {
03461 pri->threshold_devstate = new_state;
03462 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03463 }
03464 #endif
03465 }
03466 #endif
03467
03468 #if defined(HAVE_PRI)
03469
03470
03471
03472
03473
03474
03475
03476 static void my_module_ref(void)
03477 {
03478 ast_module_ref(ast_module_info->self);
03479 }
03480 #endif
03481
03482 #if defined(HAVE_PRI)
03483
03484
03485
03486
03487
03488
03489
03490 static void my_module_unref(void)
03491 {
03492 ast_module_unref(ast_module_info->self);
03493 }
03494 #endif
03495
03496 #if defined(HAVE_PRI)
03497 #if defined(HAVE_PRI_CALL_WAITING)
03498 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03499 #endif
03500 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03501
03502 struct sig_pri_callback sig_pri_callbacks =
03503 {
03504 .handle_dchan_exception = my_handle_dchan_exception,
03505 .play_tone = my_pri_play_tone,
03506 .set_echocanceller = my_set_echocanceller,
03507 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03508 .lock_private = my_lock_private,
03509 .unlock_private = my_unlock_private,
03510 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03511 .new_ast_channel = my_new_pri_ast_channel,
03512 .fixup_chans = my_pri_fixup_chans,
03513 .set_alarm = my_set_alarm,
03514 .set_dialing = my_set_dialing,
03515 .set_outgoing = my_set_outgoing,
03516 .set_digital = my_set_digital,
03517 .set_callerid = my_set_callerid,
03518 .set_dnid = my_set_dnid,
03519 .set_rdnis = my_set_rdnis,
03520 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03521 #if defined(HAVE_PRI_CALL_WAITING)
03522 .init_config = my_pri_init_config,
03523 #endif
03524 .get_orig_dialstring = my_get_orig_dialstring,
03525 .make_cc_dialstring = my_pri_make_cc_dialstring,
03526 .update_span_devstate = dahdi_pri_update_span_devstate,
03527 .module_ref = my_module_ref,
03528 .module_unref = my_module_unref,
03529 .dial_digits = my_pri_dial_digits,
03530 .open_media = my_pri_ss7_open_media,
03531 .ami_channel_event = my_ami_channel_event,
03532 };
03533 #endif
03534
03535 #if defined(HAVE_SS7)
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03547 {
03548 int event;
03549
03550 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03551 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03552 linkset->span, which);
03553 return;
03554 }
03555 switch (event) {
03556 case DAHDI_EVENT_NONE:
03557 break;
03558 case DAHDI_EVENT_ALARM:
03559 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03560 event2str(event), event, linkset->span, which);
03561 sig_ss7_link_alarm(linkset, which);
03562 break;
03563 case DAHDI_EVENT_NOALARM:
03564 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03565 event2str(event), event, linkset->span, which);
03566 sig_ss7_link_noalarm(linkset, which);
03567 break;
03568 default:
03569 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03570 event2str(event), event, linkset->span, which);
03571 break;
03572 }
03573 }
03574 #endif
03575
03576 #if defined(HAVE_SS7)
03577 static void my_ss7_set_loopback(void *pvt, int enable)
03578 {
03579 struct dahdi_pvt *p = pvt;
03580
03581 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03582 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03583 strerror(errno));
03584 }
03585 }
03586 #endif
03587
03588 #if defined(HAVE_SS7)
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603 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)
03604 {
03605 struct dahdi_pvt *p = pvt;
03606 int audio;
03607 int newlaw;
03608 struct ast_callid *callid = NULL;
03609 int callid_created = ast_callid_threadstorage_auto(&callid);
03610
03611
03612 audio = 1;
03613 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03614 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03615 p->channel, audio, strerror(errno));
03616
03617 if (law != SIG_SS7_DEFLAW) {
03618 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03619 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03620 }
03621
03622 ast_copy_string(p->exten, exten, sizeof(p->exten));
03623
03624 newlaw = -1;
03625 switch (law) {
03626 case SIG_SS7_DEFLAW:
03627 newlaw = 0;
03628 break;
03629 case SIG_SS7_ALAW:
03630 newlaw = DAHDI_LAW_ALAW;
03631 break;
03632 case SIG_SS7_ULAW:
03633 newlaw = DAHDI_LAW_MULAW;
03634 break;
03635 }
03636 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
03637 }
03638 #endif
03639
03640 #if defined(HAVE_SS7)
03641 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03642 {
03643 switch (tone) {
03644 case SIG_SS7_TONE_RINGTONE:
03645 return DAHDI_TONE_RINGTONE;
03646 case SIG_SS7_TONE_STUTTER:
03647 return DAHDI_TONE_STUTTER;
03648 case SIG_SS7_TONE_CONGESTION:
03649 return DAHDI_TONE_CONGESTION;
03650 case SIG_SS7_TONE_DIALTONE:
03651 return DAHDI_TONE_DIALTONE;
03652 case SIG_SS7_TONE_DIALRECALL:
03653 return DAHDI_TONE_DIALRECALL;
03654 case SIG_SS7_TONE_INFO:
03655 return DAHDI_TONE_INFO;
03656 case SIG_SS7_TONE_BUSY:
03657 return DAHDI_TONE_BUSY;
03658 default:
03659 return -1;
03660 }
03661 }
03662 #endif
03663
03664 #if defined(HAVE_SS7)
03665 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03666 {
03667 struct dahdi_pvt *p = pvt;
03668
03669 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03670 }
03671 #endif
03672
03673 #if defined(HAVE_SS7)
03674 struct sig_ss7_callback sig_ss7_callbacks =
03675 {
03676 .lock_private = my_lock_private,
03677 .unlock_private = my_unlock_private,
03678 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03679
03680 .set_echocanceller = my_set_echocanceller,
03681 .set_loopback = my_ss7_set_loopback,
03682
03683 .new_ast_channel = my_new_ss7_ast_channel,
03684 .play_tone = my_ss7_play_tone,
03685
03686 .handle_link_exception = my_handle_link_exception,
03687 .set_alarm = my_set_alarm,
03688 .set_dialing = my_set_dialing,
03689 .set_outgoing = my_set_outgoing,
03690 .set_digital = my_set_digital,
03691 .set_inservice = my_set_inservice,
03692 .set_locallyblocked = my_set_locallyblocked,
03693 .set_remotelyblocked = my_set_remotelyblocked,
03694 .set_callerid = my_set_callerid,
03695 .set_dnid = my_set_dnid,
03696 .open_media = my_pri_ss7_open_media,
03697 };
03698 #endif
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718 static void notify_message(char *mailbox_full, int thereornot)
03719 {
03720 char s[sizeof(mwimonitornotify) + 80];
03721 struct ast_event *event;
03722 char *mailbox, *context;
03723
03724
03725 context = mailbox = ast_strdupa(mailbox_full);
03726 strsep(&context, "@");
03727 if (ast_strlen_zero(context))
03728 context = "default";
03729
03730 if (!(event = ast_event_new(AST_EVENT_MWI,
03731 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03732 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03733 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03734 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03735 AST_EVENT_IE_END))) {
03736 return;
03737 }
03738
03739 ast_event_queue_and_cache(event);
03740
03741 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03742 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03743 ast_safe_system(s);
03744 }
03745 }
03746
03747 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03748 {
03749 struct dahdi_pvt *p = pvt;
03750
03751 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03752 return;
03753
03754 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03755 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03756 notify_message(p->mailbox, 1);
03757 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03758 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03759 notify_message(p->mailbox, 0);
03760 }
03761
03762
03763 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03764 ast_hangup(chan);
03765 return;
03766 }
03767 }
03768
03769 static int my_have_progressdetect(void *pvt)
03770 {
03771 struct dahdi_pvt *p = pvt;
03772
03773 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03774 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03775 return 1;
03776 } else {
03777
03778 return 0;
03779 }
03780 }
03781
03782 struct analog_callback analog_callbacks =
03783 {
03784 .play_tone = my_play_tone,
03785 .get_event = my_get_event,
03786 .wait_event = my_wait_event,
03787 .is_off_hook = my_is_off_hook,
03788 .set_echocanceller = my_set_echocanceller,
03789 .ring = my_ring,
03790 .flash = my_flash,
03791 .off_hook = my_off_hook,
03792 .dial_digits = my_dial_digits,
03793 .train_echocanceller = my_train_echocanceller,
03794 .on_hook = my_on_hook,
03795 .is_dialing = my_is_dialing,
03796 .allocate_sub = my_allocate_sub,
03797 .unallocate_sub = my_unallocate_sub,
03798 .swap_subs = my_swap_subchannels,
03799 .has_voicemail = my_has_voicemail,
03800 .check_for_conference = my_check_for_conference,
03801 .conf_add = my_conf_add,
03802 .conf_del = my_conf_del,
03803 .complete_conference_update = my_complete_conference_update,
03804 .start = my_start,
03805 .all_subchannels_hungup = my_all_subchannels_hungup,
03806 .lock_private = my_lock_private,
03807 .unlock_private = my_unlock_private,
03808 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03809 .handle_dtmf = my_handle_dtmf,
03810 .wink = my_wink,
03811 .new_ast_channel = my_new_analog_ast_channel,
03812 .dsp_set_digitmode = my_dsp_set_digitmode,
03813 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03814 .send_callerid = my_send_callerid,
03815 .callwait = my_callwait,
03816 .stop_callwait = my_stop_callwait,
03817 .get_callerid = my_get_callerid,
03818 .start_cid_detect = my_start_cid_detect,
03819 .stop_cid_detect = my_stop_cid_detect,
03820 .handle_notify_message = my_handle_notify_message,
03821 .increase_ss_count = my_increase_ss_count,
03822 .decrease_ss_count = my_decrease_ss_count,
03823 .distinctive_ring = my_distinctive_ring,
03824 .set_linear_mode = my_set_linear_mode,
03825 .set_inthreeway = my_set_inthreeway,
03826 .get_and_handle_alarms = my_get_and_handle_alarms,
03827 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03828 .get_sub_fd = my_get_sub_fd,
03829 .set_cadence = my_set_cadence,
03830 .set_alarm = my_set_alarm,
03831 .set_dialing = my_set_dialing,
03832 .set_outgoing = my_set_outgoing,
03833 .set_ringtimeout = my_set_ringtimeout,
03834 .set_waitingfordt = my_set_waitingfordt,
03835 .check_waitingfordt = my_check_waitingfordt,
03836 .set_confirmanswer = my_set_confirmanswer,
03837 .check_confirmanswer = my_check_confirmanswer,
03838 .set_callwaiting = my_set_callwaiting,
03839 .cancel_cidspill = my_cancel_cidspill,
03840 .confmute = my_confmute,
03841 .set_pulsedial = my_set_pulsedial,
03842 .set_new_owner = my_set_new_owner,
03843 .get_orig_dialstring = my_get_orig_dialstring,
03844 .set_needringing = my_set_needringing,
03845 .set_polarity = my_set_polarity,
03846 .start_polarityswitch = my_start_polarityswitch,
03847 .answer_polarityswitch = my_answer_polarityswitch,
03848 .hangup_polarityswitch = my_hangup_polarityswitch,
03849 .have_progressdetect = my_have_progressdetect,
03850 };
03851
03852
03853 static struct dahdi_pvt *round_robin[32];
03854
03855 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03856 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03857 {
03858 int res;
03859 if (p->subs[SUB_REAL].owner == ast)
03860 res = 0;
03861 else if (p->subs[SUB_CALLWAIT].owner == ast)
03862 res = 1;
03863 else if (p->subs[SUB_THREEWAY].owner == ast)
03864 res = 2;
03865 else {
03866 res = -1;
03867 if (!nullok)
03868 ast_log(LOG_WARNING,
03869 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03870 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03871 }
03872 return res;
03873 }
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03891 {
03892 for (;;) {
03893 if (!pvt->subs[sub_idx].owner) {
03894
03895 break;
03896 }
03897 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03898
03899 break;
03900 }
03901
03902 DEADLOCK_AVOIDANCE(&pvt->lock);
03903 }
03904 }
03905
03906 static void wakeup_sub(struct dahdi_pvt *p, int a)
03907 {
03908 dahdi_lock_sub_owner(p, a);
03909 if (p->subs[a].owner) {
03910 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03911 ast_channel_unlock(p->subs[a].owner);
03912 }
03913 }
03914
03915 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03916 {
03917 for (;;) {
03918 if (p->owner) {
03919 if (ast_channel_trylock(p->owner)) {
03920 DEADLOCK_AVOIDANCE(&p->lock);
03921 } else {
03922 ast_queue_frame(p->owner, f);
03923 ast_channel_unlock(p->owner);
03924 break;
03925 }
03926 } else
03927 break;
03928 }
03929 }
03930
03931 static void handle_clear_alarms(struct dahdi_pvt *p)
03932 {
03933 #if defined(HAVE_PRI)
03934 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03935 return;
03936 }
03937 #endif
03938
03939 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03940 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03941
03942
03943
03944
03945
03946 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03947 }
03948 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03949 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03950
03951
03952
03953
03954
03955 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03956 }
03957 }
03958
03959 #ifdef HAVE_OPENR2
03960
03961 static int dahdi_r2_answer(struct dahdi_pvt *p)
03962 {
03963 int res = 0;
03964
03965
03966
03967 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03968 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03969 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03970 if (!double_answer) {
03971
03972
03973 res = openr2_chan_answer_call(p->r2chan);
03974 } else if (wants_double_answer) {
03975 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03976 } else {
03977 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03978 }
03979 #else
03980 res = openr2_chan_answer_call(p->r2chan);
03981 #endif
03982 return res;
03983 }
03984
03985
03986
03987
03988 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03989 {
03990 openr2_calling_party_category_t cat;
03991 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03992 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
03993 if (ast_strlen_zero(catstr)) {
03994 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03995 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03996 return p->mfcr2_category;
03997 }
03998 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03999 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
04000 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
04001 return p->mfcr2_category;
04002 }
04003 ast_debug(1, "Using category %s\n", catstr);
04004 return cat;
04005 }
04006
04007 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
04008 {
04009 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04010 ast_mutex_lock(&p->lock);
04011 if (p->mfcr2call) {
04012 ast_mutex_unlock(&p->lock);
04013
04014
04015
04016
04017
04018 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
04019 return;
04020 }
04021 p->mfcr2call = 1;
04022
04023 p->cid_name[0] = '\0';
04024 p->cid_num[0] = '\0';
04025 p->cid_subaddr[0] = '\0';
04026 p->rdnis[0] = '\0';
04027 p->exten[0] = '\0';
04028 p->mfcr2_ani_index = '\0';
04029 p->mfcr2_dnis_index = '\0';
04030 p->mfcr2_dnis_matched = 0;
04031 p->mfcr2_answer_pending = 0;
04032 p->mfcr2_call_accepted = 0;
04033 ast_mutex_unlock(&p->lock);
04034 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
04035 }
04036
04037 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
04038 {
04039 int res;
04040 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04041 ast_mutex_lock(&p->lock);
04042 p->inalarm = alarm ? 1 : 0;
04043 if (p->inalarm) {
04044 res = get_alarms(p);
04045 handle_alarms(p, res);
04046 } else {
04047 handle_clear_alarms(p);
04048 }
04049 ast_mutex_unlock(&p->lock);
04050 }
04051
04052 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
04053 {
04054 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
04055 }
04056
04057 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
04058 {
04059 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04060 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
04061 if (p->owner) {
04062 ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
04063 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04064 }
04065 ast_mutex_lock(&p->lock);
04066 p->mfcr2call = 0;
04067 ast_mutex_unlock(&p->lock);
04068 }
04069
04070 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04071 {
04072 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04073 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04074 p->channel, openr2_proto_get_disconnect_string(cause));
04075
04076 openr2_chan_set_idle(p->r2chan);
04077 ast_mutex_lock(&p->lock);
04078 p->mfcr2call = 0;
04079 ast_mutex_unlock(&p->lock);
04080 }
04081 }
04082
04083 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04084 {
04085 struct dahdi_pvt *p;
04086 struct ast_channel *c;
04087 struct ast_callid *callid = NULL;
04088 int callid_created = ast_callid_threadstorage_auto(&callid);
04089 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04090 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04091 openr2_proto_get_category_string(category));
04092 p = openr2_chan_get_client_data(r2chan);
04093
04094 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04095 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04096 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04097 goto dahdi_r2_on_call_offered_cleanup;
04098 }
04099 ast_mutex_lock(&p->lock);
04100 p->mfcr2_recvd_category = category;
04101
04102 if (!p->use_callerid) {
04103 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
04104 p->cid_num[0] = 0;
04105 p->cid_name[0] = 0;
04106 }
04107
04108 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04109 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
04110 p->exten[0] = 's';
04111 p->exten[1] = 0;
04112 }
04113 ast_mutex_unlock(&p->lock);
04114 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04115 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04116 p->channel, p->exten, p->context);
04117 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04118 goto dahdi_r2_on_call_offered_cleanup;
04119 }
04120 if (!p->mfcr2_accept_on_offer) {
04121
04122 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04123 if (c) {
04124
04125
04126
04127 goto dahdi_r2_on_call_offered_cleanup;
04128 }
04129 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04130 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04131 } else if (p->mfcr2_charge_calls) {
04132 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04133 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04134 } else {
04135 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04136 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04137 }
04138
04139 dahdi_r2_on_call_offered_cleanup:
04140 ast_callid_threadstorage_auto_clean(callid, callid_created);
04141 }
04142
04143 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04144 {
04145 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04146 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04147 ast_mutex_lock(&p->lock);
04148 p->mfcr2call = 0;
04149 ast_mutex_unlock(&p->lock);
04150 }
04151
04152 static void dahdi_enable_ec(struct dahdi_pvt *p);
04153 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04154 {
04155 struct dahdi_pvt *p = NULL;
04156 struct ast_channel *c = NULL;
04157 struct ast_callid *callid = NULL;
04158 int callid_created = ast_callid_threadstorage_auto(&callid);
04159 p = openr2_chan_get_client_data(r2chan);
04160 dahdi_enable_ec(p);
04161 p->mfcr2_call_accepted = 1;
04162
04163 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04164 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04165
04166
04167
04168
04169 if (!p->mfcr2_accept_on_offer) {
04170 openr2_chan_disable_read(r2chan);
04171 if (p->mfcr2_answer_pending) {
04172 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04173 dahdi_r2_answer(p);
04174 }
04175 goto dahdi_r2_on_call_accepted_cleanup;
04176 }
04177 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04178 if (c) {
04179
04180
04181 openr2_chan_disable_read(r2chan);
04182 goto dahdi_r2_on_call_accepted_cleanup;
04183 }
04184 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04185
04186 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04187 goto dahdi_r2_on_call_accepted_cleanup;
04188 }
04189
04190 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04191 p->subs[SUB_REAL].needringing = 1;
04192 p->dialing = 0;
04193
04194 openr2_chan_disable_read(r2chan);
04195
04196 dahdi_r2_on_call_accepted_cleanup:
04197 ast_callid_threadstorage_auto_clean(callid, callid_created);
04198 }
04199
04200 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04201 {
04202 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04203 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04204 p->subs[SUB_REAL].needanswer = 1;
04205 }
04206
04207 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04208 {
04209
04210 }
04211
04212 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04213 {
04214 switch (cause) {
04215 case OR2_CAUSE_BUSY_NUMBER:
04216 return AST_CAUSE_BUSY;
04217 case OR2_CAUSE_NETWORK_CONGESTION:
04218 return AST_CAUSE_CONGESTION;
04219 case OR2_CAUSE_OUT_OF_ORDER:
04220 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04221 case OR2_CAUSE_UNALLOCATED_NUMBER:
04222 return AST_CAUSE_UNREGISTERED;
04223 case OR2_CAUSE_NO_ANSWER:
04224 return AST_CAUSE_NO_ANSWER;
04225 case OR2_CAUSE_NORMAL_CLEARING:
04226 return AST_CAUSE_NORMAL_CLEARING;
04227 case OR2_CAUSE_UNSPECIFIED:
04228 default:
04229 return AST_CAUSE_NOTDEFINED;
04230 }
04231 }
04232
04233 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04234 {
04235 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04236 char cause_str[50];
04237 struct ast_control_pvt_cause_code *cause_code;
04238 int datalen = sizeof(*cause_code);
04239
04240 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04241 ast_mutex_lock(&p->lock);
04242 if (!p->owner) {
04243 ast_mutex_unlock(&p->lock);
04244
04245 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04246 return;
04247 }
04248
04249 snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
04250 datalen += strlen(cause_str);
04251 cause_code = ast_alloca(datalen);
04252 memset(cause_code, 0, datalen);
04253 cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
04254 ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
04255 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
04256 ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
04257 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
04258
04259
04260
04261 if (ast_channel_state(p->owner) == AST_STATE_UP) {
04262 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04263 ast_mutex_unlock(&p->lock);
04264 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04265
04266 switch (cause) {
04267 case OR2_CAUSE_BUSY_NUMBER:
04268 p->subs[SUB_REAL].needbusy = 1;
04269 break;
04270 case OR2_CAUSE_NETWORK_CONGESTION:
04271 case OR2_CAUSE_OUT_OF_ORDER:
04272 case OR2_CAUSE_UNALLOCATED_NUMBER:
04273 case OR2_CAUSE_NO_ANSWER:
04274 case OR2_CAUSE_UNSPECIFIED:
04275 case OR2_CAUSE_NORMAL_CLEARING:
04276 p->subs[SUB_REAL].needcongestion = 1;
04277 break;
04278 default:
04279 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04280 }
04281 ast_mutex_unlock(&p->lock);
04282 } else {
04283 ast_mutex_unlock(&p->lock);
04284
04285
04286 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04287 }
04288 }
04289
04290 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04291 {
04292 switch (level) {
04293 case OR2_LOG_NOTICE:
04294 ast_verbose("%s", logmessage);
04295 break;
04296 case OR2_LOG_WARNING:
04297 ast_log(LOG_WARNING, "%s", logmessage);
04298 break;
04299 case OR2_LOG_ERROR:
04300 ast_log(LOG_ERROR, "%s", logmessage);
04301 break;
04302 case OR2_LOG_STACK_TRACE:
04303 case OR2_LOG_MF_TRACE:
04304 case OR2_LOG_CAS_TRACE:
04305 case OR2_LOG_DEBUG:
04306 case OR2_LOG_EX_DEBUG:
04307 ast_debug(1, "%s", logmessage);
04308 break;
04309 default:
04310 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04311 ast_debug(1, "%s", logmessage);
04312 break;
04313 }
04314 }
04315
04316 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04317 {
04318 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04319 ast_mutex_lock(&p->lock);
04320 p->remotelyblocked = 1;
04321 ast_mutex_unlock(&p->lock);
04322 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04323 }
04324
04325 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04326 {
04327 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04328 ast_mutex_lock(&p->lock);
04329 p->remotelyblocked = 0;
04330 ast_mutex_unlock(&p->lock);
04331 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04332 }
04333
04334 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04335 __attribute__((format (printf, 3, 0)));
04336 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04337 {
04338 #define CONTEXT_TAG "Context - "
04339 char logmsg[256];
04340 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04341 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04342 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04343 dahdi_r2_write_log(level, completemsg);
04344 #undef CONTEXT_TAG
04345 }
04346
04347 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04348 __attribute__((format (printf, 3, 0)));
04349 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04350 {
04351 #define CHAN_TAG "Chan "
04352 char logmsg[256];
04353 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04354 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04355 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04356 dahdi_r2_write_log(level, completemsg);
04357 }
04358
04359 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04360 {
04361 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04362
04363 if (p->immediate) {
04364 return 0;
04365 }
04366 p->exten[p->mfcr2_dnis_index] = digit;
04367 p->rdnis[p->mfcr2_dnis_index] = digit;
04368 p->mfcr2_dnis_index++;
04369 p->exten[p->mfcr2_dnis_index] = 0;
04370 p->rdnis[p->mfcr2_dnis_index] = 0;
04371
04372 if ((p->mfcr2_dnis_matched ||
04373 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04374 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04375 return 0;
04376 }
04377
04378 return 1;
04379 }
04380
04381 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04382 {
04383 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04384 p->cid_num[p->mfcr2_ani_index] = digit;
04385 p->cid_name[p->mfcr2_ani_index] = digit;
04386 p->mfcr2_ani_index++;
04387 p->cid_num[p->mfcr2_ani_index] = 0;
04388 p->cid_name[p->mfcr2_ani_index] = 0;
04389 }
04390
04391 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04392 {
04393 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04394 }
04395
04396 static openr2_event_interface_t dahdi_r2_event_iface = {
04397 .on_call_init = dahdi_r2_on_call_init,
04398 .on_call_offered = dahdi_r2_on_call_offered,
04399 .on_call_accepted = dahdi_r2_on_call_accepted,
04400 .on_call_answered = dahdi_r2_on_call_answered,
04401 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04402 .on_call_end = dahdi_r2_on_call_end,
04403 .on_call_read = dahdi_r2_on_call_read,
04404 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04405 .on_os_error = dahdi_r2_on_os_error,
04406 .on_protocol_error = dahdi_r2_on_protocol_error,
04407 .on_line_blocked = dahdi_r2_on_line_blocked,
04408 .on_line_idle = dahdi_r2_on_line_idle,
04409
04410 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04411 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04412 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04413
04414 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04415 };
04416
04417 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04418 {
04419 return AST_ALAW(sample);
04420 }
04421
04422 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04423 {
04424 return AST_LIN2A(sample);
04425 }
04426
04427 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04428 dahdi_r2_alaw_to_linear,
04429 dahdi_r2_linear_to_alaw
04430 };
04431
04432 #endif
04433
04434 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04435 {
04436 int tchan;
04437 int tinthreeway;
04438 struct ast_channel *towner;
04439
04440 ast_debug(1, "Swapping %d and %d\n", a, b);
04441
04442 tchan = p->subs[a].chan;
04443 towner = p->subs[a].owner;
04444 tinthreeway = p->subs[a].inthreeway;
04445
04446 p->subs[a].chan = p->subs[b].chan;
04447 p->subs[a].owner = p->subs[b].owner;
04448 p->subs[a].inthreeway = p->subs[b].inthreeway;
04449
04450 p->subs[b].chan = tchan;
04451 p->subs[b].owner = towner;
04452 p->subs[b].inthreeway = tinthreeway;
04453
04454 if (p->subs[a].owner)
04455 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04456 if (p->subs[b].owner)
04457 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04458 wakeup_sub(p, a);
04459 wakeup_sub(p, b);
04460 }
04461
04462 static int dahdi_open(char *fn)
04463 {
04464 int fd;
04465 int isnum;
04466 int chan = 0;
04467 int bs;
04468 int x;
04469 isnum = 1;
04470 for (x = 0; x < strlen(fn); x++) {
04471 if (!isdigit(fn[x])) {
04472 isnum = 0;
04473 break;
04474 }
04475 }
04476 if (isnum) {
04477 chan = atoi(fn);
04478 if (chan < 1) {
04479 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04480 return -1;
04481 }
04482 fn = "/dev/dahdi/channel";
04483 }
04484 fd = open(fn, O_RDWR | O_NONBLOCK);
04485 if (fd < 0) {
04486 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04487 return -1;
04488 }
04489 if (chan) {
04490 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04491 x = errno;
04492 close(fd);
04493 errno = x;
04494 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04495 return -1;
04496 }
04497 }
04498 bs = READ_SIZE;
04499 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04500 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04501 x = errno;
04502 close(fd);
04503 errno = x;
04504 return -1;
04505 }
04506 return fd;
04507 }
04508
04509 static void dahdi_close(int fd)
04510 {
04511 if (fd > 0)
04512 close(fd);
04513 }
04514
04515 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04516 {
04517 dahdi_close(chan_pvt->subs[sub_num].dfd);
04518 chan_pvt->subs[sub_num].dfd = -1;
04519 }
04520
04521 #if defined(HAVE_PRI)
04522 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04523 {
04524 dahdi_close(pri->pri.fds[fd_num]);
04525 pri->pri.fds[fd_num] = -1;
04526 }
04527 #endif
04528
04529 #if defined(HAVE_SS7)
04530 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04531 {
04532 dahdi_close(ss7->ss7.fds[fd_num]);
04533 ss7->ss7.fds[fd_num] = -1;
04534 }
04535 #endif
04536
04537 static int dahdi_setlinear(int dfd, int linear)
04538 {
04539 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04540 }
04541
04542
04543 static int alloc_sub(struct dahdi_pvt *p, int x)
04544 {
04545 struct dahdi_bufferinfo bi;
04546 int res;
04547 if (p->subs[x].dfd >= 0) {
04548 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04549 return -1;
04550 }
04551
04552 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04553 if (p->subs[x].dfd <= -1) {
04554 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04555 return -1;
04556 }
04557
04558 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04559 if (!res) {
04560 bi.txbufpolicy = p->buf_policy;
04561 bi.rxbufpolicy = p->buf_policy;
04562 bi.numbufs = p->buf_no;
04563 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04564 if (res < 0) {
04565 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04566 }
04567 } else
04568 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04569
04570 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04571 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04572 dahdi_close_sub(p, x);
04573 p->subs[x].dfd = -1;
04574 return -1;
04575 }
04576 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04577 return 0;
04578 }
04579
04580 static int unalloc_sub(struct dahdi_pvt *p, int x)
04581 {
04582 if (!x) {
04583 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04584 return -1;
04585 }
04586 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04587 dahdi_close_sub(p, x);
04588 p->subs[x].linear = 0;
04589 p->subs[x].chan = 0;
04590 p->subs[x].owner = NULL;
04591 p->subs[x].inthreeway = 0;
04592 p->polarity = POLARITY_IDLE;
04593 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04594 return 0;
04595 }
04596
04597 static int digit_to_dtmfindex(char digit)
04598 {
04599 if (isdigit(digit))
04600 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04601 else if (digit >= 'A' && digit <= 'D')
04602 return DAHDI_TONE_DTMF_A + (digit - 'A');
04603 else if (digit >= 'a' && digit <= 'd')
04604 return DAHDI_TONE_DTMF_A + (digit - 'a');
04605 else if (digit == '*')
04606 return DAHDI_TONE_DTMF_s;
04607 else if (digit == '#')
04608 return DAHDI_TONE_DTMF_p;
04609 else
04610 return -1;
04611 }
04612
04613 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04614 {
04615 struct dahdi_pvt *pvt;
04616 int idx;
04617 int dtmf = -1;
04618 int res;
04619
04620 pvt = ast_channel_tech_pvt(chan);
04621
04622 ast_mutex_lock(&pvt->lock);
04623
04624 idx = dahdi_get_index(chan, pvt, 0);
04625
04626 if ((idx != SUB_REAL) || !pvt->owner)
04627 goto out;
04628
04629 #ifdef HAVE_PRI
04630 switch (pvt->sig) {
04631 case SIG_PRI_LIB_HANDLE_CASES:
04632 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04633 if (!res)
04634 goto out;
04635 break;
04636 default:
04637 break;
04638 }
04639 #endif
04640 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04641 goto out;
04642
04643 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04644 struct dahdi_dialoperation zo = {
04645 .op = DAHDI_DIAL_OP_APPEND,
04646 };
04647
04648 zo.dialstr[0] = 'T';
04649 zo.dialstr[1] = digit;
04650 zo.dialstr[2] = '\0';
04651 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04652 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04653 ast_channel_name(chan), digit, strerror(errno));
04654 else
04655 pvt->dialing = 1;
04656 } else {
04657 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04658 ast_channel_name(chan), digit);
04659 pvt->dialing = 1;
04660 pvt->begindigit = digit;
04661 }
04662
04663 out:
04664 ast_mutex_unlock(&pvt->lock);
04665
04666 return 0;
04667 }
04668
04669 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04670 {
04671 struct dahdi_pvt *pvt;
04672 int res = 0;
04673 int idx;
04674 int x;
04675
04676 pvt = ast_channel_tech_pvt(chan);
04677
04678 ast_mutex_lock(&pvt->lock);
04679
04680 idx = dahdi_get_index(chan, pvt, 0);
04681
04682 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04683 goto out;
04684
04685 #ifdef HAVE_PRI
04686
04687 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04688 goto out;
04689 }
04690 #endif
04691
04692 if (pvt->begindigit) {
04693 x = -1;
04694 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04695 ast_channel_name(chan), digit);
04696 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04697 pvt->dialing = 0;
04698 pvt->begindigit = 0;
04699 }
04700
04701 out:
04702 ast_mutex_unlock(&pvt->lock);
04703
04704 return res;
04705 }
04706
04707 static const char * const events[] = {
04708 "No event",
04709 "On hook",
04710 "Ring/Answered",
04711 "Wink/Flash",
04712 "Alarm",
04713 "No more alarm",
04714 "HDLC Abort",
04715 "HDLC Overrun",
04716 "HDLC Bad FCS",
04717 "Dial Complete",
04718 "Ringer On",
04719 "Ringer Off",
04720 "Hook Transition Complete",
04721 "Bits Changed",
04722 "Pulse Start",
04723 "Timer Expired",
04724 "Timer Ping",
04725 "Polarity Reversal",
04726 "Ring Begin",
04727 };
04728
04729 static struct {
04730 int alarm;
04731 char *name;
04732 } alarms[] = {
04733 { DAHDI_ALARM_RED, "Red Alarm" },
04734 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04735 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04736 { DAHDI_ALARM_RECOVER, "Recovering" },
04737 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04738 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04739 { DAHDI_ALARM_NONE, "None" },
04740 };
04741
04742 static char *alarm2str(int alm)
04743 {
04744 int x;
04745 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04746 if (alarms[x].alarm & alm)
04747 return alarms[x].name;
04748 }
04749 return alm ? "Unknown Alarm" : "No Alarm";
04750 }
04751
04752 static const char *event2str(int event)
04753 {
04754 static char buf[256];
04755 if ((event < (ARRAY_LEN(events))) && (event > -1))
04756 return events[event];
04757 sprintf(buf, "Event %d", event);
04758 return buf;
04759 }
04760
04761 static char *dahdi_sig2str(int sig)
04762 {
04763 static char buf[256];
04764 switch (sig) {
04765 case SIG_EM:
04766 return "E & M Immediate";
04767 case SIG_EMWINK:
04768 return "E & M Wink";
04769 case SIG_EM_E1:
04770 return "E & M E1";
04771 case SIG_FEATD:
04772 return "Feature Group D (DTMF)";
04773 case SIG_FEATDMF:
04774 return "Feature Group D (MF)";
04775 case SIG_FEATDMF_TA:
04776 return "Feature Groud D (MF) Tandem Access";
04777 case SIG_FEATB:
04778 return "Feature Group B (MF)";
04779 case SIG_E911:
04780 return "E911 (MF)";
04781 case SIG_FGC_CAMA:
04782 return "FGC/CAMA (Dialpulse)";
04783 case SIG_FGC_CAMAMF:
04784 return "FGC/CAMA (MF)";
04785 case SIG_FXSLS:
04786 return "FXS Loopstart";
04787 case SIG_FXSGS:
04788 return "FXS Groundstart";
04789 case SIG_FXSKS:
04790 return "FXS Kewlstart";
04791 case SIG_FXOLS:
04792 return "FXO Loopstart";
04793 case SIG_FXOGS:
04794 return "FXO Groundstart";
04795 case SIG_FXOKS:
04796 return "FXO Kewlstart";
04797 case SIG_PRI:
04798 return "ISDN PRI";
04799 case SIG_BRI:
04800 return "ISDN BRI Point to Point";
04801 case SIG_BRI_PTMP:
04802 return "ISDN BRI Point to MultiPoint";
04803 case SIG_SS7:
04804 return "SS7";
04805 case SIG_MFCR2:
04806 return "MFC/R2";
04807 case SIG_SF:
04808 return "SF (Tone) Immediate";
04809 case SIG_SFWINK:
04810 return "SF (Tone) Wink";
04811 case SIG_SF_FEATD:
04812 return "SF (Tone) with Feature Group D (DTMF)";
04813 case SIG_SF_FEATDMF:
04814 return "SF (Tone) with Feature Group D (MF)";
04815 case SIG_SF_FEATB:
04816 return "SF (Tone) with Feature Group B (MF)";
04817 case 0:
04818 return "Pseudo";
04819 default:
04820 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04821 return buf;
04822 }
04823 }
04824
04825 #define sig2str dahdi_sig2str
04826
04827 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04828 {
04829
04830
04831 struct dahdi_confinfo zi;
04832
04833 memset(&zi, 0, sizeof(zi));
04834 zi.chan = 0;
04835
04836 if (slavechannel > 0) {
04837
04838 zi.confmode = DAHDI_CONF_DIGITALMON;
04839 zi.confno = slavechannel;
04840 } else {
04841 if (!idx) {
04842
04843 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04844 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04845 } else
04846 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04847 zi.confno = p->confno;
04848 }
04849 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04850 return 0;
04851 if (c->dfd < 0)
04852 return 0;
04853 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04854 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04855 return -1;
04856 }
04857 if (slavechannel < 1) {
04858 p->confno = zi.confno;
04859 }
04860 c->curconf = zi;
04861 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04862 return 0;
04863 }
04864
04865 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04866 {
04867
04868 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04869 return 1;
04870
04871 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04872 return 1;
04873 return 0;
04874 }
04875
04876 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04877 {
04878 struct dahdi_confinfo zi;
04879 if (
04880 (c->dfd < 0) ||
04881
04882 !isourconf(p, c)
04883
04884 ) return 0;
04885 memset(&zi, 0, sizeof(zi));
04886 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04887 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04888 return -1;
04889 }
04890 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04891 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04892 return 0;
04893 }
04894
04895 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04896 {
04897 int x;
04898 int useslavenative;
04899 struct dahdi_pvt *slave = NULL;
04900
04901 useslavenative = 1;
04902
04903 for (x = 0; x < 3; x++) {
04904
04905
04906 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04907 useslavenative = 0;
04908 }
04909
04910
04911 if (useslavenative) {
04912 for (x = 0; x < MAX_SLAVES; x++) {
04913 if (p->slaves[x]) {
04914 if (slave) {
04915
04916
04917 slave = NULL;
04918 useslavenative = 0;
04919 break;
04920 } else {
04921
04922 slave = p->slaves[x];
04923 }
04924 }
04925 }
04926 }
04927
04928 if (!slave)
04929 useslavenative = 0;
04930 else if (slave->law != p->law) {
04931 useslavenative = 0;
04932 slave = NULL;
04933 }
04934 if (out)
04935 *out = slave;
04936 return useslavenative;
04937 }
04938
04939 static int reset_conf(struct dahdi_pvt *p)
04940 {
04941 p->confno = -1;
04942 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04943 if (p->subs[SUB_REAL].dfd > -1) {
04944 struct dahdi_confinfo zi;
04945
04946 memset(&zi, 0, sizeof(zi));
04947 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04948 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04949 }
04950 return 0;
04951 }
04952
04953 static int update_conf(struct dahdi_pvt *p)
04954 {
04955 int needconf = 0;
04956 int x;
04957 int useslavenative;
04958 struct dahdi_pvt *slave = NULL;
04959
04960 useslavenative = isslavenative(p, &slave);
04961
04962 for (x = 0; x < 3; x++) {
04963
04964 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04965 conf_add(p, &p->subs[x], x, 0);
04966 needconf++;
04967 } else {
04968 conf_del(p, &p->subs[x], x);
04969 }
04970 }
04971
04972
04973 for (x = 0; x < MAX_SLAVES; x++) {
04974 if (p->slaves[x]) {
04975 if (useslavenative)
04976 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04977 else {
04978 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04979 needconf++;
04980 }
04981 }
04982 }
04983
04984 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04985 if (useslavenative)
04986 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04987 else {
04988 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04989 needconf++;
04990 }
04991 }
04992
04993 if (p->master) {
04994 if (isslavenative(p->master, NULL)) {
04995 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04996 } else {
04997 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04998 }
04999 }
05000 if (!needconf) {
05001
05002
05003 p->confno = -1;
05004 }
05005 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
05006 return 0;
05007 }
05008
05009 static void dahdi_enable_ec(struct dahdi_pvt *p)
05010 {
05011 int res;
05012 if (!p)
05013 return;
05014 if (p->echocanon) {
05015 ast_debug(1, "Echo cancellation already on\n");
05016 return;
05017 }
05018 if (p->digital) {
05019 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
05020 return;
05021 }
05022 if (p->echocancel.head.tap_length) {
05023 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05024 switch (p->sig) {
05025 #if defined(HAVE_PRI)
05026 case SIG_PRI_LIB_HANDLE_CASES:
05027 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05028
05029
05030
05031
05032 return;
05033 }
05034
05035 #endif
05036 #if defined(HAVE_SS7)
05037 case SIG_SS7:
05038 #endif
05039 {
05040 int x = 1;
05041
05042 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
05043 if (res)
05044 ast_log(LOG_WARNING,
05045 "Unable to enable audio mode on channel %d (%s)\n",
05046 p->channel, strerror(errno));
05047 }
05048 break;
05049 default:
05050 break;
05051 }
05052 #endif
05053 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
05054 if (res) {
05055 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
05056 } else {
05057 p->echocanon = 1;
05058 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
05059 }
05060 } else
05061 ast_debug(1, "No echo cancellation requested\n");
05062 }
05063
05064 static void dahdi_train_ec(struct dahdi_pvt *p)
05065 {
05066 int x;
05067 int res;
05068
05069 if (p && p->echocanon && p->echotraining) {
05070 x = p->echotraining;
05071 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
05072 if (res)
05073 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
05074 else
05075 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
05076 } else {
05077 ast_debug(1, "No echo training requested\n");
05078 }
05079 }
05080
05081 static void dahdi_disable_ec(struct dahdi_pvt *p)
05082 {
05083 int res;
05084
05085 if (p->echocanon) {
05086 struct dahdi_echocanparams ecp = { .tap_length = 0 };
05087
05088 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
05089
05090 if (res)
05091 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
05092 else
05093 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05094 }
05095
05096 p->echocanon = 0;
05097 }
05098
05099
05100 static int drc_sample(int sample, float drc)
05101 {
05102 float neg;
05103 float shallow, steep;
05104 float max = SHRT_MAX;
05105
05106 neg = (sample < 0 ? -1 : 1);
05107 steep = drc*sample;
05108 shallow = neg*(max-max/drc)+(float)sample/drc;
05109 if (abs(steep) < abs(shallow)) {
05110 sample = steep;
05111 }
05112 else {
05113 sample = shallow;
05114 }
05115
05116 return sample;
05117 }
05118
05119
05120 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05121 {
05122 int j;
05123 int k;
05124
05125 float linear_gain = pow(10.0, gain / 20.0);
05126
05127 switch (law) {
05128 case DAHDI_LAW_ALAW:
05129 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05130 if (gain || drc) {
05131 k = AST_ALAW(j);
05132 if (drc) {
05133 k = drc_sample(k, drc);
05134 }
05135 k = (float)k * linear_gain;
05136 if (k > 32767) {
05137 k = 32767;
05138 } else if (k < -32768) {
05139 k = -32768;
05140 }
05141 g->txgain[j] = AST_LIN2A(k);
05142 } else {
05143 g->txgain[j] = j;
05144 }
05145 }
05146 break;
05147 case DAHDI_LAW_MULAW:
05148 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05149 if (gain || drc) {
05150 k = AST_MULAW(j);
05151 if (drc) {
05152 k = drc_sample(k, drc);
05153 }
05154 k = (float)k * linear_gain;
05155 if (k > 32767) {
05156 k = 32767;
05157 } else if (k < -32768) {
05158 k = -32768;
05159 }
05160 g->txgain[j] = AST_LIN2MU(k);
05161
05162 } else {
05163 g->txgain[j] = j;
05164 }
05165 }
05166 break;
05167 }
05168 }
05169
05170 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05171 {
05172 int j;
05173 int k;
05174 float linear_gain = pow(10.0, gain / 20.0);
05175
05176 switch (law) {
05177 case DAHDI_LAW_ALAW:
05178 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05179 if (gain || drc) {
05180 k = AST_ALAW(j);
05181 if (drc) {
05182 k = drc_sample(k, drc);
05183 }
05184 k = (float)k * linear_gain;
05185 if (k > 32767) {
05186 k = 32767;
05187 } else if (k < -32768) {
05188 k = -32768;
05189 }
05190 g->rxgain[j] = AST_LIN2A(k);
05191 } else {
05192 g->rxgain[j] = j;
05193 }
05194 }
05195 break;
05196 case DAHDI_LAW_MULAW:
05197 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05198 if (gain || drc) {
05199 k = AST_MULAW(j);
05200 if (drc) {
05201 k = drc_sample(k, drc);
05202 }
05203 k = (float)k * linear_gain;
05204 if (k > 32767) {
05205 k = 32767;
05206 } else if (k < -32768) {
05207 k = -32768;
05208 }
05209 g->rxgain[j] = AST_LIN2MU(k);
05210 } else {
05211 g->rxgain[j] = j;
05212 }
05213 }
05214 break;
05215 }
05216 }
05217
05218 static int set_actual_txgain(int fd, float gain, float drc, int law)
05219 {
05220 struct dahdi_gains g;
05221 int res;
05222
05223 memset(&g, 0, sizeof(g));
05224 res = ioctl(fd, DAHDI_GETGAINS, &g);
05225 if (res) {
05226 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05227 return res;
05228 }
05229
05230 fill_txgain(&g, gain, drc, law);
05231
05232 return ioctl(fd, DAHDI_SETGAINS, &g);
05233 }
05234
05235 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05236 {
05237 struct dahdi_gains g;
05238 int res;
05239
05240 memset(&g, 0, sizeof(g));
05241 res = ioctl(fd, DAHDI_GETGAINS, &g);
05242 if (res) {
05243 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05244 return res;
05245 }
05246
05247 fill_rxgain(&g, gain, drc, law);
05248
05249 return ioctl(fd, DAHDI_SETGAINS, &g);
05250 }
05251
05252 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05253 {
05254 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05255 }
05256
05257 static int bump_gains(struct dahdi_pvt *p)
05258 {
05259 int res;
05260
05261
05262 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05263 if (res) {
05264 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05265 return -1;
05266 }
05267
05268 return 0;
05269 }
05270
05271 static int restore_gains(struct dahdi_pvt *p)
05272 {
05273 int res;
05274
05275 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05276 if (res) {
05277 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05278 return -1;
05279 }
05280
05281 return 0;
05282 }
05283
05284 static inline int dahdi_set_hook(int fd, int hs)
05285 {
05286 int x, res;
05287
05288 x = hs;
05289 res = ioctl(fd, DAHDI_HOOK, &x);
05290
05291 if (res < 0) {
05292 if (errno == EINPROGRESS)
05293 return 0;
05294 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05295
05296 }
05297
05298 return res;
05299 }
05300
05301 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05302 {
05303 int x, res;
05304
05305 x = muted;
05306 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05307 switch (p->sig) {
05308 #if defined(HAVE_PRI)
05309 case SIG_PRI_LIB_HANDLE_CASES:
05310 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05311
05312 break;
05313 }
05314
05315 #endif
05316 #if defined(HAVE_SS7)
05317 case SIG_SS7:
05318 #endif
05319 {
05320 int y = 1;
05321
05322 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05323 if (res)
05324 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05325 p->channel, strerror(errno));
05326 }
05327 break;
05328 default:
05329 break;
05330 }
05331 #endif
05332 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05333 if (res < 0)
05334 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05335 return res;
05336 }
05337
05338 static int save_conference(struct dahdi_pvt *p)
05339 {
05340 struct dahdi_confinfo c;
05341 int res;
05342 if (p->saveconf.confmode) {
05343 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05344 return -1;
05345 }
05346 p->saveconf.chan = 0;
05347 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05348 if (res) {
05349 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05350 p->saveconf.confmode = 0;
05351 return -1;
05352 }
05353 memset(&c, 0, sizeof(c));
05354 c.confmode = DAHDI_CONF_NORMAL;
05355 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05356 if (res) {
05357 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05358 return -1;
05359 }
05360 ast_debug(1, "Disabled conferencing\n");
05361 return 0;
05362 }
05363
05364 static int restore_conference(struct dahdi_pvt *p)
05365 {
05366 int res;
05367 if (p->saveconf.confmode) {
05368 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05369 p->saveconf.confmode = 0;
05370 if (res) {
05371 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05372 return -1;
05373 }
05374 ast_debug(1, "Restored conferencing\n");
05375 }
05376 return 0;
05377 }
05378
05379 static int send_cwcidspill(struct dahdi_pvt *p)
05380 {
05381 struct ast_format tmpfmt;
05382
05383 p->callwaitcas = 0;
05384 p->cidcwexpire = 0;
05385 p->cid_suppress_expire = 0;
05386 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05387 return -1;
05388 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05389
05390 p->cidlen += READ_SIZE * 4;
05391 p->cidpos = 0;
05392 send_callerid(p);
05393 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05394 return 0;
05395 }
05396
05397 static int has_voicemail(struct dahdi_pvt *p)
05398 {
05399 int new_msgs;
05400 struct ast_event *event;
05401 char *mailbox, *context;
05402
05403 mailbox = context = ast_strdupa(p->mailbox);
05404 strsep(&context, "@");
05405 if (ast_strlen_zero(context))
05406 context = "default";
05407
05408 event = ast_event_get_cached(AST_EVENT_MWI,
05409 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05410 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05411 AST_EVENT_IE_END);
05412
05413 if (event) {
05414 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05415 ast_event_destroy(event);
05416 } else
05417 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05418
05419 return new_msgs;
05420 }
05421
05422
05423
05424 static int send_callerid(struct dahdi_pvt *p)
05425 {
05426
05427 int res;
05428
05429 if (p->subs[SUB_REAL].linear) {
05430 p->subs[SUB_REAL].linear = 0;
05431 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05432 }
05433 while (p->cidpos < p->cidlen) {
05434 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05435 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05436 if (res < 0) {
05437 if (errno == EAGAIN)
05438 return 0;
05439 else {
05440 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05441 return -1;
05442 }
05443 }
05444 if (!res)
05445 return 0;
05446 p->cidpos += res;
05447 }
05448 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05449 ast_free(p->cidspill);
05450 p->cidspill = NULL;
05451 if (p->callwaitcas) {
05452
05453 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05454 p->cid_suppress_expire = p->cidcwexpire;
05455 } else
05456 restore_conference(p);
05457 return 0;
05458 }
05459
05460 static int dahdi_callwait(struct ast_channel *ast)
05461 {
05462 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05463 struct ast_format tmpfmt;
05464 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05465 if (p->cidspill) {
05466 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05467 ast_free(p->cidspill);
05468 }
05469
05470
05471
05472
05473
05474 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05475 return -1;
05476 save_conference(p);
05477
05478 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05479 if (!p->callwaitrings && p->callwaitingcallerid) {
05480 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05481 p->callwaitcas = 1;
05482 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05483 } else {
05484 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05485 p->callwaitcas = 0;
05486 p->cidlen = 2400 + READ_SIZE * 4;
05487 }
05488 p->cidpos = 0;
05489 send_callerid(p);
05490
05491 return 0;
05492 }
05493
05494 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05495 {
05496 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05497 int x, res, mysig;
05498 char *dest;
05499 AST_DECLARE_APP_ARGS(args,
05500 AST_APP_ARG(group);
05501 AST_APP_ARG(ext);
05502
05503 AST_APP_ARG(other);
05504 );
05505
05506 ast_mutex_lock(&p->lock);
05507 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05508
05509
05510 dest = ast_strdupa(rdest);
05511 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05512 if (!args.ext) {
05513 args.ext = "";
05514 }
05515
05516 #if defined(HAVE_PRI)
05517 if (dahdi_sig_pri_lib_handles(p->sig)) {
05518 char *subaddr;
05519
05520 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05521
05522
05523 subaddr = strchr(p->exten, ':');
05524 if (subaddr) {
05525 *subaddr = '\0';
05526 }
05527 } else
05528 #endif
05529 {
05530 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05531 }
05532
05533 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05534 p->subs[SUB_REAL].needbusy = 1;
05535 ast_mutex_unlock(&p->lock);
05536 return 0;
05537 }
05538 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05539 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05540 ast_mutex_unlock(&p->lock);
05541 return -1;
05542 }
05543 p->waitingfordt.tv_sec = 0;
05544 p->dialednone = 0;
05545 if ((p->radio || (p->oprmode < 0)))
05546 {
05547
05548 ast_setstate(ast, AST_STATE_UP);
05549 ast_mutex_unlock(&p->lock);
05550 return 0;
05551 }
05552 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05553 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05554 if (res)
05555 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05556 p->outgoing = 1;
05557
05558 if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05559 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05560 } else {
05561 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05562 }
05563
05564 #ifdef HAVE_PRI
05565 if (dahdi_sig_pri_lib_handles(p->sig)) {
05566 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05567 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05568 ast_mutex_unlock(&p->lock);
05569 return res;
05570 }
05571 #endif
05572
05573 #if defined(HAVE_SS7)
05574 if (p->sig == SIG_SS7) {
05575 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05576 ast_mutex_unlock(&p->lock);
05577 return res;
05578 }
05579 #endif
05580
05581
05582 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05583 p->callwaitrings = 0;
05584 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05585 ast_mutex_unlock(&p->lock);
05586 return res;
05587 }
05588
05589 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05590 switch (mysig) {
05591 case 0:
05592
05593 ast_setstate(ast, AST_STATE_UP);
05594 break;
05595 case SIG_MFCR2:
05596 break;
05597 default:
05598 ast_debug(1, "not yet implemented\n");
05599 ast_mutex_unlock(&p->lock);
05600 return -1;
05601 }
05602
05603 #ifdef HAVE_OPENR2
05604 if (p->mfcr2) {
05605 openr2_calling_party_category_t chancat;
05606 int callres = 0;
05607 char *c, *l;
05608
05609
05610 p->dialdest[0] = '\0';
05611
05612 c = args.ext;
05613 if (!p->hidecallerid) {
05614 l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05615 } else {
05616 l = NULL;
05617 }
05618 if (strlen(c) < p->stripmsd) {
05619 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05620 ast_mutex_unlock(&p->lock);
05621 return -1;
05622 }
05623 p->dialing = 1;
05624 chancat = dahdi_r2_get_channel_category(ast);
05625 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05626 if (-1 == callres) {
05627 ast_mutex_unlock(&p->lock);
05628 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05629 return -1;
05630 }
05631 p->mfcr2_call_accepted = 0;
05632 p->mfcr2_progress_sent = 0;
05633 ast_setstate(ast, AST_STATE_DIALING);
05634 }
05635 #endif
05636 ast_mutex_unlock(&p->lock);
05637 return 0;
05638 }
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05656 {
05657 struct dahdi_pvt *cur;
05658
05659 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05660
05661
05662 for (cur = iflist; cur; cur = cur->next) {
05663 if (pvt->channel < cur->channel) {
05664
05665 pvt->prev = cur->prev;
05666 pvt->next = cur;
05667 if (cur->prev) {
05668
05669 cur->prev->next = pvt;
05670 } else {
05671
05672 iflist = pvt;
05673 }
05674 cur->prev = pvt;
05675 return;
05676 }
05677 }
05678
05679
05680 pvt->prev = ifend;
05681 pvt->next = NULL;
05682 if (ifend) {
05683 ifend->next = pvt;
05684 }
05685 ifend = pvt;
05686 if (!iflist) {
05687
05688 iflist = pvt;
05689 }
05690 }
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05706 {
05707
05708 if (pvt->prev) {
05709 pvt->prev->next = pvt->next;
05710 } else if (iflist == pvt) {
05711
05712 iflist = pvt->next;
05713 }
05714
05715
05716 if (pvt->next) {
05717 pvt->next->prev = pvt->prev;
05718 } else if (ifend == pvt) {
05719
05720 ifend = pvt->prev;
05721 }
05722
05723
05724 pvt->which_iflist = DAHDI_IFLIST_NONE;
05725 pvt->prev = NULL;
05726 pvt->next = NULL;
05727 }
05728
05729 #if defined(HAVE_PRI)
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745
05746 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05747 {
05748 struct dahdi_pvt *cur;
05749
05750 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05751
05752
05753 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05754 if (pvt->channel < cur->channel) {
05755
05756 pvt->prev = cur->prev;
05757 pvt->next = cur;
05758 if (cur->prev) {
05759
05760 cur->prev->next = pvt;
05761 } else {
05762
05763 pri->no_b_chan_iflist = pvt;
05764 }
05765 cur->prev = pvt;
05766 return;
05767 }
05768 }
05769
05770
05771 pvt->prev = pri->no_b_chan_end;
05772 pvt->next = NULL;
05773 if (pri->no_b_chan_end) {
05774 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05775 }
05776 pri->no_b_chan_end = pvt;
05777 if (!pri->no_b_chan_iflist) {
05778
05779 pri->no_b_chan_iflist = pvt;
05780 }
05781 }
05782 #endif
05783
05784 #if defined(HAVE_PRI)
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796
05797
05798
05799 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05800 {
05801
05802 if (pvt->prev) {
05803 pvt->prev->next = pvt->next;
05804 } else if (pri->no_b_chan_iflist == pvt) {
05805
05806 pri->no_b_chan_iflist = pvt->next;
05807 }
05808
05809
05810 if (pvt->next) {
05811 pvt->next->prev = pvt->prev;
05812 } else if (pri->no_b_chan_end == pvt) {
05813
05814 pri->no_b_chan_end = pvt->prev;
05815 }
05816
05817
05818 pvt->which_iflist = DAHDI_IFLIST_NONE;
05819 pvt->prev = NULL;
05820 pvt->next = NULL;
05821 }
05822 #endif
05823
05824 #if defined(HAVE_PRI)
05825
05826
05827
05828
05829
05830
05831
05832
05833
05834 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05835 {
05836 unsigned idx;
05837 struct sig_pri_span *pri;
05838
05839 pri = pvt->pri;
05840 if (!pri) {
05841
05842 return;
05843 }
05844 ast_mutex_lock(&pri->lock);
05845 for (idx = 0; idx < pri->numchans; ++idx) {
05846 if (pri->pvts[idx] == pvt->sig_pvt) {
05847 pri->pvts[idx] = NULL;
05848 ast_mutex_unlock(&pri->lock);
05849 return;
05850 }
05851 }
05852 ast_mutex_unlock(&pri->lock);
05853 }
05854 #endif
05855
05856 #if defined(HAVE_SS7)
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05867 {
05868 unsigned idx;
05869 struct sig_ss7_linkset *ss7;
05870
05871 ss7 = pvt->ss7;
05872 if (!ss7) {
05873
05874 return;
05875 }
05876 ast_mutex_lock(&ss7->lock);
05877 for (idx = 0; idx < ss7->numchans; ++idx) {
05878 if (ss7->pvts[idx] == pvt->sig_pvt) {
05879 ss7->pvts[idx] = NULL;
05880 ast_mutex_unlock(&ss7->lock);
05881 return;
05882 }
05883 }
05884 ast_mutex_unlock(&ss7->lock);
05885 }
05886 #endif
05887
05888 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05889 {
05890 if (cur->next && cur->next->span == cur->span) {
05891 return cur->next;
05892 } else if (cur->prev && cur->prev->span == cur->span) {
05893 return cur->prev;
05894 }
05895
05896 return NULL;
05897 }
05898
05899 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05900 {
05901 struct dahdi_pvt *p = pvt;
05902
05903 if (p->manages_span_alarms) {
05904 struct dahdi_pvt *next = find_next_iface_in_span(p);
05905 if (next) {
05906 next->manages_span_alarms = 1;
05907 }
05908 }
05909
05910
05911 #if defined(HAVE_PRI)
05912 dahdi_unlink_pri_pvt(p);
05913 #endif
05914 #if defined(HAVE_SS7)
05915 dahdi_unlink_ss7_pvt(p);
05916 #endif
05917 switch (pvt->which_iflist) {
05918 case DAHDI_IFLIST_NONE:
05919 break;
05920 case DAHDI_IFLIST_MAIN:
05921 dahdi_iflist_extract(p);
05922 break;
05923 #if defined(HAVE_PRI)
05924 case DAHDI_IFLIST_NO_B_CHAN:
05925 if (p->pri) {
05926 dahdi_nobch_extract(p->pri, p);
05927 }
05928 break;
05929 #endif
05930 }
05931
05932 if (p->sig_pvt) {
05933 if (analog_lib_handles(p->sig, 0, 0)) {
05934 analog_delete(p->sig_pvt);
05935 }
05936 switch (p->sig) {
05937 #if defined(HAVE_PRI)
05938 case SIG_PRI_LIB_HANDLE_CASES:
05939 sig_pri_chan_delete(p->sig_pvt);
05940 break;
05941 #endif
05942 #if defined(HAVE_SS7)
05943 case SIG_SS7:
05944 sig_ss7_chan_delete(p->sig_pvt);
05945 break;
05946 #endif
05947 default:
05948 break;
05949 }
05950 }
05951 ast_free(p->cidspill);
05952 if (p->use_smdi)
05953 ast_smdi_interface_unref(p->smdi_iface);
05954 if (p->mwi_event_sub)
05955 ast_event_unsubscribe(p->mwi_event_sub);
05956 if (p->vars) {
05957 ast_variables_destroy(p->vars);
05958 }
05959 if (p->cc_params) {
05960 ast_cc_config_params_destroy(p->cc_params);
05961 }
05962
05963 p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
05964 p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
05965
05966 ast_mutex_destroy(&p->lock);
05967 dahdi_close_sub(p, SUB_REAL);
05968 if (p->owner)
05969 ast_channel_tech_pvt_set(p->owner, NULL);
05970 ast_free(p);
05971 }
05972
05973 static void destroy_channel(struct dahdi_pvt *cur, int now)
05974 {
05975 int i;
05976
05977 if (!now) {
05978
05979 if (cur->owner) {
05980 return;
05981 }
05982 for (i = 0; i < 3; i++) {
05983 if (cur->subs[i].owner) {
05984 return;
05985 }
05986 }
05987 }
05988 destroy_dahdi_pvt(cur);
05989 }
05990
05991 static void destroy_all_channels(void)
05992 {
05993 int chan;
05994 #if defined(HAVE_PRI)
05995 unsigned span;
05996 struct sig_pri_span *pri;
05997 #endif
05998 struct dahdi_pvt *p;
05999
06000 while (num_restart_pending) {
06001 usleep(1);
06002 }
06003
06004 ast_mutex_lock(&iflock);
06005
06006 while (iflist) {
06007 p = iflist;
06008
06009 chan = p->channel;
06010 #if defined(HAVE_PRI_SERVICE_MESSAGES)
06011 {
06012 char db_chan_name[20];
06013 char db_answer[5];
06014 char state;
06015 int why = -1;
06016
06017 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
06018 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
06019 sscanf(db_answer, "%1c:%30d", &state, &why);
06020 }
06021 if (!why) {
06022
06023 ast_db_del(db_chan_name, SRVST_DBKEY);
06024 }
06025 }
06026 #endif
06027
06028 destroy_dahdi_pvt(p);
06029 ast_verb(3, "Unregistered channel %d\n", chan);
06030 }
06031 ifcount = 0;
06032 ast_mutex_unlock(&iflock);
06033
06034 #if defined(HAVE_PRI)
06035
06036 for (span = 0; span < NUM_SPANS; ++span) {
06037 if (!pris[span].dchannels[0]) {
06038 break;
06039 }
06040 pri = &pris[span].pri;
06041 ast_mutex_lock(&pri->lock);
06042 while (pri->no_b_chan_iflist) {
06043 p = pri->no_b_chan_iflist;
06044
06045
06046 destroy_dahdi_pvt(p);
06047 }
06048 ast_mutex_unlock(&pri->lock);
06049 }
06050 #endif
06051 }
06052
06053 #if defined(HAVE_PRI)
06054 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
06055
06056 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
06057 {
06058
06059 struct dahdi_pvt *p;
06060
06061 if (ast_strlen_zero(digits)) {
06062 ast_debug(1, "No digit string sent to application!\n");
06063 return -1;
06064 }
06065
06066 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06067
06068 if (!p) {
06069 ast_debug(1, "Unable to find technology private\n");
06070 return -1;
06071 }
06072
06073 pri_send_keypad_facility_exec(p->sig_pvt, digits);
06074
06075 return 0;
06076 }
06077 #endif
06078
06079 #if defined(HAVE_PRI)
06080 #if defined(HAVE_PRI_PROG_W_CAUSE)
06081 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
06082
06083 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
06084 {
06085
06086 struct dahdi_pvt *pvt;
06087 char *parse;
06088 int res;
06089 AST_DECLARE_APP_ARGS(args,
06090 AST_APP_ARG(destination);
06091 AST_APP_ARG(original);
06092 AST_APP_ARG(reason);
06093 );
06094
06095 if (ast_strlen_zero(data)) {
06096 ast_debug(1, "No data sent to application!\n");
06097 return -1;
06098 }
06099 if (ast_channel_tech(chan) != &dahdi_tech) {
06100 ast_debug(1, "Only DAHDI technology accepted!\n");
06101 return -1;
06102 }
06103 pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
06104 if (!pvt) {
06105 ast_debug(1, "Unable to find technology private\n");
06106 return -1;
06107 }
06108 switch (pvt->sig) {
06109 case SIG_PRI_LIB_HANDLE_CASES:
06110 break;
06111 default:
06112 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
06113 ast_channel_name(chan));
06114 return -1;
06115 }
06116
06117 parse = ast_strdupa(data);
06118 AST_STANDARD_APP_ARGS(args, parse);
06119
06120 if (ast_strlen_zero(args.destination)) {
06121 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
06122 return -1;
06123 }
06124
06125 if (ast_strlen_zero(args.original)) {
06126 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06127 args.original = NULL;
06128 }
06129
06130 if (ast_strlen_zero(args.reason)) {
06131 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06132 args.reason = NULL;
06133 }
06134
06135 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
06136 args.destination, args.original, args.reason);
06137 if (!res) {
06138
06139
06140
06141
06142 ast_safe_sleep(chan, 5000);
06143 }
06144
06145 return -1;
06146 }
06147 #endif
06148 #endif
06149
06150 #if defined(HAVE_OPENR2)
06151 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06152
06153 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06154 {
06155
06156 openr2_call_mode_t accept_mode;
06157 int res, timeout, maxloops;
06158 struct ast_frame *f;
06159 struct dahdi_pvt *p;
06160 char *parse;
06161 AST_DECLARE_APP_ARGS(args,
06162 AST_APP_ARG(charge);
06163 );
06164
06165 if (ast_strlen_zero(data)) {
06166 ast_debug(1, "No data sent to application!\n");
06167 return -1;
06168 }
06169
06170 if (ast_channel_tech(chan) != &dahdi_tech) {
06171 ast_debug(1, "Only DAHDI technology accepted!\n");
06172 return -1;
06173 }
06174
06175 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06176 if (!p) {
06177 ast_debug(1, "Unable to find technology private!\n");
06178 return -1;
06179 }
06180
06181 parse = ast_strdupa(data);
06182 AST_STANDARD_APP_ARGS(args, parse);
06183
06184 if (ast_strlen_zero(args.charge)) {
06185 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06186 return -1;
06187 }
06188
06189 ast_mutex_lock(&p->lock);
06190 if (!p->mfcr2 || !p->mfcr2call) {
06191 ast_mutex_unlock(&p->lock);
06192 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06193 return -1;
06194 }
06195
06196 if (p->mfcr2_call_accepted) {
06197 ast_mutex_unlock(&p->lock);
06198 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06199 return 0;
06200 }
06201 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06202 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06203 ast_mutex_unlock(&p->lock);
06204 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06205 return -1;
06206 }
06207 ast_mutex_unlock(&p->lock);
06208
06209 res = 0;
06210 timeout = 100;
06211 maxloops = 50;
06212
06213 while (maxloops > 0) {
06214 maxloops--;
06215 if (ast_check_hangup(chan)) {
06216 break;
06217 }
06218 res = ast_waitfor(chan, timeout);
06219 if (res < 0) {
06220 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06221 res = -1;
06222 break;
06223 }
06224 if (res == 0) {
06225 continue;
06226 }
06227 res = 0;
06228 f = ast_read(chan);
06229 if (!f) {
06230 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06231 res = -1;
06232 break;
06233 }
06234 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06235 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06236 ast_frfree(f);
06237 res = -1;
06238 break;
06239 }
06240 ast_frfree(f);
06241 ast_mutex_lock(&p->lock);
06242 if (p->mfcr2_call_accepted) {
06243 ast_mutex_unlock(&p->lock);
06244 ast_debug(1, "Accepted MFC/R2 call!\n");
06245 break;
06246 }
06247 ast_mutex_unlock(&p->lock);
06248 }
06249 if (res == -1) {
06250 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06251 }
06252 return res;
06253 }
06254
06255 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06256 {
06257 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06258 switch (cause) {
06259 case AST_CAUSE_USER_BUSY:
06260 case AST_CAUSE_CALL_REJECTED:
06261 case AST_CAUSE_INTERWORKING:
06262 r2cause = OR2_CAUSE_BUSY_NUMBER;
06263 break;
06264
06265 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06266 case AST_CAUSE_SWITCH_CONGESTION:
06267 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06268 break;
06269
06270 case AST_CAUSE_UNALLOCATED:
06271 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06272 break;
06273
06274 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06275 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06276 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06277 break;
06278
06279 case AST_CAUSE_NO_ANSWER:
06280 case AST_CAUSE_NO_USER_RESPONSE:
06281 r2cause = OR2_CAUSE_NO_ANSWER;
06282 break;
06283
06284 default:
06285 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06286 break;
06287 }
06288 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06289 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06290 return r2cause;
06291 }
06292 #endif
06293
06294 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06295 {
06296 if (p->bufferoverrideinuse) {
06297
06298 struct dahdi_bufferinfo bi = {
06299 .txbufpolicy = p->buf_policy,
06300 .rxbufpolicy = p->buf_policy,
06301 .bufsize = p->bufsize,
06302 .numbufs = p->buf_no
06303 };
06304 int bpres;
06305
06306 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06307 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06308 }
06309 p->bufferoverrideinuse = 0;
06310 return bpres;
06311 }
06312
06313 return -1;
06314 }
06315
06316 static int dahdi_hangup(struct ast_channel *ast)
06317 {
06318 int res = 0;
06319 int idx,x;
06320 int law;
06321
06322 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06323 struct dahdi_params par;
06324
06325 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06326 if (!ast_channel_tech_pvt(ast)) {
06327 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06328 return 0;
06329 }
06330
06331 ast_mutex_lock(&p->lock);
06332 p->exten[0] = '\0';
06333 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06334 dahdi_confmute(p, 0);
06335 restore_gains(p);
06336 p->ignoredtmf = 0;
06337 p->waitingfordt.tv_sec = 0;
06338
06339 res = analog_hangup(p->sig_pvt, ast);
06340 revert_fax_buffers(p, ast);
06341
06342 goto hangup_out;
06343 } else {
06344 p->cid_num[0] = '\0';
06345 p->cid_name[0] = '\0';
06346 p->cid_subaddr[0] = '\0';
06347 }
06348
06349 #if defined(HAVE_PRI)
06350 if (dahdi_sig_pri_lib_handles(p->sig)) {
06351 x = 1;
06352 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06353
06354 dahdi_confmute(p, 0);
06355 p->muting = 0;
06356 restore_gains(p);
06357 if (p->dsp) {
06358 ast_dsp_free(p->dsp);
06359 p->dsp = NULL;
06360 }
06361 p->ignoredtmf = 0;
06362
06363
06364 p->subs[SUB_REAL].owner = NULL;
06365 p->subs[SUB_REAL].needbusy = 0;
06366 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06367
06368 p->owner = NULL;
06369 p->cid_tag[0] = '\0';
06370 p->ringt = 0;
06371 p->distinctivering = 0;
06372 p->confirmanswer = 0;
06373 p->outgoing = 0;
06374 p->digital = 0;
06375 p->faxhandled = 0;
06376 p->pulsedial = 0;
06377
06378 revert_fax_buffers(p, ast);
06379
06380 p->law = p->law_default;
06381 law = p->law_default;
06382 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06383 if (res < 0) {
06384 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06385 p->channel, strerror(errno));
06386 }
06387
06388 sig_pri_hangup(p->sig_pvt, ast);
06389
06390 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06391 dahdi_disable_ec(p);
06392
06393 x = 0;
06394 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06395 p->didtdd = 0;
06396
06397 p->rdnis[0] = '\0';
06398 update_conf(p);
06399 reset_conf(p);
06400
06401
06402 x = 0;
06403 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06404
06405 if (num_restart_pending == 0) {
06406 restart_monitor();
06407 }
06408 goto hangup_out;
06409 }
06410 #endif
06411
06412 #if defined(HAVE_SS7)
06413 if (p->sig == SIG_SS7) {
06414 x = 1;
06415 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06416
06417 dahdi_confmute(p, 0);
06418 p->muting = 0;
06419 restore_gains(p);
06420 if (p->dsp) {
06421 ast_dsp_free(p->dsp);
06422 p->dsp = NULL;
06423 }
06424 p->ignoredtmf = 0;
06425
06426
06427 p->subs[SUB_REAL].owner = NULL;
06428 p->subs[SUB_REAL].needbusy = 0;
06429 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06430
06431 p->owner = NULL;
06432 p->ringt = 0;
06433 p->distinctivering = 0;
06434 p->confirmanswer = 0;
06435 p->outgoing = 0;
06436 p->digital = 0;
06437 p->faxhandled = 0;
06438 p->pulsedial = 0;
06439
06440 revert_fax_buffers(p, ast);
06441
06442 p->law = p->law_default;
06443 law = p->law_default;
06444 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06445 if (res < 0) {
06446 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06447 p->channel, strerror(errno));
06448 }
06449
06450 sig_ss7_hangup(p->sig_pvt, ast);
06451
06452 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06453 dahdi_disable_ec(p);
06454
06455 x = 0;
06456 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06457 p->didtdd = 0;
06458
06459 update_conf(p);
06460 reset_conf(p);
06461
06462
06463 x = 0;
06464 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06465
06466 if (num_restart_pending == 0) {
06467 restart_monitor();
06468 }
06469 goto hangup_out;
06470 }
06471 #endif
06472
06473 idx = dahdi_get_index(ast, p, 1);
06474
06475 dahdi_confmute(p, 0);
06476 p->muting = 0;
06477 restore_gains(p);
06478 if (p->origcid_num) {
06479 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06480 ast_free(p->origcid_num);
06481 p->origcid_num = NULL;
06482 }
06483 if (p->origcid_name) {
06484 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06485 ast_free(p->origcid_name);
06486 p->origcid_name = NULL;
06487 }
06488 if (p->dsp)
06489 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06490
06491 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06492 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06493 p->ignoredtmf = 0;
06494
06495 if (idx > -1) {
06496
06497 p->subs[idx].owner = NULL;
06498 p->subs[idx].needanswer = 0;
06499 p->subs[idx].needflash = 0;
06500 p->subs[idx].needringing = 0;
06501 p->subs[idx].needbusy = 0;
06502 p->subs[idx].needcongestion = 0;
06503 p->subs[idx].linear = 0;
06504 p->polarity = POLARITY_IDLE;
06505 dahdi_setlinear(p->subs[idx].dfd, 0);
06506 if (idx == SUB_REAL) {
06507 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06508 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06509 if (p->subs[SUB_CALLWAIT].inthreeway) {
06510
06511 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06512
06513 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06514 unalloc_sub(p, SUB_CALLWAIT);
06515 p->owner = NULL;
06516 } else {
06517
06518 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06519 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06520 unalloc_sub(p, SUB_THREEWAY);
06521 if (p->subs[SUB_REAL].inthreeway) {
06522
06523
06524 ast_debug(1, "Call was complete, setting owner to former third call\n");
06525 p->owner = p->subs[SUB_REAL].owner;
06526 } else {
06527
06528 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06529 p->owner = NULL;
06530 }
06531 p->subs[SUB_REAL].inthreeway = 0;
06532 }
06533 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06534
06535 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06536 unalloc_sub(p, SUB_CALLWAIT);
06537 p->owner = p->subs[SUB_REAL].owner;
06538 if (ast_channel_state(p->owner) != AST_STATE_UP)
06539 p->subs[SUB_REAL].needanswer = 1;
06540 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06541 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06542 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06543 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06544 unalloc_sub(p, SUB_THREEWAY);
06545 if (p->subs[SUB_REAL].inthreeway) {
06546
06547
06548 ast_debug(1, "Call was complete, setting owner to former third call\n");
06549 p->owner = p->subs[SUB_REAL].owner;
06550 } else {
06551
06552 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06553 p->owner = NULL;
06554 }
06555 p->subs[SUB_REAL].inthreeway = 0;
06556 }
06557 } else if (idx == SUB_CALLWAIT) {
06558
06559 if (p->subs[SUB_CALLWAIT].inthreeway) {
06560
06561
06562 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06563 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06564 S_OR(p->mohsuggest, NULL),
06565 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06566 }
06567 p->subs[SUB_THREEWAY].inthreeway = 0;
06568
06569 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06570 unalloc_sub(p, SUB_THREEWAY);
06571 } else
06572 unalloc_sub(p, SUB_CALLWAIT);
06573 } else if (idx == SUB_THREEWAY) {
06574 if (p->subs[SUB_CALLWAIT].inthreeway) {
06575
06576
06577 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06578 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06579 S_OR(p->mohsuggest, NULL),
06580 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06581 }
06582 p->subs[SUB_CALLWAIT].inthreeway = 0;
06583 }
06584 p->subs[SUB_REAL].inthreeway = 0;
06585
06586
06587 unalloc_sub(p, SUB_THREEWAY);
06588 } else {
06589
06590 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06591 }
06592 }
06593
06594 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06595 p->owner = NULL;
06596 p->ringt = 0;
06597 p->distinctivering = 0;
06598 p->confirmanswer = 0;
06599 p->outgoing = 0;
06600 p->digital = 0;
06601 p->faxhandled = 0;
06602 p->pulsedial = 0;
06603 if (p->dsp) {
06604 ast_dsp_free(p->dsp);
06605 p->dsp = NULL;
06606 }
06607
06608 revert_fax_buffers(p, ast);
06609
06610 p->law = p->law_default;
06611 law = p->law_default;
06612 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06613 if (res < 0)
06614 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06615
06616 #ifdef HAVE_OPENR2
06617 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06618 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06619
06620 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06621 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06622 } else {
06623 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06624 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06625 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06626 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
06627 dahdi_r2_disconnect_call(p, r2cause);
06628 }
06629 } else if (p->mfcr2call) {
06630 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06631
06632
06633
06634
06635 p->mfcr2call = 0;
06636 }
06637 #endif
06638 switch (p->sig) {
06639 case SIG_SS7:
06640 case SIG_MFCR2:
06641 case SIG_PRI_LIB_HANDLE_CASES:
06642 case 0:
06643 break;
06644 default:
06645 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06646 break;
06647 }
06648 if (res < 0) {
06649 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06650 }
06651 switch (p->sig) {
06652 case SIG_FXOGS:
06653 case SIG_FXOLS:
06654 case SIG_FXOKS:
06655 memset(&par, 0, sizeof(par));
06656 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06657 if (!res) {
06658 struct analog_pvt *analog_p = p->sig_pvt;
06659 #if 0
06660 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06661 #endif
06662
06663 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06664 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06665 else
06666 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06667 analog_p->fxsoffhookstate = par.rxisoffhook;
06668 }
06669 break;
06670 case SIG_FXSGS:
06671 case SIG_FXSLS:
06672 case SIG_FXSKS:
06673
06674
06675 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
06676 time(&p->guardtime);
06677 p->guardtime += 2;
06678 }
06679 break;
06680 default:
06681 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06682 break;
06683 }
06684 if (p->sig)
06685 dahdi_disable_ec(p);
06686 x = 0;
06687 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06688 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06689 p->didtdd = 0;
06690 p->callwaitcas = 0;
06691 p->callwaiting = p->permcallwaiting;
06692 p->hidecallerid = p->permhidecallerid;
06693 p->waitingfordt.tv_sec = 0;
06694 p->dialing = 0;
06695 p->rdnis[0] = '\0';
06696 update_conf(p);
06697 reset_conf(p);
06698
06699 switch (p->sig) {
06700 case SIG_PRI_LIB_HANDLE_CASES:
06701 case SIG_SS7:
06702 x = 0;
06703 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06704 break;
06705 default:
06706 break;
06707 }
06708 if (num_restart_pending == 0)
06709 restart_monitor();
06710 }
06711
06712 p->callwaitingrepeat = 0;
06713 p->cidcwexpire = 0;
06714 p->cid_suppress_expire = 0;
06715 p->oprmode = 0;
06716 hangup_out:
06717 ast_channel_tech_pvt_set(ast, NULL);
06718 ast_free(p->cidspill);
06719 p->cidspill = NULL;
06720
06721 ast_mutex_unlock(&p->lock);
06722 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06723
06724 ast_mutex_lock(&iflock);
06725 if (p->restartpending) {
06726 num_restart_pending--;
06727 }
06728
06729 if (p->destroy) {
06730 destroy_channel(p, 0);
06731 }
06732 ast_mutex_unlock(&iflock);
06733
06734 ast_module_unref(ast_module_info->self);
06735 return 0;
06736 }
06737
06738 static int dahdi_answer(struct ast_channel *ast)
06739 {
06740 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06741 int res = 0;
06742 int idx;
06743 ast_setstate(ast, AST_STATE_UP);
06744 ast_mutex_lock(&p->lock);
06745 idx = dahdi_get_index(ast, p, 0);
06746 if (idx < 0)
06747 idx = SUB_REAL;
06748
06749 if ((p->radio || (p->oprmode < 0))) {
06750 ast_mutex_unlock(&p->lock);
06751 return 0;
06752 }
06753
06754 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06755 res = analog_answer(p->sig_pvt, ast);
06756 ast_mutex_unlock(&p->lock);
06757 return res;
06758 }
06759
06760 switch (p->sig) {
06761 #if defined(HAVE_PRI)
06762 case SIG_PRI_LIB_HANDLE_CASES:
06763 res = sig_pri_answer(p->sig_pvt, ast);
06764 break;
06765 #endif
06766 #if defined(HAVE_SS7)
06767 case SIG_SS7:
06768 res = sig_ss7_answer(p->sig_pvt, ast);
06769 break;
06770 #endif
06771 #ifdef HAVE_OPENR2
06772 case SIG_MFCR2:
06773 if (!p->mfcr2_call_accepted) {
06774
06775
06776 p->mfcr2_answer_pending = 1;
06777 if (p->mfcr2_charge_calls) {
06778 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06779 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06780 } else {
06781 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06782 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06783 }
06784 } else {
06785 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06786 dahdi_r2_answer(p);
06787 }
06788 break;
06789 #endif
06790 case 0:
06791 ast_mutex_unlock(&p->lock);
06792 return 0;
06793 default:
06794 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06795 res = -1;
06796 break;
06797 }
06798 ast_mutex_unlock(&p->lock);
06799 return res;
06800 }
06801
06802 static void disable_dtmf_detect(struct dahdi_pvt *p)
06803 {
06804 int val = 0;
06805
06806 p->ignoredtmf = 1;
06807
06808 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06809
06810 if (!p->hardwaredtmf && p->dsp) {
06811 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06812 ast_dsp_set_features(p->dsp, p->dsp_features);
06813 }
06814 }
06815
06816 static void enable_dtmf_detect(struct dahdi_pvt *p)
06817 {
06818 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06819
06820 if (p->channel == CHAN_PSEUDO)
06821 return;
06822
06823 p->ignoredtmf = 0;
06824
06825 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06826
06827 if (!p->hardwaredtmf && p->dsp) {
06828 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06829 ast_dsp_set_features(p->dsp, p->dsp_features);
06830 }
06831 }
06832
06833 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06834 {
06835 char *cp;
06836 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06837
06838
06839 if (!p || !data || (*datalen < 1)) {
06840 errno = EINVAL;
06841 return -1;
06842 }
06843
06844 switch (option) {
06845 case AST_OPTION_DIGIT_DETECT:
06846 cp = (char *) data;
06847 *cp = p->ignoredtmf ? 0 : 1;
06848 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06849 break;
06850 case AST_OPTION_FAX_DETECT:
06851 cp = (char *) data;
06852 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06853 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06854 break;
06855 case AST_OPTION_CC_AGENT_TYPE:
06856 #if defined(HAVE_PRI)
06857 #if defined(HAVE_PRI_CCSS)
06858 if (dahdi_sig_pri_lib_handles(p->sig)) {
06859 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06860 break;
06861 }
06862 #endif
06863 #endif
06864 return -1;
06865 default:
06866 return -1;
06867 }
06868
06869 errno = 0;
06870
06871 return 0;
06872 }
06873
06874 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06875 {
06876 char *cp;
06877 signed char *scp;
06878 int x;
06879 int idx;
06880 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
06881 struct oprmode *oprmode;
06882
06883
06884
06885 if (!p || !data || (datalen < 1)) {
06886 errno = EINVAL;
06887 return -1;
06888 }
06889
06890 switch (option) {
06891 case AST_OPTION_TXGAIN:
06892 scp = (signed char *) data;
06893 idx = dahdi_get_index(chan, p, 0);
06894 if (idx < 0) {
06895 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06896 return -1;
06897 }
06898 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06899 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06900 case AST_OPTION_RXGAIN:
06901 scp = (signed char *) data;
06902 idx = dahdi_get_index(chan, p, 0);
06903 if (idx < 0) {
06904 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06905 return -1;
06906 }
06907 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06908 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06909 case AST_OPTION_TONE_VERIFY:
06910 if (!p->dsp)
06911 break;
06912 cp = (char *) data;
06913 switch (*cp) {
06914 case 1:
06915 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06916 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06917 break;
06918 case 2:
06919 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06920 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06921 break;
06922 default:
06923 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06924 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06925 break;
06926 }
06927 break;
06928 case AST_OPTION_TDD:
06929
06930 cp = (char *) data;
06931 p->mate = 0;
06932 if (!*cp) {
06933 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06934 if (p->tdd)
06935 tdd_free(p->tdd);
06936 p->tdd = 0;
06937 break;
06938 }
06939 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06940 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06941 dahdi_disable_ec(p);
06942
06943 if (!p->didtdd) {
06944 unsigned char mybuf[41000];
06945 unsigned char *buf;
06946 int size, res, fd, len;
06947 struct pollfd fds[1];
06948
06949 buf = mybuf;
06950 memset(buf, 0x7f, sizeof(mybuf));
06951 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06952 len = 40000;
06953 idx = dahdi_get_index(chan, p, 0);
06954 if (idx < 0) {
06955 ast_log(LOG_WARNING, "No index in TDD?\n");
06956 return -1;
06957 }
06958 fd = p->subs[idx].dfd;
06959 while (len) {
06960 if (ast_check_hangup(chan))
06961 return -1;
06962 size = len;
06963 if (size > READ_SIZE)
06964 size = READ_SIZE;
06965 fds[0].fd = fd;
06966 fds[0].events = POLLPRI | POLLOUT;
06967 fds[0].revents = 0;
06968 res = poll(fds, 1, -1);
06969 if (!res) {
06970 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06971 continue;
06972 }
06973
06974 if (fds[0].revents & POLLPRI)
06975 return -1;
06976 if (!(fds[0].revents & POLLOUT)) {
06977 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06978 continue;
06979 }
06980 res = write(fd, buf, size);
06981 if (res != size) {
06982 if (res == -1) return -1;
06983 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06984 break;
06985 }
06986 len -= size;
06987 buf += size;
06988 }
06989 p->didtdd = 1;
06990 }
06991 if (*cp == 2) {
06992 if (p->tdd)
06993 tdd_free(p->tdd);
06994 p->tdd = 0;
06995 p->mate = 1;
06996 break;
06997 }
06998 if (!p->tdd) {
06999 p->tdd = tdd_new();
07000 }
07001 break;
07002 case AST_OPTION_RELAXDTMF:
07003 if (!p->dsp)
07004 break;
07005 cp = (char *) data;
07006 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
07007 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
07008 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
07009 break;
07010 case AST_OPTION_AUDIO_MODE:
07011 #if defined(HAVE_PRI)
07012 if (dahdi_sig_pri_lib_handles(p->sig)
07013 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
07014
07015 break;
07016 }
07017 #endif
07018
07019 cp = (char *) data;
07020 if (!*cp) {
07021 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
07022 x = 0;
07023 dahdi_disable_ec(p);
07024 } else {
07025 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
07026 x = 1;
07027 }
07028 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
07029 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
07030 break;
07031 case AST_OPTION_OPRMODE:
07032 oprmode = (struct oprmode *) data;
07033
07034 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
07035 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
07036 ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
07037 errno = EINVAL;
07038 return -1;
07039 }
07040 pp = ast_channel_tech_pvt(oprmode->peer);
07041 p->oprmode = pp->oprmode = 0;
07042
07043 p->oprpeer = pp;
07044 pp->oprpeer = p;
07045
07046 if (oprmode->mode)
07047 {
07048 pp->oprmode = oprmode->mode;
07049 p->oprmode = -oprmode->mode;
07050 }
07051 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
07052 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
07053 break;
07054 case AST_OPTION_ECHOCAN:
07055 cp = (char *) data;
07056 if (*cp) {
07057 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
07058 dahdi_enable_ec(p);
07059 } else {
07060 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
07061 dahdi_disable_ec(p);
07062 }
07063 break;
07064 case AST_OPTION_DIGIT_DETECT:
07065 cp = (char *) data;
07066 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07067 if (*cp) {
07068 enable_dtmf_detect(p);
07069 } else {
07070 disable_dtmf_detect(p);
07071 }
07072 break;
07073 case AST_OPTION_FAX_DETECT:
07074 cp = (char *) data;
07075 if (p->dsp) {
07076 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07077 if (*cp) {
07078 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
07079 } else {
07080 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07081 }
07082 ast_dsp_set_features(p->dsp, p->dsp_features);
07083 }
07084 break;
07085 default:
07086 return -1;
07087 }
07088 errno = 0;
07089
07090 return 0;
07091 }
07092
07093 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
07094 {
07095 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07096 int res = 0;
07097
07098 if (!p) {
07099
07100 *buf = '\0';
07101 return -1;
07102 }
07103
07104 if (!strcasecmp(data, "rxgain")) {
07105 ast_mutex_lock(&p->lock);
07106 snprintf(buf, len, "%f", p->rxgain);
07107 ast_mutex_unlock(&p->lock);
07108 } else if (!strcasecmp(data, "txgain")) {
07109 ast_mutex_lock(&p->lock);
07110 snprintf(buf, len, "%f", p->txgain);
07111 ast_mutex_unlock(&p->lock);
07112 } else if (!strcasecmp(data, "dahdi_channel")) {
07113 ast_mutex_lock(&p->lock);
07114 snprintf(buf, len, "%d", p->channel);
07115 ast_mutex_unlock(&p->lock);
07116 } else if (!strcasecmp(data, "dahdi_span")) {
07117 ast_mutex_lock(&p->lock);
07118 snprintf(buf, len, "%d", p->span);
07119 ast_mutex_unlock(&p->lock);
07120 } else if (!strcasecmp(data, "dahdi_type")) {
07121 ast_mutex_lock(&p->lock);
07122 switch (p->sig) {
07123 #if defined(HAVE_OPENR2)
07124 case SIG_MFCR2:
07125 ast_copy_string(buf, "mfc/r2", len);
07126 break;
07127 #endif
07128 #if defined(HAVE_PRI)
07129 case SIG_PRI_LIB_HANDLE_CASES:
07130 ast_copy_string(buf, "pri", len);
07131 break;
07132 #endif
07133 case 0:
07134 ast_copy_string(buf, "pseudo", len);
07135 break;
07136 #if defined(HAVE_SS7)
07137 case SIG_SS7:
07138 ast_copy_string(buf, "ss7", len);
07139 break;
07140 #endif
07141 default:
07142
07143 ast_copy_string(buf, "analog", len);
07144 break;
07145 }
07146 ast_mutex_unlock(&p->lock);
07147 #if defined(HAVE_PRI)
07148 #if defined(HAVE_PRI_REVERSE_CHARGE)
07149 } else if (!strcasecmp(data, "reversecharge")) {
07150 ast_mutex_lock(&p->lock);
07151 switch (p->sig) {
07152 case SIG_PRI_LIB_HANDLE_CASES:
07153 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07154 break;
07155 default:
07156 *buf = '\0';
07157 res = -1;
07158 break;
07159 }
07160 ast_mutex_unlock(&p->lock);
07161 #endif
07162 #if defined(HAVE_PRI_SETUP_KEYPAD)
07163 } else if (!strcasecmp(data, "keypad_digits")) {
07164 ast_mutex_lock(&p->lock);
07165 switch (p->sig) {
07166 case SIG_PRI_LIB_HANDLE_CASES:
07167 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07168 len);
07169 break;
07170 default:
07171 *buf = '\0';
07172 res = -1;
07173 break;
07174 }
07175 ast_mutex_unlock(&p->lock);
07176 #endif
07177 } else if (!strcasecmp(data, "no_media_path")) {
07178 ast_mutex_lock(&p->lock);
07179 switch (p->sig) {
07180 case SIG_PRI_LIB_HANDLE_CASES:
07181
07182
07183
07184
07185 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07186 break;
07187 default:
07188 *buf = '\0';
07189 res = -1;
07190 break;
07191 }
07192 ast_mutex_unlock(&p->lock);
07193 #endif
07194 } else {
07195 *buf = '\0';
07196 res = -1;
07197 }
07198
07199 return res;
07200 }
07201
07202
07203 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07204 {
07205 int res;
07206 char policy_str[21] = "";
07207
07208 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07209 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07210 return 1;
07211 }
07212 if (*num_buffers < 0) {
07213 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07214 return -1;
07215 }
07216 if (!strcasecmp(policy_str, "full")) {
07217 *policy = DAHDI_POLICY_WHEN_FULL;
07218 } else if (!strcasecmp(policy_str, "immediate")) {
07219 *policy = DAHDI_POLICY_IMMEDIATE;
07220 #if defined(HAVE_DAHDI_HALF_FULL)
07221 } else if (!strcasecmp(policy_str, "half")) {
07222 *policy = DAHDI_POLICY_HALF_FULL;
07223 #endif
07224 } else {
07225 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07226 return -1;
07227 }
07228
07229 return 0;
07230 }
07231
07232 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07233 {
07234 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07235 int res = 0;
07236
07237 if (!p) {
07238
07239 return -1;
07240 }
07241
07242 if (!strcasecmp(data, "buffers")) {
07243 int num_bufs, policy;
07244
07245 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07246 struct dahdi_bufferinfo bi = {
07247 .txbufpolicy = policy,
07248 .rxbufpolicy = policy,
07249 .bufsize = p->bufsize,
07250 .numbufs = num_bufs,
07251 };
07252 int bpres;
07253
07254 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07255 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07256 } else {
07257 p->bufferoverrideinuse = 1;
07258 }
07259 } else {
07260 res = -1;
07261 }
07262 } else if (!strcasecmp(data, "echocan_mode")) {
07263 if (!strcasecmp(value, "on")) {
07264 ast_mutex_lock(&p->lock);
07265 dahdi_enable_ec(p);
07266 ast_mutex_unlock(&p->lock);
07267 } else if (!strcasecmp(value, "off")) {
07268 ast_mutex_lock(&p->lock);
07269 dahdi_disable_ec(p);
07270 ast_mutex_unlock(&p->lock);
07271 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07272 } else if (!strcasecmp(value, "fax")) {
07273 int blah = 1;
07274
07275 ast_mutex_lock(&p->lock);
07276 if (!p->echocanon) {
07277 dahdi_enable_ec(p);
07278 }
07279 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07280 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07281 }
07282 ast_mutex_unlock(&p->lock);
07283 } else if (!strcasecmp(value, "voice")) {
07284 int blah = 0;
07285
07286 ast_mutex_lock(&p->lock);
07287 if (!p->echocanon) {
07288 dahdi_enable_ec(p);
07289 }
07290 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07291 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07292 }
07293 ast_mutex_unlock(&p->lock);
07294 #endif
07295 } else {
07296 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07297 res = -1;
07298 }
07299 } else {
07300 res = -1;
07301 }
07302
07303 return res;
07304 }
07305
07306 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07307 {
07308
07309 int x;
07310 int hasslaves;
07311 if (!master)
07312 return;
07313 if (needlock) {
07314 ast_mutex_lock(&master->lock);
07315 if (slave) {
07316 while (ast_mutex_trylock(&slave->lock)) {
07317 DEADLOCK_AVOIDANCE(&master->lock);
07318 }
07319 }
07320 }
07321 hasslaves = 0;
07322 for (x = 0; x < MAX_SLAVES; x++) {
07323 if (master->slaves[x]) {
07324 if (!slave || (master->slaves[x] == slave)) {
07325
07326 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07327 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07328 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07329 master->slaves[x]->master = NULL;
07330 master->slaves[x] = NULL;
07331 } else
07332 hasslaves = 1;
07333 }
07334 if (!hasslaves)
07335 master->inconference = 0;
07336 }
07337 if (!slave) {
07338 if (master->master) {
07339
07340 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07341 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07342 hasslaves = 0;
07343 for (x = 0; x < MAX_SLAVES; x++) {
07344 if (master->master->slaves[x] == master)
07345 master->master->slaves[x] = NULL;
07346 else if (master->master->slaves[x])
07347 hasslaves = 1;
07348 }
07349 if (!hasslaves)
07350 master->master->inconference = 0;
07351 }
07352 master->master = NULL;
07353 }
07354 update_conf(master);
07355 if (needlock) {
07356 if (slave)
07357 ast_mutex_unlock(&slave->lock);
07358 ast_mutex_unlock(&master->lock);
07359 }
07360 }
07361
07362 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07363 int x;
07364 if (!slave || !master) {
07365 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07366 return;
07367 }
07368 for (x = 0; x < MAX_SLAVES; x++) {
07369 if (!master->slaves[x]) {
07370 master->slaves[x] = slave;
07371 break;
07372 }
07373 }
07374 if (x >= MAX_SLAVES) {
07375 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07376 master->slaves[MAX_SLAVES - 1] = slave;
07377 }
07378 if (slave->master)
07379 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07380 slave->master = master;
07381
07382 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07383 }
07384
07385 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)
07386 {
07387 struct ast_channel *who;
07388 struct dahdi_pvt *p0, *p1, *op0, *op1;
07389 struct dahdi_pvt *master = NULL, *slave = NULL;
07390 struct ast_frame *f;
07391 int inconf = 0;
07392 int nothingok = 1;
07393 int ofd0, ofd1;
07394 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07395 int os0 = -1, os1 = -1;
07396 int priority = 0;
07397 struct ast_channel *oc0, *oc1;
07398 enum ast_bridge_result res;
07399 struct timeval start = ast_tvnow();
07400 #ifdef PRI_2BCT
07401 int triedtopribridge = 0;
07402 q931_call *q931c0;
07403 q931_call *q931c1;
07404 #endif
07405
07406
07407
07408
07409
07410
07411 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07412 return AST_BRIDGE_FAILED_NOWARN;
07413
07414 ast_channel_lock_both(c0, c1);
07415
07416 p0 = ast_channel_tech_pvt(c0);
07417 p1 = ast_channel_tech_pvt(c1);
07418
07419 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07420 ast_channel_unlock(c0);
07421 ast_channel_unlock(c1);
07422 return AST_BRIDGE_FAILED_NOWARN;
07423 }
07424
07425 oi0 = dahdi_get_index(c0, p0, 0);
07426 oi1 = dahdi_get_index(c1, p1, 0);
07427 if ((oi0 < 0) || (oi1 < 0)) {
07428 ast_channel_unlock(c0);
07429 ast_channel_unlock(c1);
07430 return AST_BRIDGE_FAILED;
07431 }
07432
07433 op0 = p0 = ast_channel_tech_pvt(c0);
07434 op1 = p1 = ast_channel_tech_pvt(c1);
07435 ofd0 = ast_channel_fd(c0, 0);
07436 ofd1 = ast_channel_fd(c1, 0);
07437 oc0 = p0->owner;
07438 oc1 = p1->owner;
07439
07440 if (ast_mutex_trylock(&p0->lock)) {
07441
07442 ast_channel_unlock(c0);
07443 ast_channel_unlock(c1);
07444 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07445 return AST_BRIDGE_RETRY;
07446 }
07447 if (ast_mutex_trylock(&p1->lock)) {
07448
07449 ast_mutex_unlock(&p0->lock);
07450 ast_channel_unlock(c0);
07451 ast_channel_unlock(c1);
07452 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07453 return AST_BRIDGE_RETRY;
07454 }
07455
07456 if ((p0->callwaiting && p0->callwaitingcallerid)
07457 || (p1->callwaiting && p1->callwaitingcallerid)) {
07458
07459
07460
07461
07462
07463
07464
07465
07466
07467 ast_mutex_unlock(&p0->lock);
07468 ast_mutex_unlock(&p1->lock);
07469 ast_channel_unlock(c0);
07470 ast_channel_unlock(c1);
07471 return AST_BRIDGE_FAILED_NOWARN;
07472 }
07473
07474 #if defined(HAVE_PRI)
07475 if ((dahdi_sig_pri_lib_handles(p0->sig)
07476 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07477 || (dahdi_sig_pri_lib_handles(p1->sig)
07478 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07479
07480
07481
07482
07483 ast_mutex_unlock(&p0->lock);
07484 ast_mutex_unlock(&p1->lock);
07485 ast_channel_unlock(c0);
07486 ast_channel_unlock(c1);
07487 return AST_BRIDGE_FAILED_NOWARN;
07488 }
07489 #endif
07490
07491 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07492 if (p0->owner && p1->owner) {
07493
07494 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07495 master = p0;
07496 slave = p1;
07497 inconf = 1;
07498 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07499 master = p1;
07500 slave = p0;
07501 inconf = 1;
07502 } else {
07503 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07504 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07505 p0->channel,
07506 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07507 p0->subs[SUB_REAL].inthreeway, p0->channel,
07508 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07509 p1->subs[SUB_REAL].inthreeway);
07510 }
07511 nothingok = 0;
07512 }
07513 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07514 if (p1->subs[SUB_THREEWAY].inthreeway) {
07515 master = p1;
07516 slave = p0;
07517 nothingok = 0;
07518 }
07519 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07520 if (p0->subs[SUB_THREEWAY].inthreeway) {
07521 master = p0;
07522 slave = p1;
07523 nothingok = 0;
07524 }
07525 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07526
07527
07528 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07529 master = p1;
07530 slave = p0;
07531 nothingok = 0;
07532 }
07533 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07534
07535 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07536 master = p0;
07537 slave = p1;
07538 nothingok = 0;
07539 }
07540 }
07541 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07542 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07543 if (master && slave) {
07544
07545
07546
07547 if ((oi1 == SUB_THREEWAY) &&
07548 p1->subs[SUB_THREEWAY].inthreeway &&
07549 p1->subs[SUB_REAL].owner &&
07550 p1->subs[SUB_REAL].inthreeway &&
07551 (ast_channel_state(p1->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07552 ast_debug(1,
07553 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07554 p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07555 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07556 os1 = ast_channel_state(p1->subs[SUB_REAL].owner);
07557 } else {
07558 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07559 p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07560 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07561 }
07562 if ((oi0 == SUB_THREEWAY) &&
07563 p0->subs[SUB_THREEWAY].inthreeway &&
07564 p0->subs[SUB_REAL].owner &&
07565 p0->subs[SUB_REAL].inthreeway &&
07566 (ast_channel_state(p0->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07567 ast_debug(1,
07568 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07569 p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07570 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07571 os0 = ast_channel_state(p0->subs[SUB_REAL].owner);
07572 } else {
07573 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07574 p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07575 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07576 }
07577 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07578 if (!p0->echocanbridged || !p1->echocanbridged) {
07579
07580 dahdi_disable_ec(p0);
07581 dahdi_disable_ec(p1);
07582 }
07583 }
07584 dahdi_link(slave, master);
07585 master->inconference = inconf;
07586 } else if (!nothingok)
07587 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07588
07589 update_conf(p0);
07590 update_conf(p1);
07591 t0 = p0->subs[SUB_REAL].inthreeway;
07592 t1 = p1->subs[SUB_REAL].inthreeway;
07593
07594 ast_mutex_unlock(&p0->lock);
07595 ast_mutex_unlock(&p1->lock);
07596
07597 ast_channel_unlock(c0);
07598 ast_channel_unlock(c1);
07599
07600
07601 if ((!master || !slave) && !nothingok) {
07602 dahdi_enable_ec(p0);
07603 dahdi_enable_ec(p1);
07604 return AST_BRIDGE_FAILED;
07605 }
07606
07607 ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07608
07609 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07610 disable_dtmf_detect(op0);
07611
07612 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07613 disable_dtmf_detect(op1);
07614
07615 for (;;) {
07616 struct ast_channel *c0_priority[2] = {c0, c1};
07617 struct ast_channel *c1_priority[2] = {c1, c0};
07618 int ms;
07619
07620
07621
07622
07623 ast_channel_lock_both(c0, c1);
07624
07625 p0 = ast_channel_tech_pvt(c0);
07626 p1 = ast_channel_tech_pvt(c1);
07627
07628 if (op0 == p0)
07629 i0 = dahdi_get_index(c0, p0, 1);
07630 if (op1 == p1)
07631 i1 = dahdi_get_index(c1, p1, 1);
07632
07633 ast_channel_unlock(c0);
07634 ast_channel_unlock(c1);
07635 ms = ast_remaining_ms(start, timeoutms);
07636 if (!ms ||
07637 (op0 != p0) ||
07638 (op1 != p1) ||
07639 (ofd0 != ast_channel_fd(c0, 0)) ||
07640 (ofd1 != ast_channel_fd(c1, 0)) ||
07641 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != ast_channel_state(p0->subs[SUB_REAL].owner))) ||
07642 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != ast_channel_state(p1->subs[SUB_REAL].owner))) ||
07643 (oc0 != p0->owner) ||
07644 (oc1 != p1->owner) ||
07645 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07646 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07647 (oi0 != i0) ||
07648 (oi1 != i1)) {
07649 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07650 op0->channel, oi0, op1->channel, oi1);
07651 res = AST_BRIDGE_RETRY;
07652 goto return_from_bridge;
07653 }
07654
07655 #ifdef PRI_2BCT
07656 if (!triedtopribridge) {
07657 triedtopribridge = 1;
07658 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07659 ast_mutex_lock(&p0->pri->lock);
07660 switch (p0->sig) {
07661 case SIG_PRI_LIB_HANDLE_CASES:
07662 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07663 break;
07664 default:
07665 q931c0 = NULL;
07666 break;
07667 }
07668 switch (p1->sig) {
07669 case SIG_PRI_LIB_HANDLE_CASES:
07670 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07671 break;
07672 default:
07673 q931c1 = NULL;
07674 break;
07675 }
07676 if (q931c0 && q931c1) {
07677 pri_channel_bridge(q931c0, q931c1);
07678 }
07679 ast_mutex_unlock(&p0->pri->lock);
07680 }
07681 }
07682 #endif
07683
07684 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07685 if (!who) {
07686 ast_debug(1, "Ooh, empty read...\n");
07687 continue;
07688 }
07689 f = ast_read(who);
07690 switch (f ? f->frametype : AST_FRAME_CONTROL) {
07691 case AST_FRAME_CONTROL:
07692 if (f && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
07693 ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
07694 break;
07695 }
07696 *fo = f;
07697 *rc = who;
07698 res = AST_BRIDGE_COMPLETE;
07699 goto return_from_bridge;
07700 case AST_FRAME_DTMF_END:
07701 if ((who == c0) && p0->pulsedial) {
07702 ast_write(c1, f);
07703 } else if ((who == c1) && p1->pulsedial) {
07704 ast_write(c0, f);
07705 } else {
07706 *fo = f;
07707 *rc = who;
07708 res = AST_BRIDGE_COMPLETE;
07709 goto return_from_bridge;
07710 }
07711 break;
07712 case AST_FRAME_TEXT:
07713 if (who == c0) {
07714 ast_write(c1, f);
07715 } else {
07716 ast_write(c0, f);
07717 }
07718 break;
07719 case AST_FRAME_VOICE:
07720
07721 case AST_FRAME_NULL:
07722 break;
07723 default:
07724 ast_debug(1, "Chan '%s' is discarding frame of frametype:%u\n",
07725 ast_channel_name(who), f->frametype);
07726 break;
07727 }
07728 ast_frfree(f);
07729
07730
07731 priority = !priority;
07732 }
07733
07734 return_from_bridge:
07735 if (op0 == p0)
07736 dahdi_enable_ec(p0);
07737
07738 if (op1 == p1)
07739 dahdi_enable_ec(p1);
07740
07741 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07742 enable_dtmf_detect(op0);
07743
07744 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07745 enable_dtmf_detect(op1);
07746
07747 dahdi_unlink(slave, master, 1);
07748
07749 return res;
07750 }
07751
07752 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07753 {
07754 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
07755 int x;
07756
07757 ast_mutex_lock(&p->lock);
07758
07759 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
07760 if (p->owner == oldchan) {
07761 p->owner = newchan;
07762 }
07763 for (x = 0; x < 3; x++) {
07764 if (p->subs[x].owner == oldchan) {
07765 if (!x) {
07766 dahdi_unlink(NULL, p, 0);
07767 }
07768 p->subs[x].owner = newchan;
07769 }
07770 }
07771 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07772 analog_fixup(oldchan, newchan, p->sig_pvt);
07773 #if defined(HAVE_PRI)
07774 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07775 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07776 #endif
07777 #if defined(HAVE_SS7)
07778 } else if (p->sig == SIG_SS7) {
07779 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07780 #endif
07781 }
07782 update_conf(p);
07783
07784 ast_mutex_unlock(&p->lock);
07785
07786 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
07787 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07788 }
07789 return 0;
07790 }
07791
07792 static int dahdi_ring_phone(struct dahdi_pvt *p)
07793 {
07794 int x;
07795 int res;
07796
07797 x = 0;
07798 x = DAHDI_ONHOOK;
07799 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07800 do {
07801 x = DAHDI_RING;
07802 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07803 if (res) {
07804 switch (errno) {
07805 case EBUSY:
07806 case EINTR:
07807
07808 usleep(10000);
07809 continue;
07810 case EINPROGRESS:
07811 res = 0;
07812 break;
07813 default:
07814 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07815 res = 0;
07816 }
07817 }
07818 } while (res);
07819 return res;
07820 }
07821
07822 static void *analog_ss_thread(void *data);
07823
07824 static int attempt_transfer(struct dahdi_pvt *p)
07825 {
07826
07827
07828
07829 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07830
07831
07832 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07833 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07834 if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
07835 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07836 }
07837 if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RING) {
07838 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07839 }
07840 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07841 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07842 ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07843 return -1;
07844 }
07845
07846 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07847 unalloc_sub(p, SUB_THREEWAY);
07848 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07849 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07850 if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RINGING) {
07851 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07852 }
07853 if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RING) {
07854 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07855 }
07856 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07857 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07858 ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
07859 return -1;
07860 }
07861
07862 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07863 ast_channel_unlock(p->subs[SUB_REAL].owner);
07864 unalloc_sub(p, SUB_THREEWAY);
07865
07866 return 1;
07867 } else {
07868 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07869 ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07870 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
07871 return -1;
07872 }
07873 return 0;
07874 }
07875
07876 static int check_for_conference(struct dahdi_pvt *p)
07877 {
07878 struct dahdi_confinfo ci;
07879
07880 if (p->master || (p->confno > -1))
07881 return 0;
07882 memset(&ci, 0, sizeof(ci));
07883 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07884 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07885 return 0;
07886 }
07887
07888
07889
07890 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07891 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07892 return 1;
07893 }
07894 return 0;
07895 }
07896
07897
07898
07899
07900
07901
07902 static int get_alarms(struct dahdi_pvt *p)
07903 {
07904 int res;
07905 struct dahdi_spaninfo zi;
07906 struct dahdi_params params;
07907
07908 memset(&zi, 0, sizeof(zi));
07909 zi.spanno = p->span;
07910
07911 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07912 if (zi.alarms != DAHDI_ALARM_NONE)
07913 return zi.alarms;
07914 } else {
07915 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07916 return 0;
07917 }
07918
07919
07920 memset(¶ms, 0, sizeof(params));
07921 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07922 return params.chan_alarms;
07923
07924 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07925
07926 return DAHDI_ALARM_NONE;
07927 }
07928
07929 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07930 {
07931 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
07932 struct ast_frame *f = *dest;
07933
07934 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07935 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07936 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07937
07938 if (p->confirmanswer) {
07939 if (f->frametype == AST_FRAME_DTMF_END) {
07940 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07941
07942
07943 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07944 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07945
07946 p->confirmanswer = 0;
07947 } else {
07948 p->subs[idx].f.frametype = AST_FRAME_NULL;
07949 p->subs[idx].f.subclass.integer = 0;
07950 }
07951 *dest = &p->subs[idx].f;
07952 } else if (p->callwaitcas) {
07953 if (f->frametype == AST_FRAME_DTMF_END) {
07954 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07955 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07956 ast_free(p->cidspill);
07957 p->cidspill = NULL;
07958 send_cwcidspill(p);
07959 }
07960 p->callwaitcas = 0;
07961 }
07962 p->subs[idx].f.frametype = AST_FRAME_NULL;
07963 p->subs[idx].f.subclass.integer = 0;
07964 *dest = &p->subs[idx].f;
07965 } else if (f->subclass.integer == 'f') {
07966 if (f->frametype == AST_FRAME_DTMF_END) {
07967
07968 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07969
07970 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07971 struct dahdi_bufferinfo bi = {
07972 .txbufpolicy = p->faxbuf_policy,
07973 .bufsize = p->bufsize,
07974 .numbufs = p->faxbuf_no
07975 };
07976 int res;
07977
07978 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07979 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07980 } else {
07981 p->bufferoverrideinuse = 1;
07982 }
07983 }
07984 p->faxhandled = 1;
07985 if (p->dsp) {
07986 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07987 ast_dsp_set_features(p->dsp, p->dsp_features);
07988 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07989 }
07990 if (strcmp(ast_channel_exten(ast), "fax")) {
07991 const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
07992
07993
07994
07995
07996
07997 ast_mutex_unlock(&p->lock);
07998 ast_channel_unlock(ast);
07999 if (ast_exists_extension(ast, target_context, "fax", 1,
08000 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
08001 ast_channel_lock(ast);
08002 ast_mutex_lock(&p->lock);
08003 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
08004
08005 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
08006 if (ast_async_goto(ast, target_context, "fax", 1))
08007 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
08008 } else {
08009 ast_channel_lock(ast);
08010 ast_mutex_lock(&p->lock);
08011 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
08012 }
08013 } else {
08014 ast_debug(1, "Already in a fax extension, not redirecting\n");
08015 }
08016 } else {
08017 ast_debug(1, "Fax already handled\n");
08018 }
08019 dahdi_confmute(p, 0);
08020 }
08021 p->subs[idx].f.frametype = AST_FRAME_NULL;
08022 p->subs[idx].f.subclass.integer = 0;
08023 *dest = &p->subs[idx].f;
08024 }
08025 }
08026
08027 static void handle_alarms(struct dahdi_pvt *p, int alms)
08028 {
08029 const char *alarm_str;
08030
08031 #if defined(HAVE_PRI)
08032 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
08033 return;
08034 }
08035 #endif
08036
08037 alarm_str = alarm2str(alms);
08038 if (report_alarms & REPORT_CHANNEL_ALARMS) {
08039 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
08040
08041
08042
08043
08044
08045 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
08046 "Alarm: %s\r\n"
08047 "Channel: %d\r\n",
08048 alarm_str, p->channel);
08049 }
08050
08051 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
08052 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
08053
08054
08055
08056
08057
08058 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
08059 "Alarm: %s\r\n"
08060 "Span: %d\r\n",
08061 alarm_str, p->span);
08062 }
08063 }
08064
08065 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
08066 {
08067 int res, x;
08068 int idx, mysig;
08069 char *c;
08070 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08071 pthread_t threadid;
08072 struct ast_channel *chan;
08073 struct ast_frame *f;
08074
08075 idx = dahdi_get_index(ast, p, 0);
08076 if (idx < 0) {
08077 return &ast_null_frame;
08078 }
08079 mysig = p->sig;
08080 if (p->outsigmod > -1)
08081 mysig = p->outsigmod;
08082 p->subs[idx].f.frametype = AST_FRAME_NULL;
08083 p->subs[idx].f.subclass.integer = 0;
08084 p->subs[idx].f.datalen = 0;
08085 p->subs[idx].f.samples = 0;
08086 p->subs[idx].f.mallocd = 0;
08087 p->subs[idx].f.offset = 0;
08088 p->subs[idx].f.src = "dahdi_handle_event";
08089 p->subs[idx].f.data.ptr = NULL;
08090 f = &p->subs[idx].f;
08091
08092 if (p->fake_event) {
08093 res = p->fake_event;
08094 p->fake_event = 0;
08095 } else
08096 res = dahdi_get_event(p->subs[idx].dfd);
08097
08098 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
08099
08100 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
08101 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
08102 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
08103 #if defined(HAVE_PRI)
08104 if (dahdi_sig_pri_lib_handles(p->sig)
08105 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08106 && p->pri
08107 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08108
08109 } else
08110 #endif
08111 {
08112
08113 dahdi_confmute(p, 0);
08114 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
08115 p->subs[idx].f.subclass.integer = res & 0xff;
08116 dahdi_handle_dtmf(ast, idx, &f);
08117 }
08118 return f;
08119 }
08120
08121 if (res & DAHDI_EVENT_DTMFDOWN) {
08122 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
08123 #if defined(HAVE_PRI)
08124 if (dahdi_sig_pri_lib_handles(p->sig)
08125 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08126 && p->pri
08127 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08128
08129 } else
08130 #endif
08131 {
08132
08133 dahdi_confmute(p, 1);
08134 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
08135 p->subs[idx].f.subclass.integer = res & 0xff;
08136 dahdi_handle_dtmf(ast, idx, &f);
08137 }
08138 return &p->subs[idx].f;
08139 }
08140
08141 switch (res) {
08142 case DAHDI_EVENT_EC_DISABLED:
08143 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
08144 p->echocanon = 0;
08145 break;
08146 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
08147 case DAHDI_EVENT_TX_CED_DETECTED:
08148 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
08149 break;
08150 case DAHDI_EVENT_RX_CED_DETECTED:
08151 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
08152 break;
08153 case DAHDI_EVENT_EC_NLP_DISABLED:
08154 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
08155 break;
08156 case DAHDI_EVENT_EC_NLP_ENABLED:
08157 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
08158 break;
08159 #endif
08160 case DAHDI_EVENT_BITSCHANGED:
08161 #ifdef HAVE_OPENR2
08162 if (p->sig != SIG_MFCR2) {
08163 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08164 } else {
08165 ast_debug(1, "bits changed in chan %d\n", p->channel);
08166 openr2_chan_handle_cas(p->r2chan);
08167 }
08168 #else
08169 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08170 #endif
08171 break;
08172 case DAHDI_EVENT_PULSE_START:
08173
08174 if (!ast_channel_pbx(ast))
08175 tone_zone_play_tone(p->subs[idx].dfd, -1);
08176 break;
08177 case DAHDI_EVENT_DIALCOMPLETE:
08178
08179 #if defined(HAVE_PRI)
08180 if (dahdi_sig_pri_lib_handles(p->sig)) {
08181 if (p->inalarm) {
08182 break;
08183 }
08184 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08185 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
08186 ast_channel_name(ast), strerror(errno));
08187 return NULL;
08188 }
08189 if (x) {
08190
08191 break;
08192 }
08193
08194
08195
08196
08197 sig_pri_dial_complete(p->sig_pvt, ast);
08198 break;
08199 }
08200 #endif
08201 #ifdef HAVE_OPENR2
08202 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
08203
08204
08205 break;
08206 }
08207 #endif
08208 if (p->inalarm) break;
08209 if ((p->radio || (p->oprmode < 0))) break;
08210 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08211 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
08212 return NULL;
08213 }
08214 if (!x) {
08215 dahdi_enable_ec(p);
08216 if (p->echobreak) {
08217 dahdi_train_ec(p);
08218 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08219 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08220 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08221 p->echobreak = 0;
08222 } else {
08223 p->dialing = 0;
08224 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08225
08226 if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
08227 ast_setstate(ast, AST_STATE_UP);
08228 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08229 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08230 break;
08231 } else {
08232
08233 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08234 }
08235 }
08236 if (ast_channel_state(ast) == AST_STATE_DIALING) {
08237 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08238 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08239 } else if (p->confirmanswer || (!p->dialednone
08240 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08241 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08242 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08243 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08244 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08245 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08246 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08247 || (mysig == SIG_SF_FEATB)))) {
08248 ast_setstate(ast, AST_STATE_RINGING);
08249 } else if (!p->answeronpolarityswitch) {
08250 ast_setstate(ast, AST_STATE_UP);
08251 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08252 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08253
08254 p->polarity = POLARITY_REV;
08255 } else {
08256
08257 p->polarity = POLARITY_IDLE;
08258 }
08259 }
08260 }
08261 }
08262 break;
08263 case DAHDI_EVENT_ALARM:
08264 switch (p->sig) {
08265 #if defined(HAVE_PRI)
08266 case SIG_PRI_LIB_HANDLE_CASES:
08267 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08268 break;
08269 #endif
08270 #if defined(HAVE_SS7)
08271 case SIG_SS7:
08272 sig_ss7_set_alarm(p->sig_pvt, 1);
08273 break;
08274 #endif
08275 default:
08276 p->inalarm = 1;
08277 break;
08278 }
08279 res = get_alarms(p);
08280 handle_alarms(p, res);
08281 #ifdef HAVE_PRI
08282 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08283
08284 } else {
08285 break;
08286 }
08287 #endif
08288 #if defined(HAVE_SS7)
08289 if (p->sig == SIG_SS7)
08290 break;
08291 #endif
08292 #ifdef HAVE_OPENR2
08293 if (p->sig == SIG_MFCR2)
08294 break;
08295 #endif
08296 case DAHDI_EVENT_ONHOOK:
08297 if (p->radio) {
08298 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08299 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08300 break;
08301 }
08302 if (p->oprmode < 0)
08303 {
08304 if (p->oprmode != -1) break;
08305 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08306 {
08307
08308 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08309 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08310 save_conference(p->oprpeer);
08311 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08312 }
08313 break;
08314 }
08315 switch (p->sig) {
08316 case SIG_FXOLS:
08317 case SIG_FXOGS:
08318 case SIG_FXOKS:
08319
08320 if (idx == SUB_REAL) {
08321
08322 if (p->subs[SUB_CALLWAIT].owner) {
08323
08324 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08325 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08326 unalloc_sub(p, SUB_CALLWAIT);
08327 #if 0
08328 p->subs[idx].needanswer = 0;
08329 p->subs[idx].needringing = 0;
08330 #endif
08331 p->callwaitingrepeat = 0;
08332 p->cidcwexpire = 0;
08333 p->cid_suppress_expire = 0;
08334 p->owner = NULL;
08335
08336 if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
08337 p->dialing = 1;
08338 dahdi_ring_phone(p);
08339 } else if (p->subs[SUB_THREEWAY].owner) {
08340 unsigned int mssinceflash;
08341
08342
08343 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08344
08345 DLA_UNLOCK(&p->lock);
08346 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08347
08348
08349
08350 DLA_LOCK(&p->lock);
08351 if (p->owner != ast) {
08352 ast_log(LOG_WARNING, "This isn't good...\n");
08353 return NULL;
08354 }
08355 }
08356 if (!p->subs[SUB_THREEWAY].owner) {
08357 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08358 return NULL;
08359 }
08360 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08361 ast_debug(1, "Last flash was %u ms ago\n", mssinceflash);
08362 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08363
08364
08365 if (p->subs[SUB_THREEWAY].owner)
08366 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08367 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08368 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08369 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08370 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
08371 if (p->transfer) {
08372
08373 p->subs[SUB_REAL].inthreeway = 0;
08374 p->subs[SUB_THREEWAY].inthreeway = 0;
08375
08376 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
08377 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08378
08379 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08380 p->owner = NULL;
08381
08382 dahdi_ring_phone(p);
08383 } else {
08384 if ((res = attempt_transfer(p)) < 0) {
08385 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08386 if (p->subs[SUB_THREEWAY].owner)
08387 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08388 } else if (res) {
08389
08390 if (p->subs[SUB_THREEWAY].owner)
08391 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08392 break;
08393 }
08394 }
08395 } else {
08396 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08397 if (p->subs[SUB_THREEWAY].owner)
08398 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08399 }
08400 } else {
08401 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08402
08403 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08404 p->owner = NULL;
08405
08406 dahdi_ring_phone(p);
08407 }
08408 }
08409 } else {
08410 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08411 }
08412
08413 default:
08414 dahdi_disable_ec(p);
08415 return NULL;
08416 }
08417 break;
08418 case DAHDI_EVENT_RINGOFFHOOK:
08419 if (p->inalarm) break;
08420 if (p->oprmode < 0)
08421 {
08422 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08423 {
08424
08425 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08426 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08427 restore_conference(p->oprpeer);
08428 }
08429 break;
08430 }
08431 if (p->radio)
08432 {
08433 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08434 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08435 break;
08436 }
08437
08438
08439 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
08440 c = strchr(p->dialdest, '/');
08441 if (c)
08442 c++;
08443 else
08444 c = p->dialdest;
08445 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08446 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08447 if (strlen(p->dop.dialstr) > 4) {
08448 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08449 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08450 p->echorest[sizeof(p->echorest) - 1] = '\0';
08451 p->echobreak = 1;
08452 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08453 } else
08454 p->echobreak = 0;
08455 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08456 int saveerr = errno;
08457
08458 x = DAHDI_ONHOOK;
08459 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08460 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08461 return NULL;
08462 }
08463 p->dialing = 1;
08464 return &p->subs[idx].f;
08465 }
08466 switch (p->sig) {
08467 case SIG_FXOLS:
08468 case SIG_FXOGS:
08469 case SIG_FXOKS:
08470 switch (ast_channel_state(ast)) {
08471 case AST_STATE_RINGING:
08472 dahdi_enable_ec(p);
08473 dahdi_train_ec(p);
08474 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08475 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08476
08477 p->subs[SUB_REAL].needringing = 0;
08478 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08479 ast_debug(1, "channel %d answered\n", p->channel);
08480
08481
08482 ast_free(p->cidspill);
08483 p->cidspill = NULL;
08484 restore_conference(p);
08485
08486 p->dialing = 0;
08487 p->callwaitcas = 0;
08488 if (p->confirmanswer) {
08489
08490 p->subs[idx].f.frametype = AST_FRAME_NULL;
08491 p->subs[idx].f.subclass.integer = 0;
08492 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08493
08494 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08495 if (res < 0) {
08496 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08497 p->dop.dialstr[0] = '\0';
08498 return NULL;
08499 } else {
08500 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08501 p->subs[idx].f.frametype = AST_FRAME_NULL;
08502 p->subs[idx].f.subclass.integer = 0;
08503 p->dialing = 1;
08504 }
08505 p->dop.dialstr[0] = '\0';
08506 ast_setstate(ast, AST_STATE_DIALING);
08507 } else
08508 ast_setstate(ast, AST_STATE_UP);
08509 return &p->subs[idx].f;
08510 case AST_STATE_DOWN:
08511 ast_setstate(ast, AST_STATE_RING);
08512 ast_channel_rings_set(ast, 1);
08513 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08514 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08515 ast_debug(1, "channel %d picked up\n", p->channel);
08516 return &p->subs[idx].f;
08517 case AST_STATE_UP:
08518
08519 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08520
08521 if (ast_bridged_channel(p->owner))
08522 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08523 p->subs[idx].needunhold = 1;
08524 break;
08525 case AST_STATE_RESERVED:
08526
08527 if (has_voicemail(p))
08528 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08529 else
08530 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08531 break;
08532 default:
08533 ast_log(LOG_WARNING, "FXO phone off hook in weird state %u??\n", ast_channel_state(ast));
08534 }
08535 break;
08536 case SIG_FXSLS:
08537 case SIG_FXSGS:
08538 case SIG_FXSKS:
08539 if (ast_channel_state(ast) == AST_STATE_RING) {
08540 p->ringt = p->ringt_base;
08541 }
08542
08543
08544
08545 ast_debug(1, "Setting IDLE polarity due "
08546 "to ring. Old polarity was %d\n",
08547 p->polarity);
08548 p->polarity = POLARITY_IDLE;
08549
08550
08551 case SIG_EM:
08552 case SIG_EM_E1:
08553 case SIG_EMWINK:
08554 case SIG_FEATD:
08555 case SIG_FEATDMF:
08556 case SIG_FEATDMF_TA:
08557 case SIG_E911:
08558 case SIG_FGC_CAMA:
08559 case SIG_FGC_CAMAMF:
08560 case SIG_FEATB:
08561 case SIG_SF:
08562 case SIG_SFWINK:
08563 case SIG_SF_FEATD:
08564 case SIG_SF_FEATDMF:
08565 case SIG_SF_FEATB:
08566 if (ast_channel_state(ast) == AST_STATE_PRERING)
08567 ast_setstate(ast, AST_STATE_RING);
08568 if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
08569 ast_debug(1, "Ring detected\n");
08570 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08571 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08572 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
08573 ast_debug(1, "Line answered\n");
08574 if (p->confirmanswer) {
08575 p->subs[idx].f.frametype = AST_FRAME_NULL;
08576 p->subs[idx].f.subclass.integer = 0;
08577 } else {
08578 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08579 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08580 ast_setstate(ast, AST_STATE_UP);
08581 }
08582 } else if (ast_channel_state(ast) != AST_STATE_RING)
08583 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %u on channel %d\n", ast_channel_state(ast), p->channel);
08584 break;
08585 default:
08586 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08587 }
08588 break;
08589 case DAHDI_EVENT_RINGBEGIN:
08590 switch (p->sig) {
08591 case SIG_FXSLS:
08592 case SIG_FXSGS:
08593 case SIG_FXSKS:
08594 if (ast_channel_state(ast) == AST_STATE_RING) {
08595 p->ringt = p->ringt_base;
08596 }
08597 break;
08598 }
08599 break;
08600 case DAHDI_EVENT_RINGERON:
08601 break;
08602 case DAHDI_EVENT_NOALARM:
08603 switch (p->sig) {
08604 #if defined(HAVE_PRI)
08605 case SIG_PRI_LIB_HANDLE_CASES:
08606 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08607 break;
08608 #endif
08609 #if defined(HAVE_SS7)
08610 case SIG_SS7:
08611 sig_ss7_set_alarm(p->sig_pvt, 0);
08612 break;
08613 #endif
08614 default:
08615 p->inalarm = 0;
08616 break;
08617 }
08618 handle_clear_alarms(p);
08619 break;
08620 case DAHDI_EVENT_WINKFLASH:
08621 if (p->inalarm) break;
08622 if (p->radio) break;
08623 if (p->oprmode < 0) break;
08624 if (p->oprmode > 1)
08625 {
08626 struct dahdi_params par;
08627
08628 memset(&par, 0, sizeof(par));
08629 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08630 {
08631 if (!par.rxisoffhook)
08632 {
08633
08634 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08635 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08636 save_conference(p);
08637 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08638 }
08639 }
08640 break;
08641 }
08642
08643 p->flashtime = ast_tvnow();
08644 switch (mysig) {
08645 case SIG_FXOLS:
08646 case SIG_FXOGS:
08647 case SIG_FXOKS:
08648 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08649 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08650
08651
08652 ast_free(p->cidspill);
08653 p->cidspill = NULL;
08654 restore_conference(p);
08655 p->callwaitcas = 0;
08656
08657 if (idx != SUB_REAL) {
08658 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08659 goto winkflashdone;
08660 }
08661
08662 if (p->subs[SUB_CALLWAIT].owner) {
08663
08664 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08665 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08666 p->owner = p->subs[SUB_REAL].owner;
08667 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
08668 if (ast_channel_state(p->owner) == AST_STATE_RINGING) {
08669 ast_setstate(p->owner, AST_STATE_UP);
08670 p->subs[SUB_REAL].needanswer = 1;
08671 }
08672 p->callwaitingrepeat = 0;
08673 p->cidcwexpire = 0;
08674 p->cid_suppress_expire = 0;
08675
08676 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08677 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08678 S_OR(p->mohsuggest, NULL),
08679 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08680 }
08681 p->subs[SUB_CALLWAIT].needhold = 1;
08682 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08683 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08684 S_OR(p->mohsuggest, NULL),
08685 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08686 }
08687 p->subs[SUB_REAL].needunhold = 1;
08688 } else if (!p->subs[SUB_THREEWAY].owner) {
08689 if (!p->threewaycalling) {
08690
08691 p->subs[SUB_REAL].needflash = 1;
08692 goto winkflashdone;
08693 } else if (!check_for_conference(p)) {
08694 struct ast_callid *callid = NULL;
08695 int callid_created;
08696 char cid_num[256];
08697 char cid_name[256];
08698
08699 cid_num[0] = 0;
08700 cid_name[0] = 0;
08701 if (p->dahditrcallerid && p->owner) {
08702 if (ast_channel_caller(p->owner)->id.number.valid
08703 && ast_channel_caller(p->owner)->id.number.str) {
08704 ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
08705 sizeof(cid_num));
08706 }
08707 if (ast_channel_caller(p->owner)->id.name.valid
08708 && ast_channel_caller(p->owner)->id.name.str) {
08709 ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
08710 sizeof(cid_name));
08711 }
08712 }
08713
08714
08715 if (!((ast_channel_pbx(ast)) ||
08716 (ast_channel_state(ast) == AST_STATE_UP) ||
08717 (ast_channel_state(ast) == AST_STATE_RING))) {
08718 ast_debug(1, "Flash when call not up or ringing\n");
08719 goto winkflashdone;
08720 }
08721 if (alloc_sub(p, SUB_THREEWAY)) {
08722 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08723 goto winkflashdone;
08724 }
08725 callid_created = ast_callid_threadstorage_auto(&callid);
08726
08727
08728
08729
08730
08731
08732 ast_mutex_unlock(&p->lock);
08733 ast_channel_unlock(ast);
08734 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, callid);
08735 ast_channel_lock(ast);
08736 ast_mutex_lock(&p->lock);
08737 if (p->dahditrcallerid) {
08738 if (!p->origcid_num)
08739 p->origcid_num = ast_strdup(p->cid_num);
08740 if (!p->origcid_name)
08741 p->origcid_name = ast_strdup(p->cid_name);
08742 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08743 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08744 }
08745
08746 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08747
08748 dahdi_disable_ec(p);
08749 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08750 if (res)
08751 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08752 p->owner = chan;
08753 if (!chan) {
08754 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08755 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08756 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08757 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08758 dahdi_enable_ec(p);
08759 ast_hangup(chan);
08760 } else {
08761 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08762
08763
08764 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08765 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08766 S_OR(p->mohsuggest, NULL),
08767 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08768 }
08769 p->subs[SUB_THREEWAY].needhold = 1;
08770 }
08771 ast_callid_threadstorage_auto_clean(callid, callid_created);
08772 }
08773 } else {
08774
08775 if (p->subs[SUB_THREEWAY].inthreeway) {
08776
08777 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08778
08779 if ((ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP) && (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_UP)) {
08780
08781 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08782 p->owner = p->subs[SUB_REAL].owner;
08783 }
08784
08785 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08786 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08787 p->subs[SUB_REAL].inthreeway = 0;
08788 p->subs[SUB_THREEWAY].inthreeway = 0;
08789 } else {
08790
08791 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
08792 (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
08793 int otherindex = SUB_THREEWAY;
08794
08795 ast_verb(3, "Building conference call with %s and %s\n",
08796 ast_channel_name(p->subs[SUB_THREEWAY].owner),
08797 ast_channel_name(p->subs[SUB_REAL].owner));
08798
08799 p->subs[SUB_THREEWAY].inthreeway = 1;
08800 p->subs[SUB_REAL].inthreeway = 1;
08801 if (ast_channel_state(ast) == AST_STATE_UP) {
08802 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08803 otherindex = SUB_REAL;
08804 }
08805 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08806 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08807 p->subs[otherindex].needunhold = 1;
08808 p->owner = p->subs[SUB_REAL].owner;
08809 } else {
08810 ast_verb(3, "Dumping incomplete call on on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08811 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08812 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08813 p->owner = p->subs[SUB_REAL].owner;
08814 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08815 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08816 p->subs[SUB_REAL].needunhold = 1;
08817 dahdi_enable_ec(p);
08818 }
08819 }
08820 }
08821 winkflashdone:
08822 update_conf(p);
08823 break;
08824 case SIG_EM:
08825 case SIG_EM_E1:
08826 case SIG_FEATD:
08827 case SIG_SF:
08828 case SIG_SFWINK:
08829 case SIG_SF_FEATD:
08830 case SIG_FXSLS:
08831 case SIG_FXSGS:
08832 if (p->dialing)
08833 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08834 else
08835 ast_debug(1, "Got wink in weird state %u on channel %d\n", ast_channel_state(ast), p->channel);
08836 break;
08837 case SIG_FEATDMF_TA:
08838 switch (p->whichwink) {
08839 case 0:
08840 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
08841 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08842 ast_channel_caller(p->owner)->ani.number.str, ""));
08843 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08844 ast_channel_caller(p->owner)->ani2,
08845 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08846 ast_channel_caller(p->owner)->ani.number.str, ""));
08847 break;
08848 case 1:
08849 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08850 break;
08851 case 2:
08852 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08853 return NULL;
08854 }
08855 p->whichwink++;
08856
08857 case SIG_FEATDMF:
08858 case SIG_E911:
08859 case SIG_FGC_CAMAMF:
08860 case SIG_FGC_CAMA:
08861 case SIG_FEATB:
08862 case SIG_SF_FEATDMF:
08863 case SIG_SF_FEATB:
08864 case SIG_EMWINK:
08865
08866 if (!ast_strlen_zero(p->dop.dialstr)) {
08867 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08868 if (res < 0) {
08869 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08870 p->dop.dialstr[0] = '\0';
08871 return NULL;
08872 } else
08873 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08874 }
08875 p->dop.dialstr[0] = '\0';
08876 break;
08877 default:
08878 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08879 }
08880 break;
08881 case DAHDI_EVENT_HOOKCOMPLETE:
08882 if (p->inalarm) break;
08883 if ((p->radio || (p->oprmode < 0))) break;
08884 if (p->waitingfordt.tv_sec) break;
08885 switch (mysig) {
08886 case SIG_FXSLS:
08887 case SIG_FXSGS:
08888 case SIG_FXSKS:
08889 case SIG_EM:
08890 case SIG_EM_E1:
08891 case SIG_EMWINK:
08892 case SIG_FEATD:
08893 case SIG_SF:
08894 case SIG_SFWINK:
08895 case SIG_SF_FEATD:
08896 if (!ast_strlen_zero(p->dop.dialstr)) {
08897 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08898 if (res < 0) {
08899 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08900 p->dop.dialstr[0] = '\0';
08901 return NULL;
08902 } else
08903 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08904 }
08905 p->dop.dialstr[0] = '\0';
08906 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08907 break;
08908 case SIG_FEATDMF:
08909 case SIG_FEATDMF_TA:
08910 case SIG_E911:
08911 case SIG_FGC_CAMA:
08912 case SIG_FGC_CAMAMF:
08913 case SIG_FEATB:
08914 case SIG_SF_FEATDMF:
08915 case SIG_SF_FEATB:
08916 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08917 break;
08918 default:
08919 break;
08920 }
08921 break;
08922 case DAHDI_EVENT_POLARITY:
08923
08924
08925
08926
08927
08928
08929 if (p->polarity == POLARITY_IDLE) {
08930 p->polarity = POLARITY_REV;
08931 if (p->answeronpolarityswitch &&
08932 ((ast_channel_state(ast) == AST_STATE_DIALING) ||
08933 (ast_channel_state(ast) == AST_STATE_RINGING))) {
08934 ast_debug(1, "Answering on polarity switch!\n");
08935 ast_setstate(p->owner, AST_STATE_UP);
08936 if (p->hanguponpolarityswitch) {
08937 p->polaritydelaytv = ast_tvnow();
08938 }
08939 } else
08940 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %u\n", p->channel, ast_channel_state(ast));
08941 }
08942
08943
08944 if (p->hanguponpolarityswitch &&
08945 (p->polarityonanswerdelay > 0) &&
08946 (p->polarity == POLARITY_REV) &&
08947 ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
08948
08949 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08950
08951 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08952 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08953 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08954 p->polarity = POLARITY_IDLE;
08955 } else
08956 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %u\n", p->channel, ast_channel_state(ast));
08957
08958 } else {
08959 p->polarity = POLARITY_IDLE;
08960 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %u\n", p->channel, ast_channel_state(ast));
08961 }
08962
08963 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %u, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08964 break;
08965 default:
08966 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08967 }
08968 return &p->subs[idx].f;
08969 }
08970
08971 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08972 {
08973 int res;
08974 int idx;
08975 struct ast_frame *f;
08976 int usedindex = -1;
08977 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08978
08979 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08980 idx = SUB_REAL;
08981 }
08982
08983 p->subs[idx].f.frametype = AST_FRAME_NULL;
08984 p->subs[idx].f.datalen = 0;
08985 p->subs[idx].f.samples = 0;
08986 p->subs[idx].f.mallocd = 0;
08987 p->subs[idx].f.offset = 0;
08988 p->subs[idx].f.subclass.integer = 0;
08989 p->subs[idx].f.delivery = ast_tv(0,0);
08990 p->subs[idx].f.src = "dahdi_exception";
08991 p->subs[idx].f.data.ptr = NULL;
08992
08993
08994 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08995
08996
08997
08998
08999
09000 if (p->fake_event) {
09001 res = p->fake_event;
09002 p->fake_event = 0;
09003 } else
09004 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
09005
09006 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
09007 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
09008 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
09009 p->owner = p->subs[SUB_REAL].owner;
09010 if (p->owner && ast_bridged_channel(p->owner))
09011 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09012 p->subs[SUB_REAL].needunhold = 1;
09013 }
09014 switch (res) {
09015 case DAHDI_EVENT_ONHOOK:
09016 dahdi_disable_ec(p);
09017 if (p->owner) {
09018 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
09019 dahdi_ring_phone(p);
09020 p->callwaitingrepeat = 0;
09021 p->cidcwexpire = 0;
09022 p->cid_suppress_expire = 0;
09023 } else
09024 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09025 update_conf(p);
09026 break;
09027 case DAHDI_EVENT_RINGOFFHOOK:
09028 dahdi_enable_ec(p);
09029 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09030 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
09031 p->subs[SUB_REAL].needanswer = 1;
09032 p->dialing = 0;
09033 }
09034 break;
09035 case DAHDI_EVENT_HOOKCOMPLETE:
09036 case DAHDI_EVENT_RINGERON:
09037 case DAHDI_EVENT_RINGEROFF:
09038
09039 break;
09040 case DAHDI_EVENT_WINKFLASH:
09041 p->flashtime = ast_tvnow();
09042 if (p->owner) {
09043 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
09044 if (ast_channel_state(p->owner) != AST_STATE_UP) {
09045
09046 usedindex = dahdi_get_index(p->owner, p, 0);
09047 if (usedindex > -1) {
09048 p->subs[usedindex].needanswer = 1;
09049 }
09050 ast_setstate(p->owner, AST_STATE_UP);
09051 }
09052 p->callwaitingrepeat = 0;
09053 p->cidcwexpire = 0;
09054 p->cid_suppress_expire = 0;
09055 if (ast_bridged_channel(p->owner))
09056 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09057 p->subs[SUB_REAL].needunhold = 1;
09058 } else
09059 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09060 update_conf(p);
09061 break;
09062 default:
09063 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
09064 }
09065 f = &p->subs[idx].f;
09066 return f;
09067 }
09068 if (!(p->radio || (p->oprmode < 0)))
09069 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
09070
09071 if (ast != p->owner) {
09072 if (p->owner) {
09073 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
09074 }
09075 f = &p->subs[idx].f;
09076 return f;
09077 }
09078
09079 f = dahdi_handle_event(ast);
09080 if (!f) {
09081 const char *name = ast_strdupa(ast_channel_name(ast));
09082
09083
09084 ast_mutex_unlock(&p->lock);
09085 ast_channel_unlock(ast);
09086 ast_set_hangupsource(ast, name, 0);
09087 ast_channel_lock(ast);
09088 ast_mutex_lock(&p->lock);
09089 }
09090 return f;
09091 }
09092
09093 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
09094 {
09095 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09096 struct ast_frame *f;
09097 ast_mutex_lock(&p->lock);
09098 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09099 struct analog_pvt *analog_p = p->sig_pvt;
09100 f = analog_exception(analog_p, ast);
09101 } else {
09102 f = __dahdi_exception(ast);
09103 }
09104 ast_mutex_unlock(&p->lock);
09105 return f;
09106 }
09107
09108 static struct ast_frame *dahdi_read(struct ast_channel *ast)
09109 {
09110 struct dahdi_pvt *p;
09111 int res;
09112 int idx;
09113 void *readbuf;
09114 struct ast_frame *f;
09115
09116
09117
09118
09119
09120
09121 p = ast_channel_tech_pvt(ast);
09122 while (ast_mutex_trylock(&p->lock)) {
09123 CHANNEL_DEADLOCK_AVOIDANCE(ast);
09124
09125
09126
09127
09128
09129
09130
09131
09132
09133
09134
09135
09136 if (ast_channel_tech_pvt(ast) != p) {
09137
09138 return &ast_null_frame;
09139 }
09140 }
09141
09142 idx = dahdi_get_index(ast, p, 0);
09143
09144
09145 if (idx < 0) {
09146 ast_log(LOG_WARNING, "We don't exist?\n");
09147 ast_mutex_unlock(&p->lock);
09148 return NULL;
09149 }
09150
09151 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09152 ast_mutex_unlock(&p->lock);
09153 return NULL;
09154 }
09155
09156 p->subs[idx].f.frametype = AST_FRAME_NULL;
09157 p->subs[idx].f.datalen = 0;
09158 p->subs[idx].f.samples = 0;
09159 p->subs[idx].f.mallocd = 0;
09160 p->subs[idx].f.offset = 0;
09161 p->subs[idx].f.subclass.integer = 0;
09162 p->subs[idx].f.delivery = ast_tv(0,0);
09163 p->subs[idx].f.src = "dahdi_read";
09164 p->subs[idx].f.data.ptr = NULL;
09165
09166
09167 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09168 {
09169 struct dahdi_params ps;
09170
09171 memset(&ps, 0, sizeof(ps));
09172 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09173 ast_mutex_unlock(&p->lock);
09174 return NULL;
09175 }
09176 p->firstradio = 1;
09177 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09178 if (ps.rxisoffhook)
09179 {
09180 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09181 }
09182 else
09183 {
09184 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09185 }
09186 ast_mutex_unlock(&p->lock);
09187 return &p->subs[idx].f;
09188 }
09189 if (p->ringt > 0) {
09190 if (!(--p->ringt)) {
09191 ast_mutex_unlock(&p->lock);
09192 return NULL;
09193 }
09194 }
09195
09196 #ifdef HAVE_OPENR2
09197 if (p->mfcr2) {
09198 openr2_chan_process_event(p->r2chan);
09199 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09200 struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
09201
09202
09203 if (p->mfcr2_call_accepted &&
09204 !p->mfcr2_progress_sent &&
09205 ast_channel_state(ast) == AST_STATE_RINGING) {
09206 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09207 ast_queue_frame(p->owner, &fr);
09208 p->mfcr2_progress_sent = 1;
09209 }
09210 }
09211 }
09212 #endif
09213
09214 if (p->subs[idx].needringing) {
09215
09216 p->subs[idx].needringing = 0;
09217 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09218 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09219 ast_setstate(ast, AST_STATE_RINGING);
09220 ast_mutex_unlock(&p->lock);
09221 return &p->subs[idx].f;
09222 }
09223
09224 if (p->subs[idx].needbusy) {
09225
09226 p->subs[idx].needbusy = 0;
09227 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09228 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09229 ast_mutex_unlock(&p->lock);
09230 return &p->subs[idx].f;
09231 }
09232
09233 if (p->subs[idx].needcongestion) {
09234
09235 p->subs[idx].needcongestion = 0;
09236 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09237 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09238 ast_mutex_unlock(&p->lock);
09239 return &p->subs[idx].f;
09240 }
09241
09242 if (p->subs[idx].needanswer) {
09243
09244 p->subs[idx].needanswer = 0;
09245 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09246 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09247 ast_mutex_unlock(&p->lock);
09248 return &p->subs[idx].f;
09249 }
09250 #ifdef HAVE_OPENR2
09251 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09252
09253
09254
09255
09256 ast_mutex_unlock(&p->lock);
09257 return &ast_null_frame;
09258 }
09259 #endif
09260
09261 if (p->subs[idx].needflash) {
09262
09263 p->subs[idx].needflash = 0;
09264 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09265 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09266 ast_mutex_unlock(&p->lock);
09267 return &p->subs[idx].f;
09268 }
09269
09270 if (p->subs[idx].needhold) {
09271
09272 p->subs[idx].needhold = 0;
09273 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09274 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09275 ast_mutex_unlock(&p->lock);
09276 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
09277 return &p->subs[idx].f;
09278 }
09279
09280 if (p->subs[idx].needunhold) {
09281
09282 p->subs[idx].needunhold = 0;
09283 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09284 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09285 ast_mutex_unlock(&p->lock);
09286 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
09287 return &p->subs[idx].f;
09288 }
09289
09290
09291
09292
09293
09294 if (p->fake_event && p->owner == ast) {
09295 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09296 struct analog_pvt *analog_p = p->sig_pvt;
09297
09298 f = analog_exception(analog_p, ast);
09299 } else {
09300 f = __dahdi_exception(ast);
09301 }
09302 ast_mutex_unlock(&p->lock);
09303 return f;
09304 }
09305
09306 if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
09307 if (!p->subs[idx].linear) {
09308 p->subs[idx].linear = 1;
09309 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09310 if (res)
09311 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09312 }
09313 } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) ||
09314 (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) {
09315 if (p->subs[idx].linear) {
09316 p->subs[idx].linear = 0;
09317 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09318 if (res)
09319 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09320 }
09321 } else {
09322 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
09323 ast_mutex_unlock(&p->lock);
09324 return NULL;
09325 }
09326 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09327 CHECK_BLOCKING(ast);
09328 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09329 ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
09330
09331 if (res < 0) {
09332 f = NULL;
09333 if (res == -1) {
09334 if (errno == EAGAIN) {
09335
09336 ast_mutex_unlock(&p->lock);
09337 return &p->subs[idx].f;
09338 } else if (errno == ELAST) {
09339 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09340 struct analog_pvt *analog_p = p->sig_pvt;
09341 f = analog_exception(analog_p, ast);
09342 } else {
09343 f = __dahdi_exception(ast);
09344 }
09345 } else
09346 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09347 }
09348 ast_mutex_unlock(&p->lock);
09349 return f;
09350 }
09351 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09352 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09353 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09354 struct analog_pvt *analog_p = p->sig_pvt;
09355 f = analog_exception(analog_p, ast);
09356 } else {
09357 f = __dahdi_exception(ast);
09358 }
09359 ast_mutex_unlock(&p->lock);
09360 return f;
09361 }
09362 if (p->tdd) {
09363 int c;
09364
09365 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09366 if (c < 0) {
09367 ast_debug(1,"tdd_feed failed\n");
09368 ast_mutex_unlock(&p->lock);
09369 return NULL;
09370 }
09371 if (c) {
09372 p->subs[idx].f.subclass.integer = 0;
09373 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09374 p->subs[idx].f.mallocd = 0;
09375 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09376 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09377 p->subs[idx].f.datalen = 1;
09378 *((char *) p->subs[idx].f.data.ptr) = c;
09379 ast_mutex_unlock(&p->lock);
09380 return &p->subs[idx].f;
09381 }
09382 }
09383 if (idx == SUB_REAL) {
09384
09385 if (p->cidcwexpire) {
09386 if (!--p->cidcwexpire) {
09387
09388 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09389 restore_conference(p);
09390 }
09391 }
09392 if (p->cid_suppress_expire) {
09393 --p->cid_suppress_expire;
09394 }
09395 if (p->callwaitingrepeat) {
09396 if (!--p->callwaitingrepeat) {
09397
09398 ++p->callwaitrings;
09399 dahdi_callwait(ast);
09400 }
09401 }
09402 }
09403 if (p->subs[idx].linear) {
09404 p->subs[idx].f.datalen = READ_SIZE * 2;
09405 } else
09406 p->subs[idx].f.datalen = READ_SIZE;
09407
09408
09409 if ((p->owner == ast) && p->cidspill) {
09410 send_callerid(p);
09411 }
09412
09413 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09414 ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast));
09415 p->subs[idx].f.samples = READ_SIZE;
09416 p->subs[idx].f.mallocd = 0;
09417 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09418 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09419 #if 0
09420 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09421 #endif
09422 if ((p->dialing && !p->waitingfordt.tv_sec) || p->radio ||
09423 (idx && (ast_channel_state(ast) != AST_STATE_UP)) ||
09424 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09425 ) {
09426
09427
09428 p->subs[idx].f.frametype = AST_FRAME_NULL;
09429 p->subs[idx].f.subclass.integer = 0;
09430 p->subs[idx].f.samples = 0;
09431 p->subs[idx].f.mallocd = 0;
09432 p->subs[idx].f.offset = 0;
09433 p->subs[idx].f.data.ptr = NULL;
09434 p->subs[idx].f.datalen= 0;
09435 }
09436 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
09437
09438 int mute;
09439
09440 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09441
09442
09443 mute = ast_dsp_was_muted(p->dsp);
09444 if (p->muting != mute) {
09445 p->muting = mute;
09446 dahdi_confmute(p, mute);
09447 }
09448
09449 if (f) {
09450 if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
09451 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
09452 if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
09453 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09454 ast_dsp_set_features(p->dsp, p->dsp_features);
09455 }
09456 }
09457 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09458 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
09459
09460
09461
09462
09463 ast_frfree(f);
09464 f = NULL;
09465 }
09466 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
09467 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
09468
09469 ast_frfree(f);
09470 f = NULL;
09471 }
09472 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09473 || f->frametype == AST_FRAME_DTMF_END) {
09474 #ifdef HAVE_PRI
09475 if (dahdi_sig_pri_lib_handles(p->sig)
09476 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09477 && p->pri
09478 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09479 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09480
09481 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09482 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09483 (unsigned)f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
09484
09485 f->frametype = AST_FRAME_NULL;
09486 f->subclass.integer = 0;
09487 }
09488 #endif
09489
09490 p->pulsedial = 0;
09491 } else if (p->waitingfordt.tv_sec) {
09492 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09493 p->waitingfordt.tv_sec = 0;
09494 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09495 ast_frfree(f);
09496 f = NULL;
09497 } else if (f->frametype == AST_FRAME_VOICE) {
09498 f->frametype = AST_FRAME_NULL;
09499 f->subclass.integer = 0;
09500 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) {
09501 p->waitingfordt.tv_sec = 0;
09502 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09503 ast_dsp_set_features(p->dsp, p->dsp_features);
09504 ast_debug(1, "Got 10 samples of dialtone!\n");
09505 if (!ast_strlen_zero(p->dop.dialstr)) {
09506 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09507 if (res < 0) {
09508 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09509 p->dop.dialstr[0] = '\0';
09510 ast_mutex_unlock(&p->lock);
09511 ast_frfree(f);
09512 return NULL;
09513 } else {
09514 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
09515 p->dialing = 1;
09516 p->dop.dialstr[0] = '\0';
09517 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09518 ast_setstate(ast, AST_STATE_DIALING);
09519 }
09520 }
09521 }
09522 }
09523 }
09524 }
09525 } else
09526 f = &p->subs[idx].f;
09527
09528 if (f) {
09529 switch (f->frametype) {
09530 case AST_FRAME_DTMF_BEGIN:
09531 case AST_FRAME_DTMF_END:
09532 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09533 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09534 } else {
09535 dahdi_handle_dtmf(ast, idx, &f);
09536 }
09537 break;
09538 case AST_FRAME_VOICE:
09539 if (p->cidspill || p->cid_suppress_expire) {
09540
09541 p->subs[idx].f.frametype = AST_FRAME_NULL;
09542 p->subs[idx].f.subclass.integer = 0;
09543 p->subs[idx].f.samples = 0;
09544 p->subs[idx].f.mallocd = 0;
09545 p->subs[idx].f.offset = 0;
09546 p->subs[idx].f.data.ptr = NULL;
09547 p->subs[idx].f.datalen= 0;
09548 }
09549 break;
09550 default:
09551 break;
09552 }
09553 }
09554
09555 ast_mutex_unlock(&p->lock);
09556 return f;
09557 }
09558
09559 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09560 {
09561 int sent=0;
09562 int size;
09563 int res;
09564 int fd;
09565 fd = p->subs[idx].dfd;
09566 while (len) {
09567 size = len;
09568 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09569 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09570 res = write(fd, buf, size);
09571 if (res != size) {
09572 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09573 return sent;
09574 }
09575 len -= size;
09576 buf += size;
09577 }
09578 return sent;
09579 }
09580
09581 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09582 {
09583 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09584 int res;
09585 int idx;
09586 idx = dahdi_get_index(ast, p, 0);
09587 if (idx < 0) {
09588 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09589 return -1;
09590 }
09591
09592
09593 if (frame->frametype != AST_FRAME_VOICE) {
09594 if (frame->frametype != AST_FRAME_IMAGE)
09595 ast_log(LOG_WARNING, "Don't know what to do with frame type '%u'\n", frame->frametype);
09596 return 0;
09597 }
09598 if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09599 (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09600 (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09601 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09602 return -1;
09603 }
09604 if (p->dialing) {
09605 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09606 return 0;
09607 }
09608 if (!p->owner) {
09609 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09610 return 0;
09611 }
09612 if (p->cidspill) {
09613 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09614 ast_channel_name(ast));
09615 return 0;
09616 }
09617
09618 if (!frame->data.ptr || !frame->datalen)
09619 return 0;
09620
09621 if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09622 if (!p->subs[idx].linear) {
09623 p->subs[idx].linear = 1;
09624 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09625 if (res)
09626 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09627 }
09628 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09629 } else {
09630
09631 if (p->subs[idx].linear) {
09632 p->subs[idx].linear = 0;
09633 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09634 if (res)
09635 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09636 }
09637 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09638 }
09639 if (res < 0) {
09640 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09641 return -1;
09642 }
09643 return 0;
09644 }
09645
09646 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09647 {
09648 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
09649 int res=-1;
09650 int idx;
09651 int func = DAHDI_FLASH;
09652
09653 ast_mutex_lock(&p->lock);
09654 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
09655 switch (p->sig) {
09656 #if defined(HAVE_PRI)
09657 case SIG_PRI_LIB_HANDLE_CASES:
09658 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09659 ast_mutex_unlock(&p->lock);
09660 return res;
09661 #endif
09662 #if defined(HAVE_SS7)
09663 case SIG_SS7:
09664 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09665 ast_mutex_unlock(&p->lock);
09666 return res;
09667 #endif
09668 default:
09669 break;
09670 }
09671 #ifdef HAVE_OPENR2
09672 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09673 ast_mutex_unlock(&p->lock);
09674
09675
09676 return 0;
09677 }
09678 #endif
09679 idx = dahdi_get_index(chan, p, 0);
09680 if (idx == SUB_REAL) {
09681 switch (condition) {
09682 case AST_CONTROL_BUSY:
09683 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09684 break;
09685 case AST_CONTROL_RINGING:
09686 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09687
09688 if (ast_channel_state(chan) != AST_STATE_UP) {
09689 if ((ast_channel_state(chan) != AST_STATE_RING) ||
09690 ((p->sig != SIG_FXSKS) &&
09691 (p->sig != SIG_FXSLS) &&
09692 (p->sig != SIG_FXSGS)))
09693 ast_setstate(chan, AST_STATE_RINGING);
09694 }
09695 break;
09696 case AST_CONTROL_INCOMPLETE:
09697 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
09698
09699 res = 0;
09700 break;
09701 case AST_CONTROL_PROCEEDING:
09702 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
09703
09704 res = 0;
09705 break;
09706 case AST_CONTROL_PROGRESS:
09707 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
09708
09709 res = 0;
09710 break;
09711 case AST_CONTROL_CONGESTION:
09712
09713 switch (ast_channel_hangupcause(chan)) {
09714 case AST_CAUSE_USER_BUSY:
09715 case AST_CAUSE_NORMAL_CLEARING:
09716 case 0:
09717
09718 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
09719 break;
09720 default:
09721 break;
09722 }
09723 break;
09724 case AST_CONTROL_HOLD:
09725 ast_moh_start(chan, data, p->mohinterpret);
09726 break;
09727 case AST_CONTROL_UNHOLD:
09728 ast_moh_stop(chan);
09729 break;
09730 case AST_CONTROL_RADIO_KEY:
09731 if (p->radio)
09732 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09733 res = 0;
09734 break;
09735 case AST_CONTROL_RADIO_UNKEY:
09736 if (p->radio)
09737 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09738 res = 0;
09739 break;
09740 case AST_CONTROL_FLASH:
09741
09742 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09743
09744 p->dop.dialstr[0] = '\0';
09745 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09746 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09747 ast_channel_name(chan), strerror(errno));
09748 } else
09749 res = 0;
09750 } else
09751 res = 0;
09752 break;
09753 case AST_CONTROL_SRCUPDATE:
09754 res = 0;
09755 break;
09756 case -1:
09757 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09758 break;
09759 }
09760 } else {
09761 res = 0;
09762 }
09763 ast_mutex_unlock(&p->lock);
09764 return res;
09765 }
09766
09767 #if defined(HAVE_PRI)
09768 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09769 #else
09770 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09771 #endif
09772 {
09773 struct ast_str *chan_name;
09774 int x, y;
09775
09776
09777 if (!(chan_name = ast_str_create(32))) {
09778 return NULL;
09779 }
09780 if (i->channel == CHAN_PSEUDO) {
09781 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09782 #if defined(HAVE_PRI)
09783 } else if (i->pri) {
09784 ast_mutex_lock(&i->pri->lock);
09785 y = ++i->pri->new_chan_seq;
09786 if (is_outgoing) {
09787 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, (unsigned)y);
09788 address[0] = '\0';
09789 } else if (ast_strlen_zero(i->cid_subaddr)) {
09790
09791 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, (unsigned)y);
09792 } else {
09793
09794 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09795 i->cid_subaddr, (unsigned)y);
09796 }
09797 ast_mutex_unlock(&i->pri->lock);
09798 #endif
09799 } else {
09800 y = 1;
09801 do {
09802 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09803 for (x = 0; x < 3; ++x) {
09804 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09805 ast_channel_name(i->subs[x].owner) + 6)) {
09806 break;
09807 }
09808 }
09809 ++y;
09810 } while (x < 3);
09811 }
09812 return chan_name;
09813 }
09814
09815 static struct ast_channel *dahdi_new_callid_clean(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid, int callid_created)
09816 {
09817 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, linkedid, callid);
09818
09819 ast_callid_threadstorage_auto_clean(callid, callid_created);
09820
09821 return new_channel;
09822 }
09823
09824 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid, struct ast_callid *callid)
09825 {
09826 struct ast_channel *tmp;
09827 struct ast_format deflaw;
09828 int x;
09829 int features;
09830 struct ast_str *chan_name;
09831 struct ast_variable *v;
09832 char *dashptr;
09833 char device_name[AST_CHANNEL_NAME];
09834
09835 if (i->subs[idx].owner) {
09836 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09837 return NULL;
09838 }
09839
09840 ast_format_clear(&deflaw);
09841 #if defined(HAVE_PRI)
09842
09843
09844
09845
09846 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09847 #else
09848 chan_name = create_channel_name(i);
09849 #endif
09850 if (!chan_name) {
09851 return NULL;
09852 }
09853
09854 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));
09855 ast_free(chan_name);
09856 if (!tmp) {
09857 return NULL;
09858 }
09859
09860 if (callid) {
09861 ast_channel_callid_set(tmp, callid);
09862 }
09863
09864 ast_channel_tech_set(tmp, &dahdi_tech);
09865 #if defined(HAVE_PRI)
09866 if (i->pri) {
09867 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09868 }
09869 #endif
09870 ast_channel_cc_params_init(tmp, i->cc_params);
09871 if (law) {
09872 i->law = law;
09873 if (law == DAHDI_LAW_ALAW) {
09874 ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09875 } else {
09876 ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09877 }
09878 } else {
09879 switch (i->sig) {
09880 case SIG_PRI_LIB_HANDLE_CASES:
09881
09882 i->law = (i->law_default == DAHDI_LAW_ALAW)
09883 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09884 break;
09885 default:
09886 i->law = i->law_default;
09887 break;
09888 }
09889 if (i->law_default == DAHDI_LAW_ALAW) {
09890 ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09891 } else {
09892 ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09893 }
09894 }
09895 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09896 ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw);
09897
09898 ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw);
09899 ast_format_copy(ast_channel_readformat(tmp), &deflaw);
09900 ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw);
09901 ast_format_copy(ast_channel_writeformat(tmp), &deflaw);
09902 i->subs[idx].linear = 0;
09903 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09904 features = 0;
09905 if (idx == SUB_REAL) {
09906 if (i->busydetect && CANBUSYDETECT(i))
09907 features |= DSP_FEATURE_BUSY_DETECT;
09908 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09909 features |= DSP_FEATURE_CALL_PROGRESS;
09910 if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
09911 features |= DSP_FEATURE_WAITDIALTONE;
09912 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09913 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09914 features |= DSP_FEATURE_FAX_DETECT;
09915 }
09916 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09917 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09918 i->hardwaredtmf = 0;
09919 features |= DSP_FEATURE_DIGIT_DETECT;
09920 } else if (NEED_MFDETECT(i)) {
09921 i->hardwaredtmf = 1;
09922 features |= DSP_FEATURE_DIGIT_DETECT;
09923 }
09924 }
09925 if (features) {
09926 if (i->dsp) {
09927 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
09928 } else {
09929 if (i->channel != CHAN_PSEUDO)
09930 i->dsp = ast_dsp_new();
09931 else
09932 i->dsp = NULL;
09933 if (i->dsp) {
09934 i->dsp_features = features;
09935 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09936
09937 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09938
09939
09940 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09941 features = 0;
09942 }
09943 #endif
09944 ast_dsp_set_features(i->dsp, features);
09945 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09946 if (!ast_strlen_zero(progzone))
09947 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09948 if (i->busydetect && CANBUSYDETECT(i)) {
09949 ast_dsp_set_busy_count(i->dsp, i->busycount);
09950 ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
09951 }
09952 }
09953 }
09954 }
09955
09956 i->dialtone_scanning_time_elapsed = 0;
09957
09958 if (state == AST_STATE_RING)
09959 ast_channel_rings_set(tmp, 1);
09960 ast_channel_tech_pvt_set(tmp, i);
09961 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09962
09963 ast_channel_callgroup_set(tmp, i->callgroup);
09964 ast_channel_pickupgroup_set(tmp, i->pickupgroup);
09965 ast_channel_named_callgroups_set(tmp, i->named_callgroups);
09966 ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
09967 }
09968 if (!ast_strlen_zero(i->parkinglot))
09969 ast_channel_parkinglot_set(tmp, i->parkinglot);
09970 if (!ast_strlen_zero(i->language))
09971 ast_channel_language_set(tmp, i->language);
09972 if (!i->owner)
09973 i->owner = tmp;
09974 if (!ast_strlen_zero(i->accountcode))
09975 ast_channel_accountcode_set(tmp, i->accountcode);
09976 if (i->amaflags)
09977 ast_channel_amaflags_set(tmp, i->amaflags);
09978 i->subs[idx].owner = tmp;
09979 ast_channel_context_set(tmp, i->context);
09980 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09981 ast_channel_call_forward_set(tmp, i->call_forward);
09982 }
09983
09984 if (!i->adsi)
09985 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
09986 if (!ast_strlen_zero(i->exten))
09987 ast_channel_exten_set(tmp, i->exten);
09988 if (!ast_strlen_zero(i->rdnis)) {
09989 ast_channel_redirecting(tmp)->from.number.valid = 1;
09990 ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
09991 }
09992 if (!ast_strlen_zero(i->dnid)) {
09993 ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
09994 }
09995
09996
09997
09998 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09999 if (!ast_strlen_zero(i->cid_ani)) {
10000 ast_channel_caller(tmp)->ani.number.valid = 1;
10001 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
10002 } else if (!ast_strlen_zero(i->cid_num)) {
10003 ast_channel_caller(tmp)->ani.number.valid = 1;
10004 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10005 }
10006 #else
10007 if (!ast_strlen_zero(i->cid_num)) {
10008 ast_channel_caller(tmp)->ani.number.valid = 1;
10009 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10010 }
10011 #endif
10012 ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
10013 ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
10014 ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
10015 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
10016 ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
10017
10018 i->fake_event = 0;
10019
10020 dahdi_confmute(i, 0);
10021 i->muting = 0;
10022
10023 ast_jb_configure(tmp, &global_jbconf);
10024
10025
10026 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
10027 dashptr = strrchr(device_name, '-');
10028 if (dashptr) {
10029 *dashptr = '\0';
10030 }
10031 ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
10032 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
10033
10034 for (v = i->vars ; v ; v = v->next)
10035 pbx_builtin_setvar_helper(tmp, v->name, v->value);
10036
10037 ast_module_ref(ast_module_info->self);
10038
10039 dahdi_ami_channel_event(i, tmp);
10040 if (startpbx) {
10041 #ifdef HAVE_OPENR2
10042 if (i->mfcr2call) {
10043 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
10044 }
10045 #endif
10046 if (ast_pbx_start(tmp)) {
10047 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
10048 ast_hangup(tmp);
10049 return NULL;
10050 }
10051 }
10052 return tmp;
10053 }
10054
10055
10056 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
10057 {
10058 char c;
10059
10060 *str = 0;
10061 for (;;)
10062 {
10063
10064 c = ast_waitfordigit(chan, ms);
10065
10066 if (c < 1)
10067 return c;
10068 *str++ = c;
10069 *str = 0;
10070 if (strchr(term, c))
10071 return 1;
10072 }
10073 }
10074
10075 static int dahdi_wink(struct dahdi_pvt *p, int idx)
10076 {
10077 int j;
10078 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
10079 for (;;)
10080 {
10081
10082 j = DAHDI_IOMUX_SIGEVENT;
10083
10084 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
10085
10086 if (j & DAHDI_IOMUX_SIGEVENT) break;
10087 }
10088
10089 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
10090 return 0;
10091 }
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101
10102 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
10103 {
10104 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
10105 return analog_dnd(dahdichan->sig_pvt, flag);
10106 }
10107
10108 if (flag == -1) {
10109 return dahdichan->dnd;
10110 }
10111
10112
10113 dahdichan->dnd = flag;
10114 ast_verb(3, "%s DND on channel %d\n",
10115 flag? "Enabled" : "Disabled",
10116 dahdichan->channel);
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
10131 "Channel: DAHDI/%d\r\n"
10132 "Status: %s\r\n", dahdichan->channel,
10133 flag? "enabled" : "disabled");
10134
10135 return 0;
10136 }
10137
10138 static int canmatch_featurecode(const char *exten)
10139 {
10140 int extlen = strlen(exten);
10141 const char *pickup_ext;
10142 if (!extlen) {
10143 return 1;
10144 }
10145 pickup_ext = ast_pickup_ext();
10146 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
10147 return 1;
10148 }
10149
10150 if (exten[0] == '*' && extlen < 3) {
10151 if (extlen == 1) {
10152 return 1;
10153 }
10154
10155 switch (exten[1]) {
10156 case '6':
10157 case '7':
10158 case '8':
10159 return 1;
10160 }
10161 }
10162 return 0;
10163 }
10164
10165 static void *analog_ss_thread(void *data)
10166 {
10167 struct ast_channel *chan = data;
10168 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
10169 char exten[AST_MAX_EXTENSION] = "";
10170 char exten2[AST_MAX_EXTENSION] = "";
10171 unsigned char buf[256];
10172 char dtmfcid[300];
10173 char dtmfbuf[300];
10174 struct callerid_state *cs = NULL;
10175 char *name = NULL, *number = NULL;
10176 int distMatches;
10177 int curRingData[3];
10178 int receivedRingT;
10179 int counter1;
10180 int counter;
10181 int samples = 0;
10182 struct ast_smdi_md_message *smdi_msg = NULL;
10183 int flags = 0;
10184 int i;
10185 int timeout;
10186 int getforward = 0;
10187 char *s1, *s2;
10188 int len = 0;
10189 int res;
10190 int idx;
10191 struct ast_format tmpfmt;
10192
10193 ast_mutex_lock(&ss_thread_lock);
10194 ss_thread_count++;
10195 ast_mutex_unlock(&ss_thread_lock);
10196
10197
10198
10199 if (!p) {
10200 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
10201 ast_hangup(chan);
10202 goto quit;
10203 }
10204 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
10205 idx = dahdi_get_index(chan, p, 1);
10206 if (idx < 0) {
10207 ast_log(LOG_WARNING, "Huh?\n");
10208 ast_hangup(chan);
10209 goto quit;
10210 }
10211 if (p->dsp)
10212 ast_dsp_digitreset(p->dsp);
10213 switch (p->sig) {
10214 case SIG_FEATD:
10215 case SIG_FEATDMF:
10216 case SIG_FEATDMF_TA:
10217 case SIG_E911:
10218 case SIG_FGC_CAMAMF:
10219 case SIG_FEATB:
10220 case SIG_EMWINK:
10221 case SIG_SF_FEATD:
10222 case SIG_SF_FEATDMF:
10223 case SIG_SF_FEATB:
10224 case SIG_SFWINK:
10225 if (dahdi_wink(p, idx))
10226 goto quit;
10227
10228 case SIG_EM:
10229 case SIG_EM_E1:
10230 case SIG_SF:
10231 case SIG_FGC_CAMA:
10232 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10233 if (p->dsp)
10234 ast_dsp_digitreset(p->dsp);
10235
10236 if (p->dsp) {
10237 if (NEED_MFDETECT(p))
10238 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10239 else
10240 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10241 }
10242 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10243
10244 if (!p->immediate)
10245
10246 res = ast_waitfordigit(chan, 5000);
10247 else
10248 res = 0;
10249 if (res > 0) {
10250
10251 dtmfbuf[0] = res;
10252 switch (p->sig) {
10253 case SIG_FEATD:
10254 case SIG_SF_FEATD:
10255 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10256 if (res > 0)
10257 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10258 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10259 break;
10260 case SIG_FEATDMF_TA:
10261 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10262 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10263 if (dahdi_wink(p, idx)) goto quit;
10264 dtmfbuf[0] = 0;
10265
10266 res = ast_waitfordigit(chan, 5000);
10267 if (res <= 0) break;
10268 dtmfbuf[0] = res;
10269
10270 case SIG_FEATDMF:
10271 case SIG_E911:
10272 case SIG_FGC_CAMAMF:
10273 case SIG_SF_FEATDMF:
10274 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10275
10276 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10277 {
10278 if (dahdi_wink(p, idx)) goto quit;
10279 dtmfbuf[0] = 0;
10280
10281 res = ast_waitfordigit(chan, 5000);
10282 if (res <= 0) break;
10283 dtmfbuf[0] = res;
10284 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10285 }
10286 if (res > 0) {
10287
10288 if (p->sig == SIG_E911)
10289 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10290 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10291 }
10292 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10293 break;
10294 case SIG_FEATB:
10295 case SIG_SF_FEATB:
10296 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10297 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10298 break;
10299 case SIG_EMWINK:
10300
10301
10302
10303
10304 if (res == '*') {
10305 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10306 if (res > 0)
10307 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10308 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10309 break;
10310 }
10311 default:
10312
10313 len = 1;
10314 dtmfbuf[len] = '\0';
10315 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10316 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10317 timeout = matchdigittimeout;
10318 } else {
10319 timeout = gendigittimeout;
10320 }
10321 res = ast_waitfordigit(chan, timeout);
10322 if (res < 0) {
10323 ast_debug(1, "waitfordigit returned < 0...\n");
10324 ast_hangup(chan);
10325 goto quit;
10326 } else if (res) {
10327 dtmfbuf[len++] = res;
10328 dtmfbuf[len] = '\0';
10329 } else {
10330 break;
10331 }
10332 }
10333 break;
10334 }
10335 }
10336 if (res == -1) {
10337 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10338 ast_hangup(chan);
10339 goto quit;
10340 } else if (res < 0) {
10341 ast_debug(1, "Got hung up before digits finished\n");
10342 ast_hangup(chan);
10343 goto quit;
10344 }
10345
10346 if (p->sig == SIG_FGC_CAMA) {
10347 char anibuf[100];
10348
10349 if (ast_safe_sleep(chan,1000) == -1) {
10350 ast_hangup(chan);
10351 goto quit;
10352 }
10353 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10354 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10355 res = my_getsigstr(chan, anibuf, "#", 10000);
10356 if ((res > 0) && (strlen(anibuf) > 2)) {
10357 if (anibuf[strlen(anibuf) - 1] == '#')
10358 anibuf[strlen(anibuf) - 1] = 0;
10359 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10360 }
10361 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10362 }
10363
10364 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10365 if (ast_strlen_zero(exten))
10366 ast_copy_string(exten, "s", sizeof(exten));
10367 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10368
10369 if (exten[0] == '*') {
10370 char *stringp=NULL;
10371 ast_copy_string(exten2, exten, sizeof(exten2));
10372
10373 stringp=exten2 +1;
10374 s1 = strsep(&stringp, "*");
10375 s2 = strsep(&stringp, "*");
10376 if (s2) {
10377 if (!ast_strlen_zero(p->cid_num))
10378 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10379 else
10380 ast_set_callerid(chan, s1, NULL, s1);
10381 ast_copy_string(exten, s2, sizeof(exten));
10382 } else
10383 ast_copy_string(exten, s1, sizeof(exten));
10384 } else if (p->sig == SIG_FEATD)
10385 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10386 }
10387 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10388 if (exten[0] == '*') {
10389 char *stringp=NULL;
10390 ast_copy_string(exten2, exten, sizeof(exten2));
10391
10392 stringp=exten2 +1;
10393 s1 = strsep(&stringp, "#");
10394 s2 = strsep(&stringp, "#");
10395 if (s2) {
10396 if (!ast_strlen_zero(p->cid_num))
10397 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10398 else
10399 if (*(s1 + 2))
10400 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10401 ast_copy_string(exten, s2 + 1, sizeof(exten));
10402 } else
10403 ast_copy_string(exten, s1 + 2, sizeof(exten));
10404 } else
10405 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10406 }
10407 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10408 if (exten[0] == '*') {
10409 char *stringp=NULL;
10410 ast_copy_string(exten2, exten, sizeof(exten2));
10411
10412 stringp=exten2 +1;
10413 s1 = strsep(&stringp, "#");
10414 s2 = strsep(&stringp, "#");
10415 if (s2 && (*(s2 + 1) == '0')) {
10416 if (*(s2 + 2))
10417 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10418 }
10419 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10420 else ast_copy_string(exten, "911", sizeof(exten));
10421 } else
10422 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10423 }
10424 if (p->sig == SIG_FEATB) {
10425 if (exten[0] == '*') {
10426 char *stringp=NULL;
10427 ast_copy_string(exten2, exten, sizeof(exten2));
10428
10429 stringp=exten2 +1;
10430 s1 = strsep(&stringp, "#");
10431 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10432 } else
10433 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10434 }
10435 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10436 dahdi_wink(p, idx);
10437
10438
10439
10440 if (ast_safe_sleep(chan, 100)) {
10441 ast_hangup(chan);
10442 goto quit;
10443 }
10444 }
10445 dahdi_enable_ec(p);
10446 if (NEED_MFDETECT(p)) {
10447 if (p->dsp) {
10448 if (!p->hardwaredtmf)
10449 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10450 else {
10451 ast_dsp_free(p->dsp);
10452 p->dsp = NULL;
10453 }
10454 }
10455 }
10456
10457 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10458 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10459 ast_channel_exten_set(chan, exten);
10460 if (p->dsp) ast_dsp_digitreset(p->dsp);
10461 res = ast_pbx_run(chan);
10462 if (res) {
10463 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10464 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10465 }
10466 goto quit;
10467 } else {
10468 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10469 sleep(2);
10470 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10471 if (res < 0)
10472 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10473 else
10474 sleep(1);
10475 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10476 if (res >= 0)
10477 ast_waitstream(chan, "");
10478 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10479 ast_hangup(chan);
10480 goto quit;
10481 }
10482 break;
10483 case SIG_FXOLS:
10484 case SIG_FXOGS:
10485 case SIG_FXOKS:
10486
10487 timeout = firstdigittimeout;
10488
10489
10490 if (p->subs[SUB_THREEWAY].owner)
10491 timeout = 999999;
10492 while (len < AST_MAX_EXTENSION-1) {
10493
10494
10495 if (p->immediate)
10496 res = 's';
10497 else
10498 res = ast_waitfordigit(chan, timeout);
10499 timeout = 0;
10500 if (res < 0) {
10501 ast_debug(1, "waitfordigit returned < 0...\n");
10502 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10503 ast_hangup(chan);
10504 goto quit;
10505 } else if (res) {
10506 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10507 exten[len++]=res;
10508 exten[len] = '\0';
10509 }
10510 if (!ast_ignore_pattern(ast_channel_context(chan), exten))
10511 tone_zone_play_tone(p->subs[idx].dfd, -1);
10512 else
10513 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10514 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, ast_channel_context(chan))) {
10515 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10516 if (getforward) {
10517
10518 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10519 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10520 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10521 if (res)
10522 break;
10523 usleep(500000);
10524 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10525 sleep(1);
10526 memset(exten, 0, sizeof(exten));
10527 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10528 len = 0;
10529 getforward = 0;
10530 } else {
10531 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10532 ast_channel_exten_set(chan, exten);
10533 if (!ast_strlen_zero(p->cid_num)) {
10534 if (!p->hidecallerid)
10535 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10536 else
10537 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10538 }
10539 if (!ast_strlen_zero(p->cid_name)) {
10540 if (!p->hidecallerid)
10541 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10542 }
10543 ast_setstate(chan, AST_STATE_RING);
10544 dahdi_enable_ec(p);
10545 res = ast_pbx_run(chan);
10546 if (res) {
10547 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10548 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10549 }
10550 goto quit;
10551 }
10552 } else {
10553
10554
10555 timeout = matchdigittimeout;
10556 }
10557 } else if (res == 0) {
10558 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10559 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10560 dahdi_wait_event(p->subs[idx].dfd);
10561 ast_hangup(chan);
10562 goto quit;
10563 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10564 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10565
10566 p->callwaiting = 0;
10567 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10568 if (res) {
10569 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10570 ast_channel_name(chan), strerror(errno));
10571 }
10572 len = 0;
10573 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10574 memset(exten, 0, sizeof(exten));
10575 timeout = firstdigittimeout;
10576
10577 } else if (!strcmp(exten,ast_pickup_ext())) {
10578
10579
10580
10581
10582 if (idx == SUB_REAL) {
10583
10584 if (p->subs[SUB_THREEWAY].owner) {
10585
10586
10587 alloc_sub(p, SUB_CALLWAIT);
10588 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10589 unalloc_sub(p, SUB_THREEWAY);
10590 }
10591 dahdi_enable_ec(p);
10592 if (ast_pickup_call(chan)) {
10593 ast_debug(1, "No call pickup possible...\n");
10594 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10595 dahdi_wait_event(p->subs[idx].dfd);
10596 }
10597 ast_hangup(chan);
10598 goto quit;
10599 } else {
10600 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10601 ast_hangup(chan);
10602 goto quit;
10603 }
10604
10605 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10606 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10607
10608 p->hidecallerid = 1;
10609 ast_party_number_free(&ast_channel_caller(chan)->id.number);
10610 ast_party_number_init(&ast_channel_caller(chan)->id.number);
10611 ast_party_name_free(&ast_channel_caller(chan)->id.name);
10612 ast_party_name_init(&ast_channel_caller(chan)->id.name);
10613 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10614 if (res) {
10615 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10616 ast_channel_name(chan), strerror(errno));
10617 }
10618 len = 0;
10619 memset(exten, 0, sizeof(exten));
10620 timeout = firstdigittimeout;
10621 } else if (p->callreturn && !strcmp(exten, "*69")) {
10622 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10623 break;
10624 } else if (!strcmp(exten, "*78")) {
10625 dahdi_dnd(p, 1);
10626
10627 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10628 getforward = 0;
10629 memset(exten, 0, sizeof(exten));
10630 len = 0;
10631 } else if (!strcmp(exten, "*79")) {
10632 dahdi_dnd(p, 0);
10633
10634 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10635 getforward = 0;
10636 memset(exten, 0, sizeof(exten));
10637 len = 0;
10638 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10639 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10640 getforward = 1;
10641 memset(exten, 0, sizeof(exten));
10642 len = 0;
10643 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10644 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10645 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10646 memset(p->call_forward, 0, sizeof(p->call_forward));
10647 getforward = 0;
10648 memset(exten, 0, sizeof(exten));
10649 len = 0;
10650 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, ast_channel_context(chan)) &&
10651 p->subs[SUB_THREEWAY].owner &&
10652 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10653
10654
10655 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10656 chan, exten, ast_channel_context(chan), 0, NULL);
10657 ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
10658 break;
10659 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10660 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10661
10662 p->hidecallerid = 0;
10663 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10664 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10665 if (res) {
10666 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10667 ast_channel_name(chan), strerror(errno));
10668 }
10669 len = 0;
10670 memset(exten, 0, sizeof(exten));
10671 timeout = firstdigittimeout;
10672 } else if (!strcmp(exten, "*0")) {
10673 struct ast_channel *nbridge =
10674 p->subs[SUB_THREEWAY].owner;
10675 struct dahdi_pvt *pbridge = NULL;
10676
10677 if (nbridge && ast_bridged_channel(nbridge))
10678 pbridge = ast_channel_tech_pvt(ast_bridged_channel(nbridge));
10679 if (nbridge && pbridge &&
10680 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10681 (ast_channel_tech(ast_bridged_channel(nbridge)) == &dahdi_tech) &&
10682 ISTRUNK(pbridge)) {
10683 int func = DAHDI_FLASH;
10684
10685 p->dop.dialstr[0] = '\0';
10686
10687 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10688 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10689 ast_channel_name(nbridge), strerror(errno));
10690 }
10691 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10692 unalloc_sub(p, SUB_THREEWAY);
10693 p->owner = p->subs[SUB_REAL].owner;
10694 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10695 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10696 ast_hangup(chan);
10697 goto quit;
10698 } else {
10699 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10700 dahdi_wait_event(p->subs[idx].dfd);
10701 tone_zone_play_tone(p->subs[idx].dfd, -1);
10702 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10703 unalloc_sub(p, SUB_THREEWAY);
10704 p->owner = p->subs[SUB_REAL].owner;
10705 ast_hangup(chan);
10706 goto quit;
10707 }
10708 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10709 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10710 && !canmatch_featurecode(exten)) {
10711 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10712 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10713 ast_channel_context(chan));
10714 break;
10715 }
10716 if (!timeout)
10717 timeout = gendigittimeout;
10718 if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10719 tone_zone_play_tone(p->subs[idx].dfd, -1);
10720 }
10721 break;
10722 case SIG_FXSLS:
10723 case SIG_FXSGS:
10724 case SIG_FXSKS:
10725
10726 if (p->use_smdi && p->smdi_iface) {
10727 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10728
10729 if (smdi_msg != NULL) {
10730 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10731
10732 if (smdi_msg->type == 'B')
10733 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10734 else if (smdi_msg->type == 'N')
10735 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10736
10737 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10738 } else {
10739 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10740 }
10741 }
10742
10743 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10744 number = smdi_msg->calling_st;
10745
10746
10747
10748
10749 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10750 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10751
10752 if (p->cid_signalling == CID_SIG_DTMF) {
10753 int k = 0;
10754 int off_ms;
10755 struct timeval start = ast_tvnow();
10756 int ms;
10757 cs = NULL;
10758 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10759 dahdi_setlinear(p->subs[idx].dfd, 0);
10760
10761
10762
10763
10764
10765
10766 ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10767 off_ms = 4000;
10768 for (;;) {
10769 struct ast_frame *f;
10770
10771 ms = ast_remaining_ms(start, off_ms);
10772 res = ast_waitfor(chan, ms);
10773 if (res <= 0) {
10774
10775
10776
10777
10778
10779 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10780 "Exiting simple switch\n");
10781 ast_hangup(chan);
10782 goto quit;
10783 }
10784 f = ast_read(chan);
10785 if (!f)
10786 break;
10787 if (f->frametype == AST_FRAME_DTMF) {
10788 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10789 dtmfbuf[k++] = f->subclass.integer;
10790 }
10791 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10792 start = ast_tvnow();
10793 }
10794 ast_frfree(f);
10795 if (ast_channel_state(chan) == AST_STATE_RING ||
10796 ast_channel_state(chan) == AST_STATE_RINGING)
10797 break;
10798 }
10799 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10800 dtmfbuf[k] = '\0';
10801 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10802
10803 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10804 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10805 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10806
10807 if (!ast_strlen_zero(dtmfcid))
10808 number = dtmfcid;
10809 else
10810 number = NULL;
10811
10812 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10813 cs = callerid_new(p->cid_signalling);
10814 if (cs) {
10815 int off_ms;
10816 struct timeval start;
10817 int ms;
10818 samples = 0;
10819 #if 1
10820 bump_gains(p);
10821 #endif
10822
10823 dahdi_setlinear(p->subs[idx].dfd, 0);
10824
10825
10826 for (;;) {
10827 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10828 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10829 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10830 callerid_free(cs);
10831 ast_hangup(chan);
10832 goto quit;
10833 }
10834 if (i & DAHDI_IOMUX_SIGEVENT) {
10835 res = dahdi_get_event(p->subs[idx].dfd);
10836 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10837 if (res == DAHDI_EVENT_NOALARM) {
10838 p->inalarm = 0;
10839 }
10840
10841 if (p->cid_signalling == CID_SIG_V23_JP) {
10842 if (res == DAHDI_EVENT_RINGBEGIN) {
10843 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10844 usleep(1);
10845 }
10846 } else {
10847 res = 0;
10848 break;
10849 }
10850 } else if (i & DAHDI_IOMUX_READ) {
10851 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10852 if (res < 0) {
10853 if (errno != ELAST) {
10854 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10855 callerid_free(cs);
10856 ast_hangup(chan);
10857 goto quit;
10858 }
10859 break;
10860 }
10861 samples += res;
10862
10863 if (p->cid_signalling == CID_SIG_V23_JP) {
10864 res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10865 } else {
10866 res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10867 }
10868 if (res < 0) {
10869
10870
10871
10872
10873 ast_log(LOG_WARNING,
10874 "Failed to decode CallerID on channel '%s'\n",
10875 ast_channel_name(chan));
10876 break;
10877 } else if (res)
10878 break;
10879 else if (samples > (8000 * 10))
10880 break;
10881 }
10882 }
10883 if (res == 1) {
10884 callerid_get(cs, &name, &number, &flags);
10885 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10886 }
10887
10888 if (p->cid_signalling == CID_SIG_V23_JP) {
10889 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10890 usleep(1);
10891 }
10892
10893
10894 start = ast_tvnow();
10895 off_ms = 4000;
10896 for (;;) {
10897 struct ast_frame *f;
10898
10899 ms = ast_remaining_ms(start, off_ms);
10900 res = ast_waitfor(chan, ms);
10901 if (res <= 0) {
10902 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10903 "Exiting simple switch\n");
10904 ast_hangup(chan);
10905 goto quit;
10906 }
10907 if (!(f = ast_read(chan))) {
10908 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10909 ast_hangup(chan);
10910 goto quit;
10911 }
10912 ast_frfree(f);
10913 if (ast_channel_state(chan) == AST_STATE_RING ||
10914 ast_channel_state(chan) == AST_STATE_RINGING)
10915 break;
10916 }
10917
10918
10919
10920 if (p->usedistinctiveringdetection) {
10921 len = 0;
10922 distMatches = 0;
10923
10924 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10925 curRingData[receivedRingT] = 0;
10926 receivedRingT = 0;
10927 counter = 0;
10928 counter1 = 0;
10929
10930 if (strcmp(p->context,p->defcontext) != 0) {
10931 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10932 ast_channel_context_set(chan, p->defcontext);
10933 }
10934
10935 for (;;) {
10936 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10937 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10938 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10939 callerid_free(cs);
10940 ast_hangup(chan);
10941 goto quit;
10942 }
10943 if (i & DAHDI_IOMUX_SIGEVENT) {
10944 res = dahdi_get_event(p->subs[idx].dfd);
10945 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10946 if (res == DAHDI_EVENT_NOALARM) {
10947 p->inalarm = 0;
10948 }
10949 res = 0;
10950
10951
10952 curRingData[receivedRingT] = p->ringt;
10953
10954 if (p->ringt < p->ringt_base/2)
10955 break;
10956
10957
10958 if (++receivedRingT == ARRAY_LEN(curRingData))
10959 break;
10960 } else if (i & DAHDI_IOMUX_READ) {
10961 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10962 if (res < 0) {
10963 if (errno != ELAST) {
10964 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10965 callerid_free(cs);
10966 ast_hangup(chan);
10967 goto quit;
10968 }
10969 break;
10970 }
10971 if (p->ringt > 0) {
10972 if (!(--p->ringt)) {
10973 res = -1;
10974 break;
10975 }
10976 }
10977 }
10978 }
10979
10980 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10981 for (counter = 0; counter < 3; counter++) {
10982
10983
10984 distMatches = 0;
10985 for (counter1 = 0; counter1 < 3; counter1++) {
10986 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10987 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10988 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10989 curRingData[counter1]);
10990 distMatches++;
10991 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10992 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10993 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10994 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10995 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10996 distMatches++;
10997 }
10998 }
10999
11000 if (distMatches == 3) {
11001
11002 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11003 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11004 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11005 break;
11006 }
11007 }
11008 }
11009
11010 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11011 #if 1
11012 restore_gains(p);
11013 #endif
11014 } else
11015 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11016 } else {
11017 ast_log(LOG_WARNING, "Channel %s in prering "
11018 "state, but I have nothing to do. "
11019 "Terminating simple switch, should be "
11020 "restarted by the actual ring.\n",
11021 ast_channel_name(chan));
11022 ast_hangup(chan);
11023 goto quit;
11024 }
11025 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
11026 if (p->cid_signalling == CID_SIG_DTMF) {
11027 int k = 0;
11028 int off_ms;
11029 struct timeval start;
11030 int ms;
11031 cs = NULL;
11032 dahdi_setlinear(p->subs[idx].dfd, 0);
11033 off_ms = 2000;
11034 start = ast_tvnow();
11035 for (;;) {
11036 struct ast_frame *f;
11037
11038 ms = ast_remaining_ms(start, off_ms);
11039 res = ast_waitfor(chan, ms);
11040 if (res <= 0) {
11041 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
11042 "Exiting simple switch\n");
11043 ast_hangup(chan);
11044 goto quit;
11045 }
11046 f = ast_read(chan);
11047 if (!f) {
11048
11049 ast_hangup(chan);
11050 goto quit;
11051 }
11052 if (f->frametype == AST_FRAME_DTMF) {
11053 dtmfbuf[k++] = f->subclass.integer;
11054 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
11055 start = ast_tvnow();
11056 }
11057 ast_frfree(f);
11058
11059 if (p->ringt_base == p->ringt)
11060 break;
11061 }
11062 dtmfbuf[k] = '\0';
11063 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11064
11065 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
11066 ast_debug(1, "CID is '%s', flags %d\n",
11067 dtmfcid, flags);
11068
11069 if (!ast_strlen_zero(dtmfcid))
11070 number = dtmfcid;
11071 else
11072 number = NULL;
11073
11074 } else {
11075
11076 cs = callerid_new(p->cid_signalling);
11077 if (cs) {
11078 #if 1
11079 bump_gains(p);
11080 #endif
11081 samples = 0;
11082 len = 0;
11083 distMatches = 0;
11084
11085 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
11086 curRingData[receivedRingT] = 0;
11087 receivedRingT = 0;
11088 counter = 0;
11089 counter1 = 0;
11090
11091 if (strcmp(p->context,p->defcontext) != 0) {
11092 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
11093 ast_channel_context_set(chan, p->defcontext);
11094 }
11095
11096
11097 dahdi_setlinear(p->subs[idx].dfd, 0);
11098 for (;;) {
11099 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11100 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11101 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11102 callerid_free(cs);
11103 ast_hangup(chan);
11104 goto quit;
11105 }
11106 if (i & DAHDI_IOMUX_SIGEVENT) {
11107 res = dahdi_get_event(p->subs[idx].dfd);
11108 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11109 if (res == DAHDI_EVENT_NOALARM) {
11110 p->inalarm = 0;
11111 }
11112
11113 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
11114 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
11115 p->polarity = POLARITY_IDLE;
11116 callerid_free(cs);
11117 ast_hangup(chan);
11118 goto quit;
11119 }
11120 res = 0;
11121
11122
11123 curRingData[receivedRingT] = p->ringt;
11124
11125 if (p->ringt < p->ringt_base/2)
11126 break;
11127
11128
11129 if (++receivedRingT == ARRAY_LEN(curRingData))
11130 break;
11131 } else if (i & DAHDI_IOMUX_READ) {
11132 res = read(p->subs[idx].dfd, buf, sizeof(buf));
11133 if (res < 0) {
11134 if (errno != ELAST) {
11135 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11136 callerid_free(cs);
11137 ast_hangup(chan);
11138 goto quit;
11139 }
11140 break;
11141 }
11142 if (p->ringt > 0) {
11143 if (!(--p->ringt)) {
11144 res = -1;
11145 break;
11146 }
11147 }
11148 samples += res;
11149 res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
11150 if (res < 0) {
11151
11152
11153
11154
11155 ast_log(LOG_WARNING,
11156 "Failed to decode CallerID on channel '%s'\n",
11157 ast_channel_name(chan));
11158 break;
11159 } else if (res)
11160 break;
11161 else if (samples > (8000 * 10))
11162 break;
11163 }
11164 }
11165 if (res == 1) {
11166 callerid_get(cs, &name, &number, &flags);
11167 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
11168 }
11169 if (distinctiveringaftercid == 1) {
11170
11171 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
11172 curRingData[receivedRingT] = 0;
11173 }
11174 receivedRingT = 0;
11175 ast_verb(3, "Detecting post-CID distinctive ring\n");
11176 for (;;) {
11177 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11178 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11179 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11180 callerid_free(cs);
11181 ast_hangup(chan);
11182 goto quit;
11183 }
11184 if (i & DAHDI_IOMUX_SIGEVENT) {
11185 res = dahdi_get_event(p->subs[idx].dfd);
11186 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11187 if (res == DAHDI_EVENT_NOALARM) {
11188 p->inalarm = 0;
11189 }
11190 res = 0;
11191
11192
11193 curRingData[receivedRingT] = p->ringt;
11194
11195 if (p->ringt < p->ringt_base/2)
11196 break;
11197
11198
11199 if (++receivedRingT == ARRAY_LEN(curRingData))
11200 break;
11201 } else if (i & DAHDI_IOMUX_READ) {
11202 res = read(p->subs[idx].dfd, buf, sizeof(buf));
11203 if (res < 0) {
11204 if (errno != ELAST) {
11205 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11206 callerid_free(cs);
11207 ast_hangup(chan);
11208 goto quit;
11209 }
11210 break;
11211 }
11212 if (p->ringt > 0) {
11213 if (!(--p->ringt)) {
11214 res = -1;
11215 break;
11216 }
11217 }
11218 }
11219 }
11220 }
11221 if (p->usedistinctiveringdetection) {
11222
11223 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11224
11225 for (counter = 0; counter < 3; counter++) {
11226
11227
11228
11229 ast_verb(3, "Checking %d,%d,%d\n",
11230 p->drings.ringnum[counter].ring[0],
11231 p->drings.ringnum[counter].ring[1],
11232 p->drings.ringnum[counter].ring[2]);
11233 distMatches = 0;
11234 for (counter1 = 0; counter1 < 3; counter1++) {
11235 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11236 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11237 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11238 curRingData[counter1]);
11239 distMatches++;
11240 }
11241 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11242 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11243 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11244 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11245 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11246 distMatches++;
11247 }
11248 }
11249 if (distMatches == 3) {
11250
11251 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11252 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11253 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11254 break;
11255 }
11256 }
11257 }
11258
11259 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11260 #if 1
11261 restore_gains(p);
11262 #endif
11263 if (res < 0) {
11264 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11265 }
11266 } else
11267 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11268 }
11269 } else
11270 cs = NULL;
11271
11272 if (number)
11273 ast_shrink_phone_number(number);
11274 ast_set_callerid(chan, number, name, number);
11275
11276 if (smdi_msg)
11277 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11278
11279 if (cs)
11280 callerid_free(cs);
11281
11282 my_handle_notify_message(chan, p, flags, -1);
11283
11284 ast_setstate(chan, AST_STATE_RING);
11285 ast_channel_rings_set(chan, 1);
11286 p->ringt = p->ringt_base;
11287 res = ast_pbx_run(chan);
11288 if (res) {
11289 ast_hangup(chan);
11290 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11291 }
11292 goto quit;
11293 default:
11294 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11295 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11296 if (res < 0)
11297 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11298 }
11299 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11300 if (res < 0)
11301 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11302 ast_hangup(chan);
11303 quit:
11304 ast_mutex_lock(&ss_thread_lock);
11305 ss_thread_count--;
11306 ast_cond_signal(&ss_thread_complete);
11307 ast_mutex_unlock(&ss_thread_lock);
11308 return NULL;
11309 }
11310
11311 struct mwi_thread_data {
11312 struct dahdi_pvt *pvt;
11313 unsigned char buf[READ_SIZE];
11314 size_t len;
11315 };
11316
11317 static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
11318 {
11319 int x;
11320 int sum = 0;
11321
11322 if (!len)
11323 return 0;
11324
11325 for (x = 0; x < len; x++)
11326 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11327
11328 return sum / len;
11329 }
11330
11331 static void *mwi_thread(void *data)
11332 {
11333 struct mwi_thread_data *mtd = data;
11334 struct callerid_state *cs;
11335 pthread_t threadid;
11336 int samples = 0;
11337 char *name, *number;
11338 int flags;
11339 int i, res;
11340 unsigned int spill_done = 0;
11341 int spill_result = -1;
11342 struct ast_format tmpfmt;
11343
11344 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11345 goto quit_no_clean;
11346 }
11347
11348 callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
11349
11350 bump_gains(mtd->pvt);
11351
11352 for (;;) {
11353 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11354 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11355 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11356 goto quit;
11357 }
11358
11359 if (i & DAHDI_IOMUX_SIGEVENT) {
11360 struct ast_channel *chan;
11361 struct ast_callid *callid = NULL;
11362 int callid_created;
11363
11364
11365
11366
11367 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11368
11369 switch (res) {
11370 case DAHDI_EVENT_NEONMWI_ACTIVE:
11371 case DAHDI_EVENT_NEONMWI_INACTIVE:
11372 case DAHDI_EVENT_NONE:
11373 case DAHDI_EVENT_BITSCHANGED:
11374 break;
11375 case DAHDI_EVENT_NOALARM:
11376 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11377 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11378
11379 analog_p->inalarm = 0;
11380 }
11381 mtd->pvt->inalarm = 0;
11382 handle_clear_alarms(mtd->pvt);
11383 break;
11384 case DAHDI_EVENT_ALARM:
11385 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11386 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11387
11388 analog_p->inalarm = 1;
11389 }
11390 mtd->pvt->inalarm = 1;
11391 res = get_alarms(mtd->pvt);
11392 handle_alarms(mtd->pvt, res);
11393 break;
11394 default:
11395 callid_created = ast_callid_threadstorage_auto(&callid);
11396 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11397 callerid_free(cs);
11398
11399 restore_gains(mtd->pvt);
11400 mtd->pvt->ringt = mtd->pvt->ringt_base;
11401
11402 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid))) {
11403 int result;
11404
11405 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11406 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11407 } else {
11408 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11409 }
11410 if (result) {
11411 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11412 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11413 if (res < 0)
11414 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11415 ast_hangup(chan);
11416 }
11417 } else {
11418 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11419 }
11420
11421 ast_callid_threadstorage_auto_clean(callid, callid_created);
11422 goto quit_no_clean;
11423 }
11424 } else if (i & DAHDI_IOMUX_READ) {
11425 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11426 if (errno != ELAST) {
11427 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11428 goto quit;
11429 }
11430 break;
11431 }
11432 samples += res;
11433 if (!spill_done) {
11434 if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
11435
11436
11437
11438
11439 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11440 break;
11441 } else if (spill_result) {
11442 spill_done = 1;
11443 }
11444 } else {
11445
11446
11447
11448 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11449 break;
11450 }
11451 if (samples > (8000 * 4))
11452 break;
11453 }
11454 }
11455
11456 if (spill_result == 1) {
11457 callerid_get(cs, &name, &number, &flags);
11458 if (flags & CID_MSGWAITING) {
11459 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11460 notify_message(mtd->pvt->mailbox, 1);
11461 } else if (flags & CID_NOMSGWAITING) {
11462 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11463 notify_message(mtd->pvt->mailbox, 0);
11464 } else {
11465 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11466 }
11467 }
11468
11469
11470 quit:
11471 callerid_free(cs);
11472
11473 restore_gains(mtd->pvt);
11474
11475 quit_no_clean:
11476 mtd->pvt->mwimonitoractive = 0;
11477 ast_free(mtd);
11478
11479 return NULL;
11480 }
11481
11482
11483
11484
11485
11486
11487
11488
11489 static int mwi_send_init(struct dahdi_pvt * pvt)
11490 {
11491 int x;
11492 struct ast_format tmpfmt;
11493
11494 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11495
11496 if (pvt->mwisend_rpas) {
11497 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11498 pvt->mwisendactive = 1;
11499 } else if (pvt->mwisend_fsk) {
11500 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11501 pvt->mwisendactive = 1;
11502 } else {
11503 pvt->mwisendactive = 0;
11504 return 0;
11505 }
11506 #else
11507 if (mwisend_rpas) {
11508 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11509 } else {
11510 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11511 }
11512 pvt->mwisendactive = 1;
11513 #endif
11514
11515 if (pvt->cidspill) {
11516 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11517 ast_free(pvt->cidspill);
11518 pvt->cidspill = NULL;
11519 pvt->cidpos = 0;
11520 pvt->cidlen = 0;
11521 }
11522 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11523 if (!pvt->cidspill) {
11524 pvt->mwisendactive = 0;
11525 return -1;
11526 }
11527 x = DAHDI_FLUSH_BOTH;
11528 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11529 x = 3000;
11530 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11531 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11532 if (pvt->mwisend_fsk) {
11533 #endif
11534 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11535 ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11536 pvt->cidpos = 0;
11537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11538 }
11539 #endif
11540 return 0;
11541 }
11542
11543 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11544 {
11545 struct timeval now;
11546 int res;
11547
11548
11549
11550
11551 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11552 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11553 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11554
11555 switch ( pvt->mwisend_data.mwisend_current) {
11556 case MWI_SEND_SA:
11557
11558 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11559 if (res) {
11560 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11561 goto quit;
11562 }
11563 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11564 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11565 break;
11566 case MWI_SEND_SA_WAIT:
11567 break;
11568 case MWI_SEND_PAUSE:
11569 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11570 if (pvt->mwisend_fsk) {
11571 #endif
11572 gettimeofday(&now, NULL);
11573 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11574 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11575 }
11576 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11577 } else {
11578 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11579 }
11580 #endif
11581 break;
11582 case MWI_SEND_SPILL:
11583
11584 if(0 < num_read) {
11585 if (num_read > pvt->cidlen - pvt->cidpos)
11586 num_read = pvt->cidlen - pvt->cidpos;
11587 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11588 if (res > 0) {
11589 pvt->cidpos += res;
11590 if (pvt->cidpos >= pvt->cidlen) {
11591 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11592 }
11593 } else {
11594 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11595 goto quit;
11596 }
11597 }
11598 break;
11599 case MWI_SEND_CLEANUP:
11600
11601 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11602 break;
11603 default:
11604
11605 goto quit;
11606 }
11607 }
11608
11609 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11610 if (pvt->cidspill) {
11611 ast_free(pvt->cidspill);
11612 pvt->cidspill = NULL;
11613 pvt->cidpos = 0;
11614 pvt->cidlen = 0;
11615 }
11616 pvt->mwisendactive = 0;
11617 }
11618 return 0;
11619 quit:
11620 if (pvt->cidspill) {
11621 ast_free(pvt->cidspill);
11622 pvt->cidspill = NULL;
11623 pvt->cidpos = 0;
11624 pvt->cidlen = 0;
11625 }
11626 pvt->mwisendactive = 0;
11627 return -1;
11628 }
11629
11630 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11631 {
11632 int handled = 0;
11633
11634 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11635 switch (event) {
11636 case DAHDI_EVENT_RINGEROFF:
11637 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11638 handled = 1;
11639
11640 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11641 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11642 ast_free(pvt->cidspill);
11643 pvt->cidspill = NULL;
11644 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11645 pvt->mwisendactive = 0;
11646 } else {
11647 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11648 gettimeofday(&pvt->mwisend_data.pause, NULL);
11649 }
11650 }
11651 break;
11652
11653 case DAHDI_EVENT_RINGOFFHOOK:
11654 if (pvt->cidspill) {
11655 ast_free(pvt->cidspill);
11656 pvt->cidspill = NULL;
11657 pvt->cidpos = 0;
11658 pvt->cidlen = 0;
11659 }
11660 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11661 pvt->mwisendactive = 0;
11662 break;
11663 case DAHDI_EVENT_RINGERON:
11664 case DAHDI_EVENT_HOOKCOMPLETE:
11665 break;
11666 default:
11667 break;
11668 }
11669 }
11670 return handled;
11671 }
11672
11673
11674 static int dahdi_destroy_channel_bynum(int channel)
11675 {
11676 struct dahdi_pvt *cur;
11677
11678 ast_mutex_lock(&iflock);
11679 for (cur = iflist; cur; cur = cur->next) {
11680 if (cur->channel == channel) {
11681 int x = DAHDI_FLASH;
11682
11683
11684 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11685
11686 destroy_channel(cur, 1);
11687 ast_mutex_unlock(&iflock);
11688 ast_module_unref(ast_module_info->self);
11689 return RESULT_SUCCESS;
11690 }
11691 }
11692 ast_mutex_unlock(&iflock);
11693 return RESULT_FAILURE;
11694 }
11695
11696 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11697 {
11698 int res;
11699 pthread_t threadid;
11700 struct ast_channel *chan;
11701 struct ast_callid *callid = NULL;
11702 int callid_created;
11703
11704
11705
11706 switch (event) {
11707 case DAHDI_EVENT_NONE:
11708 case DAHDI_EVENT_BITSCHANGED:
11709 break;
11710 case DAHDI_EVENT_WINKFLASH:
11711 case DAHDI_EVENT_RINGOFFHOOK:
11712 if (i->inalarm) break;
11713 if (i->radio) break;
11714
11715 switch (i->sig) {
11716 case SIG_FXOLS:
11717 case SIG_FXOGS:
11718 case SIG_FXOKS:
11719 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11720 if (res && (errno == EBUSY)) {
11721 break;
11722 }
11723
11724 callid_created = ast_callid_threadstorage_auto(&callid);
11725
11726
11727 ast_free(i->cidspill);
11728 i->cidspill = NULL;
11729 restore_conference(i);
11730
11731 if (i->immediate) {
11732 dahdi_enable_ec(i);
11733
11734 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11735 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, callid);
11736 if (!chan) {
11737 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11738 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11739 if (res < 0)
11740 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11741 }
11742 } else {
11743
11744 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, callid);
11745 if (chan) {
11746 if (has_voicemail(i))
11747 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11748 else
11749 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11750 if (res < 0)
11751 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11752 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11753 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11754 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11755 if (res < 0)
11756 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11757 ast_hangup(chan);
11758 }
11759 } else
11760 ast_log(LOG_WARNING, "Unable to create channel\n");
11761 }
11762
11763 ast_callid_threadstorage_auto_clean(callid, callid_created);
11764 break;
11765 case SIG_FXSLS:
11766 case SIG_FXSGS:
11767 case SIG_FXSKS:
11768 i->ringt = i->ringt_base;
11769
11770 case SIG_EMWINK:
11771 case SIG_FEATD:
11772 case SIG_FEATDMF:
11773 case SIG_FEATDMF_TA:
11774 case SIG_E911:
11775 case SIG_FGC_CAMA:
11776 case SIG_FGC_CAMAMF:
11777 case SIG_FEATB:
11778 case SIG_EM:
11779 case SIG_EM_E1:
11780 case SIG_SFWINK:
11781 case SIG_SF_FEATD:
11782 case SIG_SF_FEATDMF:
11783 case SIG_SF_FEATB:
11784 case SIG_SF:
11785
11786 callid_created = ast_callid_threadstorage_auto(&callid);
11787 if (i->cid_start == CID_START_POLARITY_IN) {
11788 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11789 } else {
11790 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid);
11791 }
11792
11793 if (!chan) {
11794 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11795 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11796 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11797 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11798 if (res < 0) {
11799 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11800 }
11801 ast_hangup(chan);
11802 }
11803
11804 ast_callid_threadstorage_auto_clean(callid, callid_created);
11805 break;
11806 default:
11807 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11808 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11809 if (res < 0)
11810 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11811 return NULL;
11812 }
11813 break;
11814 case DAHDI_EVENT_NOALARM:
11815 switch (i->sig) {
11816 #if defined(HAVE_PRI)
11817 case SIG_PRI_LIB_HANDLE_CASES:
11818 ast_mutex_lock(&i->lock);
11819 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11820 ast_mutex_unlock(&i->lock);
11821 break;
11822 #endif
11823 #if defined(HAVE_SS7)
11824 case SIG_SS7:
11825 sig_ss7_set_alarm(i->sig_pvt, 0);
11826 break;
11827 #endif
11828 default:
11829 i->inalarm = 0;
11830 break;
11831 }
11832 handle_clear_alarms(i);
11833 break;
11834 case DAHDI_EVENT_ALARM:
11835 switch (i->sig) {
11836 #if defined(HAVE_PRI)
11837 case SIG_PRI_LIB_HANDLE_CASES:
11838 ast_mutex_lock(&i->lock);
11839 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11840 ast_mutex_unlock(&i->lock);
11841 break;
11842 #endif
11843 #if defined(HAVE_SS7)
11844 case SIG_SS7:
11845 sig_ss7_set_alarm(i->sig_pvt, 1);
11846 break;
11847 #endif
11848 default:
11849 i->inalarm = 1;
11850 break;
11851 }
11852 res = get_alarms(i);
11853 handle_alarms(i, res);
11854
11855 case DAHDI_EVENT_ONHOOK:
11856 if (i->radio)
11857 break;
11858
11859 switch (i->sig) {
11860 case SIG_FXOLS:
11861 case SIG_FXOGS:
11862 case SIG_FEATD:
11863 case SIG_FEATDMF:
11864 case SIG_FEATDMF_TA:
11865 case SIG_E911:
11866 case SIG_FGC_CAMA:
11867 case SIG_FGC_CAMAMF:
11868 case SIG_FEATB:
11869 case SIG_EM:
11870 case SIG_EM_E1:
11871 case SIG_EMWINK:
11872 case SIG_SF_FEATD:
11873 case SIG_SF_FEATDMF:
11874 case SIG_SF_FEATB:
11875 case SIG_SF:
11876 case SIG_SFWINK:
11877 case SIG_FXSLS:
11878 case SIG_FXSGS:
11879 case SIG_FXSKS:
11880 case SIG_FXOKS:
11881 dahdi_disable_ec(i);
11882
11883 #ifdef ZHONE_HACK
11884 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11885 usleep(1);
11886 #endif
11887 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11888 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11889 break;
11890 case SIG_SS7:
11891 case SIG_PRI_LIB_HANDLE_CASES:
11892 dahdi_disable_ec(i);
11893 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11894 break;
11895 default:
11896 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11897 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11898 return NULL;
11899 }
11900 break;
11901 case DAHDI_EVENT_POLARITY:
11902 switch (i->sig) {
11903 case SIG_FXSLS:
11904 case SIG_FXSKS:
11905 case SIG_FXSGS:
11906
11907
11908
11909
11910 callid_created = ast_callid_threadstorage_auto(&callid);
11911 if (i->hanguponpolarityswitch)
11912 i->polarity = POLARITY_REV;
11913 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11914 i->polarity = POLARITY_REV;
11915 ast_verb(2, "Starting post polarity "
11916 "CID detection on channel %d\n",
11917 i->channel);
11918 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11919 if (!chan) {
11920 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11921 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11922 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11923 ast_hangup(chan);
11924 }
11925 }
11926 ast_callid_threadstorage_auto_clean(callid, callid_created);
11927 break;
11928 default:
11929 ast_log(LOG_WARNING, "handle_init_event detected "
11930 "polarity reversal on non-FXO (SIG_FXS) "
11931 "interface %d\n", i->channel);
11932 }
11933 break;
11934 case DAHDI_EVENT_REMOVED:
11935 ast_log(LOG_NOTICE,
11936 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11937 i->channel);
11938 return i;
11939 case DAHDI_EVENT_NEONMWI_ACTIVE:
11940 if (i->mwimonitor_neon) {
11941 notify_message(i->mailbox, 1);
11942 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11943 }
11944 break;
11945 case DAHDI_EVENT_NEONMWI_INACTIVE:
11946 if (i->mwimonitor_neon) {
11947 notify_message(i->mailbox, 0);
11948 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11949 }
11950 break;
11951 }
11952 return NULL;
11953 }
11954
11955 static void monitor_pfds_clean(void *arg) {
11956 struct pollfd **pfds = arg;
11957 ast_free(*pfds);
11958 }
11959
11960 static void *do_monitor(void *data)
11961 {
11962 int count, res, res2, spoint, pollres=0;
11963 struct dahdi_pvt *i;
11964 struct dahdi_pvt *last = NULL;
11965 struct dahdi_pvt *doomed;
11966 time_t thispass = 0, lastpass = 0;
11967 int found;
11968 char buf[1024];
11969 struct pollfd *pfds=NULL;
11970 int lastalloc = -1;
11971
11972
11973
11974 #if 0
11975 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11976 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11977 return NULL;
11978 }
11979 ast_debug(1, "Monitor starting...\n");
11980 #endif
11981 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11982
11983 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11984 for (;;) {
11985
11986 ast_mutex_lock(&iflock);
11987 if (!pfds || (lastalloc != ifcount)) {
11988 if (pfds) {
11989 ast_free(pfds);
11990 pfds = NULL;
11991 }
11992 if (ifcount) {
11993 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11994 ast_mutex_unlock(&iflock);
11995 return NULL;
11996 }
11997 }
11998 lastalloc = ifcount;
11999 }
12000
12001
12002 count = 0;
12003 for (i = iflist; i; i = i->next) {
12004 ast_mutex_lock(&i->lock);
12005 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
12006 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12007 struct analog_pvt *p = i->sig_pvt;
12008
12009 if (!p) {
12010 ast_log(LOG_ERROR, "No sig_pvt?\n");
12011 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
12012
12013 pfds[count].fd = i->subs[SUB_REAL].dfd;
12014 pfds[count].events = POLLPRI;
12015 pfds[count].revents = 0;
12016
12017 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12018 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12019 pfds[count].events |= POLLIN;
12020 }
12021 count++;
12022 }
12023 } else {
12024 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
12025
12026 pfds[count].fd = i->subs[SUB_REAL].dfd;
12027 pfds[count].events = POLLPRI;
12028 pfds[count].revents = 0;
12029
12030
12031 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12032 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12033 pfds[count].events |= POLLIN;
12034 }
12035 count++;
12036 }
12037 }
12038 }
12039 ast_mutex_unlock(&i->lock);
12040 }
12041
12042 ast_mutex_unlock(&iflock);
12043
12044 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12045 pthread_testcancel();
12046
12047 res = poll(pfds, count, 1000);
12048 pthread_testcancel();
12049 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12050
12051
12052 if (res < 0) {
12053 if ((errno != EAGAIN) && (errno != EINTR))
12054 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
12055 continue;
12056 }
12057
12058
12059 ast_mutex_lock(&iflock);
12060 found = 0;
12061 spoint = 0;
12062 lastpass = thispass;
12063 thispass = time(NULL);
12064 doomed = NULL;
12065 for (i = iflist;; i = i->next) {
12066 if (doomed) {
12067 int res;
12068 res = dahdi_destroy_channel_bynum(doomed->channel);
12069 if (res != RESULT_SUCCESS) {
12070 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
12071 }
12072 doomed = NULL;
12073 }
12074 if (!i) {
12075 break;
12076 }
12077
12078 if (thispass != lastpass) {
12079 if (!found && ((i == last) || ((i == iflist) && !last))) {
12080 last = i;
12081 if (last) {
12082 struct analog_pvt *analog_p = last->sig_pvt;
12083
12084 if (analog_p
12085 && !last->mwisendactive
12086 && (last->sig & __DAHDI_SIG_FXO)
12087 && !analog_p->fxsoffhookstate
12088 && !last->owner
12089 && !ast_strlen_zero(last->mailbox)
12090 && (thispass - analog_p->onhooktime > 3)) {
12091 res = has_voicemail(last);
12092 if (analog_p->msgstate != res) {
12093
12094 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
12095 if (res2) {
12096
12097 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
12098 }
12099
12100 if (mwi_send_init(last)) {
12101 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
12102 }
12103 analog_p->msgstate = res;
12104 found ++;
12105 }
12106 }
12107 last = last->next;
12108 }
12109 }
12110 }
12111 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12112 if (i->radio && !i->owner)
12113 {
12114 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12115 if (res)
12116 {
12117 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12118
12119 ast_mutex_unlock(&iflock);
12120 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12121 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12122 else
12123 doomed = handle_init_event(i, res);
12124 ast_mutex_lock(&iflock);
12125 }
12126 continue;
12127 }
12128 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12129 if (pollres & POLLIN) {
12130 if (i->owner || i->subs[SUB_REAL].owner) {
12131 #ifdef HAVE_PRI
12132 if (!i->pri)
12133 #endif
12134 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12135 continue;
12136 }
12137 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
12138 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12139 continue;
12140 }
12141 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12142 if (res > 0) {
12143 if (i->mwimonitor_fsk) {
12144 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12145 pthread_attr_t attr;
12146 pthread_t threadid;
12147 struct mwi_thread_data *mtd;
12148
12149 pthread_attr_init(&attr);
12150 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12151
12152 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12153 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12154 mtd->pvt = i;
12155 memcpy(mtd->buf, buf, res);
12156 mtd->len = res;
12157 i->mwimonitoractive = 1;
12158 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12159 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12160 i->mwimonitoractive = 0;
12161 ast_free(mtd);
12162 }
12163 }
12164 }
12165
12166 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12167 int energy;
12168 struct timeval now;
12169
12170
12171
12172 if (1 == i->dtmfcid_holdoff_state) {
12173 gettimeofday(&i->dtmfcid_delay, NULL);
12174 i->dtmfcid_holdoff_state = 2;
12175 } else if (2 == i->dtmfcid_holdoff_state) {
12176 gettimeofday(&now, NULL);
12177 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12178 i->dtmfcid_holdoff_state = 0;
12179 }
12180 } else {
12181 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12182 if (!i->mwisendactive && energy > dtmfcid_level) {
12183 pthread_t threadid;
12184 struct ast_channel *chan;
12185 ast_mutex_unlock(&iflock);
12186 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12187
12188 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
12189 i->dtmfcid_holdoff_state = 1;
12190 } else {
12191 struct ast_callid *callid = NULL;
12192 int callid_created = ast_callid_threadstorage_auto(&callid);
12193 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
12194 if (!chan) {
12195 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12196 } else {
12197 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12198 if (res) {
12199 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12200 ast_hangup(chan);
12201 } else {
12202 i->dtmfcid_holdoff_state = 1;
12203 }
12204 }
12205 ast_callid_threadstorage_auto_clean(callid, callid_created);
12206 }
12207 ast_mutex_lock(&iflock);
12208 }
12209 }
12210 }
12211 if (i->mwisendactive) {
12212 mwi_send_process_buffer(i, res);
12213 }
12214 } else {
12215 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12216 }
12217 }
12218 if (pollres & POLLPRI) {
12219 if (i->owner || i->subs[SUB_REAL].owner) {
12220 #ifdef HAVE_PRI
12221 if (!i->pri)
12222 #endif
12223 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12224 continue;
12225 }
12226 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12227 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12228
12229 ast_mutex_unlock(&iflock);
12230 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12231 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12232 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12233 else
12234 doomed = handle_init_event(i, res);
12235 }
12236 ast_mutex_lock(&iflock);
12237 }
12238 }
12239 }
12240 ast_mutex_unlock(&iflock);
12241 }
12242
12243 pthread_cleanup_pop(1);
12244 return NULL;
12245
12246 }
12247
12248 static int restart_monitor(void)
12249 {
12250
12251 if (monitor_thread == AST_PTHREADT_STOP)
12252 return 0;
12253 ast_mutex_lock(&monlock);
12254 if (monitor_thread == pthread_self()) {
12255 ast_mutex_unlock(&monlock);
12256 ast_log(LOG_WARNING, "Cannot kill myself\n");
12257 return -1;
12258 }
12259 if (monitor_thread != AST_PTHREADT_NULL) {
12260
12261 pthread_kill(monitor_thread, SIGURG);
12262 } else {
12263
12264 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12265 ast_mutex_unlock(&monlock);
12266 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12267 return -1;
12268 }
12269 }
12270 ast_mutex_unlock(&monlock);
12271 return 0;
12272 }
12273
12274 #if defined(HAVE_PRI)
12275 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12276 {
12277 int x;
12278 int trunkgroup;
12279
12280 trunkgroup = pris[*span].mastertrunkgroup;
12281 if (trunkgroup) {
12282
12283 for (x = 0; x < NUM_SPANS; x++) {
12284 if (pris[x].pri.trunkgroup == trunkgroup) {
12285 *span = x;
12286 return 0;
12287 }
12288 }
12289 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12290 *span = -1;
12291 } else {
12292 if (pris[*span].pri.trunkgroup) {
12293 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);
12294 *span = -1;
12295 } else if (pris[*span].mastertrunkgroup) {
12296 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12297 *span = -1;
12298 } else {
12299 if (si->totalchans == 31) {
12300
12301 pris[*span].dchannels[0] = 16 + offset;
12302 } else if (si->totalchans == 24) {
12303
12304 pris[*span].dchannels[0] = 24 + offset;
12305 } else if (si->totalchans == 3) {
12306
12307 pris[*span].dchannels[0] = 3 + offset;
12308 } else {
12309 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);
12310 *span = -1;
12311 return 0;
12312 }
12313 pris[*span].pri.span = *span + 1;
12314 }
12315 }
12316 return 0;
12317 }
12318 #endif
12319
12320 #if defined(HAVE_PRI)
12321 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12322 {
12323 struct dahdi_spaninfo si;
12324 struct dahdi_params p;
12325 int fd;
12326 int span;
12327 int ospan=0;
12328 int x,y;
12329 for (x = 0; x < NUM_SPANS; x++) {
12330 if (pris[x].pri.trunkgroup == trunkgroup) {
12331 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12332 return -1;
12333 }
12334 }
12335 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12336 if (!channels[y])
12337 break;
12338 memset(&si, 0, sizeof(si));
12339 memset(&p, 0, sizeof(p));
12340 fd = open("/dev/dahdi/channel", O_RDWR);
12341 if (fd < 0) {
12342 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12343 return -1;
12344 }
12345 x = channels[y];
12346 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12347 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12348 close(fd);
12349 return -1;
12350 }
12351 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12352 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12353 close(fd);
12354 return -1;
12355 }
12356 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12357 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12358 close(fd);
12359 return -1;
12360 }
12361 span = p.spanno - 1;
12362 if (pris[span].pri.trunkgroup) {
12363 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12364 close(fd);
12365 return -1;
12366 }
12367 if (pris[span].pri.pvts[0]) {
12368 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12369 close(fd);
12370 return -1;
12371 }
12372 if (!y) {
12373 pris[span].pri.trunkgroup = trunkgroup;
12374 ospan = span;
12375 }
12376 pris[ospan].dchannels[y] = channels[y];
12377 pris[span].pri.span = span + 1;
12378 close(fd);
12379 }
12380 return 0;
12381 }
12382 #endif
12383
12384 #if defined(HAVE_PRI)
12385 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12386 {
12387 if (pris[span].mastertrunkgroup) {
12388 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);
12389 return -1;
12390 }
12391 pris[span].mastertrunkgroup = trunkgroup;
12392 pris[span].prilogicalspan = logicalspan;
12393 return 0;
12394 }
12395 #endif
12396
12397 #if defined(HAVE_SS7)
12398 static unsigned int parse_pointcode(const char *pcstring)
12399 {
12400 unsigned int code1, code2, code3;
12401 int numvals;
12402
12403 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12404 if (numvals == 1)
12405 return code1;
12406 if (numvals == 3)
12407 return (code1 << 16) | (code2 << 8) | code3;
12408
12409 return 0;
12410 }
12411 #endif
12412
12413 #if defined(HAVE_SS7)
12414 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12415 {
12416 if ((linkset < 0) || (linkset >= NUM_SPANS))
12417 return NULL;
12418 else
12419 return &linksets[linkset - 1];
12420 }
12421 #endif
12422
12423 #ifdef HAVE_OPENR2
12424 static void dahdi_r2_destroy_links(void)
12425 {
12426 int i = 0;
12427 if (!r2links) {
12428 return;
12429 }
12430 for (; i < r2links_count; i++) {
12431 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12432 pthread_cancel(r2links[i]->r2master);
12433 pthread_join(r2links[i]->r2master, NULL);
12434 openr2_context_delete(r2links[i]->protocol_context);
12435 }
12436 ast_free(r2links[i]);
12437 }
12438 ast_free(r2links);
12439 r2links = NULL;
12440 r2links_count = 0;
12441 }
12442
12443
12444 #define R2_LINK_CAPACITY 30
12445 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12446 {
12447 struct dahdi_mfcr2 *new_r2link = NULL;
12448 struct dahdi_mfcr2 **new_r2links = NULL;
12449
12450
12451
12452
12453
12454 if (!r2links_count ||
12455 memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12456 (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12457 new_r2link = ast_calloc(1, sizeof(**r2links));
12458 if (!new_r2link) {
12459 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12460 return NULL;
12461 }
12462 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12463 if (!new_r2links) {
12464 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12465 ast_free(new_r2link);
12466 return NULL;
12467 }
12468 r2links = new_r2links;
12469 new_r2link->r2master = AST_PTHREADT_NULL;
12470 r2links[r2links_count] = new_r2link;
12471 r2links_count++;
12472 ast_debug(1, "Created new R2 link!\n");
12473 }
12474 return r2links[r2links_count - 1];
12475 }
12476
12477 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12478 {
12479 char tmplogdir[] = "/tmp";
12480 char logdir[OR2_MAX_PATH];
12481 int threshold = 0;
12482 int snres = 0;
12483 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12484 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12485 conf->mfcr2.max_dnis);
12486 if (!r2_link->protocol_context) {
12487 return -1;
12488 }
12489 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12490 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12491 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12492 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12493 #endif
12494 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12495 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12496 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12497 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12498 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12499 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12500 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12501 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12502 #endif
12503 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12504 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12505 #endif
12506 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12507 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12508 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12509 }
12510 } else {
12511 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12512 if (snres >= sizeof(logdir)) {
12513 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12514 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12515 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12516 }
12517 } else {
12518 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12519 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12520 }
12521 }
12522 }
12523 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12524 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12525 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12526 }
12527 }
12528
12529 memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12530 return 0;
12531 }
12532 #endif
12533
12534
12535
12536
12537
12538
12539 static int sigtype_to_signalling(int sigtype)
12540 {
12541 return sigtype;
12542 }
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12557 {
12558 struct stat stbuf;
12559 int num;
12560
12561 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12562 if (stat(path, &stbuf) < 0) {
12563 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12564 return -errno;
12565 }
12566 if (!S_ISCHR(stbuf.st_mode)) {
12567 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12568 return -EINVAL;
12569 }
12570 num = minor(stbuf.st_rdev);
12571 ast_debug(1, "%s -> %d\n", path, num);
12572 return num;
12573
12574 }
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589
12590 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12591 {
12592
12593 struct dahdi_pvt *tmp;
12594 char fn[80];
12595 struct dahdi_bufferinfo bi;
12596
12597 int res;
12598 #if defined(HAVE_PRI)
12599 int span = 0;
12600 #endif
12601 int here = 0;
12602 int x;
12603 struct analog_pvt *analog_p = NULL;
12604 struct dahdi_params p;
12605 #if defined(HAVE_PRI)
12606 struct dahdi_spaninfo si;
12607 struct sig_pri_chan *pri_chan = NULL;
12608 #endif
12609 #if defined(HAVE_SS7)
12610 struct sig_ss7_chan *ss7_chan = NULL;
12611 #endif
12612
12613
12614 for (tmp = iflist; tmp; tmp = tmp->next) {
12615 if (!tmp->destroy) {
12616 if (tmp->channel == channel) {
12617
12618 here = 1;
12619 break;
12620 }
12621 if (tmp->channel > channel) {
12622
12623 tmp = NULL;
12624 break;
12625 }
12626 }
12627 }
12628
12629 if (!here && reloading != 1) {
12630 tmp = ast_calloc(1, sizeof(*tmp));
12631 if (!tmp) {
12632 return NULL;
12633 }
12634 tmp->cc_params = ast_cc_config_params_init();
12635 if (!tmp->cc_params) {
12636 ast_free(tmp);
12637 return NULL;
12638 }
12639 ast_mutex_init(&tmp->lock);
12640 ifcount++;
12641 for (x = 0; x < 3; x++)
12642 tmp->subs[x].dfd = -1;
12643 tmp->channel = channel;
12644 tmp->priindication_oob = conf->chan.priindication_oob;
12645 }
12646
12647 if (tmp) {
12648 int chan_sig = conf->chan.sig;
12649
12650
12651 if (reloading && tmp->vars) {
12652 ast_variables_destroy(tmp->vars);
12653 tmp->vars = NULL;
12654 }
12655
12656 if (!here) {
12657
12658 if ((channel != CHAN_PSEUDO)) {
12659 int count = 0;
12660
12661 snprintf(fn, sizeof(fn), "%d", channel);
12662
12663 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12664 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12665 usleep(1);
12666 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12667 count++;
12668 }
12669
12670 if (tmp->subs[SUB_REAL].dfd < 0) {
12671 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);
12672 destroy_dahdi_pvt(tmp);
12673 return NULL;
12674 }
12675 memset(&p, 0, sizeof(p));
12676 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12677 if (res < 0) {
12678 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12679 destroy_dahdi_pvt(tmp);
12680 return NULL;
12681 }
12682 if (conf->is_sig_auto)
12683 chan_sig = sigtype_to_signalling(p.sigtype);
12684 if (p.sigtype != (chan_sig & 0x3ffff)) {
12685 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));
12686 destroy_dahdi_pvt(tmp);
12687 return NULL;
12688 }
12689 tmp->law_default = p.curlaw;
12690 tmp->law = p.curlaw;
12691 tmp->span = p.spanno;
12692 #if defined(HAVE_PRI)
12693 span = p.spanno - 1;
12694 #endif
12695 } else {
12696 chan_sig = 0;
12697 }
12698 tmp->sig = chan_sig;
12699 tmp->outsigmod = conf->chan.outsigmod;
12700
12701 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12702 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12703 if (!analog_p) {
12704 destroy_dahdi_pvt(tmp);
12705 return NULL;
12706 }
12707 tmp->sig_pvt = analog_p;
12708 }
12709 #if defined(HAVE_SS7)
12710 if (chan_sig == SIG_SS7) {
12711 struct dahdi_ss7 *ss7;
12712 int clear = 0;
12713
12714 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12715 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12716 destroy_dahdi_pvt(tmp);
12717 return NULL;
12718 }
12719
12720 ss7 = ss7_resolve_linkset(cur_linkset);
12721 if (!ss7) {
12722 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12723 destroy_dahdi_pvt(tmp);
12724 return NULL;
12725 }
12726 ss7->ss7.span = cur_linkset;
12727 if (cur_cicbeginswith < 0) {
12728 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12729 destroy_dahdi_pvt(tmp);
12730 return NULL;
12731 }
12732 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12733 if (!ss7_chan) {
12734 destroy_dahdi_pvt(tmp);
12735 return NULL;
12736 }
12737 tmp->sig_pvt = ss7_chan;
12738 tmp->ss7 = &ss7->ss7;
12739
12740 ss7_chan->channel = tmp->channel;
12741 ss7_chan->cic = cur_cicbeginswith++;
12742
12743
12744 ss7_chan->dpc = cur_defaultdpc;
12745
12746 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12747
12748 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12749 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12750 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12751 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12752
12753 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12754 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12755 }
12756 #endif
12757 #ifdef HAVE_OPENR2
12758 if (chan_sig == SIG_MFCR2) {
12759 struct dahdi_mfcr2 *r2_link;
12760 r2_link = dahdi_r2_get_link(conf);
12761 if (!r2_link) {
12762 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12763 destroy_dahdi_pvt(tmp);
12764 return NULL;
12765 }
12766 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12767 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12768 destroy_dahdi_pvt(tmp);
12769 return NULL;
12770 }
12771 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12772 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12773 destroy_dahdi_pvt(tmp);
12774 return NULL;
12775 }
12776 r2_link->pvts[r2_link->numchans++] = tmp;
12777 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12778 tmp->subs[SUB_REAL].dfd,
12779 NULL, NULL);
12780 if (!tmp->r2chan) {
12781 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12782 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12783 destroy_dahdi_pvt(tmp);
12784 return NULL;
12785 }
12786 tmp->mfcr2 = r2_link;
12787 if (conf->mfcr2.call_files) {
12788 openr2_chan_enable_call_files(tmp->r2chan);
12789 }
12790 openr2_chan_set_client_data(tmp->r2chan, tmp);
12791
12792 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12793 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12794 tmp->mfcr2_category = conf->mfcr2.category;
12795 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12796 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12797 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12798 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12799 tmp->mfcr2call = 0;
12800 tmp->mfcr2_dnis_index = 0;
12801 tmp->mfcr2_ani_index = 0;
12802 }
12803 #endif
12804 #ifdef HAVE_PRI
12805 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12806 int offset;
12807 int matchesdchan;
12808 int x,y;
12809 int myswitchtype = 0;
12810
12811 offset = 0;
12812 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12813 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12814 destroy_dahdi_pvt(tmp);
12815 return NULL;
12816 }
12817 if (span >= NUM_SPANS) {
12818 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12819 destroy_dahdi_pvt(tmp);
12820 return NULL;
12821 } else {
12822 si.spanno = 0;
12823 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12824 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12825 destroy_dahdi_pvt(tmp);
12826 return NULL;
12827 }
12828
12829 tmp->logicalspan = pris[span].prilogicalspan;
12830 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12831 if (span < 0) {
12832 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12833 destroy_dahdi_pvt(tmp);
12834 return NULL;
12835 }
12836 myswitchtype = conf->pri.pri.switchtype;
12837
12838 matchesdchan=0;
12839 for (x = 0; x < NUM_SPANS; x++) {
12840 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12841 if (pris[x].dchannels[y] == tmp->channel) {
12842 matchesdchan = 1;
12843 break;
12844 }
12845 }
12846 }
12847 if (!matchesdchan) {
12848 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12849 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12850 destroy_dahdi_pvt(tmp);
12851 return NULL;
12852 }
12853 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12854 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12855 destroy_dahdi_pvt(tmp);
12856 return NULL;
12857 }
12858 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12859 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));
12860 destroy_dahdi_pvt(tmp);
12861 return NULL;
12862 }
12863 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12864 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12865 destroy_dahdi_pvt(tmp);
12866 return NULL;
12867 }
12868 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12869 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12870 destroy_dahdi_pvt(tmp);
12871 return NULL;
12872 }
12873 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12874 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12875 destroy_dahdi_pvt(tmp);
12876 return NULL;
12877 }
12878 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12879 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12880 destroy_dahdi_pvt(tmp);
12881 return NULL;
12882 }
12883 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12884 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12885 pris[span].pri.trunkgroup);
12886 destroy_dahdi_pvt(tmp);
12887 return NULL;
12888 }
12889
12890 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12891 if (!pri_chan) {
12892 destroy_dahdi_pvt(tmp);
12893 return NULL;
12894 }
12895 tmp->sig_pvt = pri_chan;
12896 tmp->pri = &pris[span].pri;
12897
12898 tmp->priexclusive = conf->chan.priexclusive;
12899
12900 if (!tmp->pri->cc_params) {
12901 tmp->pri->cc_params = ast_cc_config_params_init();
12902 if (!tmp->pri->cc_params) {
12903 destroy_dahdi_pvt(tmp);
12904 return NULL;
12905 }
12906 }
12907 ast_cc_copy_config_params(tmp->pri->cc_params,
12908 conf->chan.cc_params);
12909
12910 pris[span].pri.sig = chan_sig;
12911 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12912 pris[span].pri.switchtype = myswitchtype;
12913 pris[span].pri.nsf = conf->pri.pri.nsf;
12914 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12915 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12916 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12917 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12918 pris[span].pri.minunused = conf->pri.pri.minunused;
12919 pris[span].pri.minidle = conf->pri.pri.minidle;
12920 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12921 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12922 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12923 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12924 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12925 #endif
12926 #ifdef HAVE_PRI_INBANDDISCONNECT
12927 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12928 #endif
12929 #if defined(HAVE_PRI_CALL_HOLD)
12930 pris[span].pri.hold_disconnect_transfer =
12931 conf->pri.pri.hold_disconnect_transfer;
12932 #endif
12933 #if defined(HAVE_PRI_CCSS)
12934 pris[span].pri.cc_ptmp_recall_mode =
12935 conf->pri.pri.cc_ptmp_recall_mode;
12936 pris[span].pri.cc_qsig_signaling_link_req =
12937 conf->pri.pri.cc_qsig_signaling_link_req;
12938 pris[span].pri.cc_qsig_signaling_link_rsp =
12939 conf->pri.pri.cc_qsig_signaling_link_rsp;
12940 #endif
12941 #if defined(HAVE_PRI_CALL_WAITING)
12942 pris[span].pri.max_call_waiting_calls =
12943 conf->pri.pri.max_call_waiting_calls;
12944 pris[span].pri.allow_call_waiting_calls =
12945 conf->pri.pri.allow_call_waiting_calls;
12946 #endif
12947 pris[span].pri.transfer = conf->chan.transfer;
12948 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12949 #if defined(HAVE_PRI_L2_PERSISTENCE)
12950 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12951 #endif
12952 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12953 #if defined(HAVE_PRI_AOC_EVENTS)
12954 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12955 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12956 #endif
12957 if (chan_sig == SIG_BRI_PTMP) {
12958 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12959 } else {
12960
12961 pris[span].pri.layer1_ignored = 0;
12962 }
12963 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12964 pris[span].pri.inband_on_setup_ack = conf->pri.pri.inband_on_setup_ack;
12965 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12966 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12967 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12968 #if defined(HAVE_PRI_MWI)
12969 ast_copy_string(pris[span].pri.mwi_mailboxes,
12970 conf->pri.pri.mwi_mailboxes,
12971 sizeof(pris[span].pri.mwi_mailboxes));
12972 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12973 conf->pri.pri.mwi_vm_numbers,
12974 sizeof(pris[span].pri.mwi_vm_numbers));
12975 #endif
12976 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12977 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12978 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12979 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12980 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12981 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12982 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12983 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12984 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12985 #if defined(HAVE_PRI_DISPLAY_TEXT)
12986 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12987 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12988 #endif
12989 #if defined(HAVE_PRI_MCID)
12990 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12991 #endif
12992 #if defined(HAVE_PRI_DATETIME_SEND)
12993 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12994 #endif
12995
12996 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12997 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12998 }
12999
13000 #if defined(HAVE_PRI_CALL_WAITING)
13001
13002 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
13003 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
13004 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
13005 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
13006 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
13007 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
13008 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
13009 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
13010 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
13011 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
13012 #endif
13013 } else {
13014 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
13015 destroy_dahdi_pvt(tmp);
13016 return NULL;
13017 }
13018 }
13019 }
13020 #endif
13021 } else {
13022
13023 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));
13024 chan_sig = tmp->sig;
13025 if (tmp->subs[SUB_REAL].dfd > -1) {
13026 memset(&p, 0, sizeof(p));
13027 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13028 }
13029 }
13030
13031 switch (chan_sig) {
13032 case SIG_FXSKS:
13033 case SIG_FXSLS:
13034 case SIG_EM:
13035 case SIG_EM_E1:
13036 case SIG_EMWINK:
13037 case SIG_FEATD:
13038 case SIG_FEATDMF:
13039 case SIG_FEATDMF_TA:
13040 case SIG_FEATB:
13041 case SIG_E911:
13042 case SIG_SF:
13043 case SIG_SFWINK:
13044 case SIG_FGC_CAMA:
13045 case SIG_FGC_CAMAMF:
13046 case SIG_SF_FEATD:
13047 case SIG_SF_FEATDMF:
13048 case SIG_SF_FEATB:
13049 p.starttime = 250;
13050 break;
13051 }
13052
13053 if (tmp->radio) {
13054
13055 p.channo = channel;
13056 p.rxwinktime = 1;
13057 p.rxflashtime = 1;
13058 p.starttime = 1;
13059 p.debouncetime = 5;
13060 } else {
13061 p.channo = channel;
13062
13063 if (conf->timing.prewinktime >= 0)
13064 p.prewinktime = conf->timing.prewinktime;
13065 if (conf->timing.preflashtime >= 0)
13066 p.preflashtime = conf->timing.preflashtime;
13067 if (conf->timing.winktime >= 0)
13068 p.winktime = conf->timing.winktime;
13069 if (conf->timing.flashtime >= 0)
13070 p.flashtime = conf->timing.flashtime;
13071 if (conf->timing.starttime >= 0)
13072 p.starttime = conf->timing.starttime;
13073 if (conf->timing.rxwinktime >= 0)
13074 p.rxwinktime = conf->timing.rxwinktime;
13075 if (conf->timing.rxflashtime >= 0)
13076 p.rxflashtime = conf->timing.rxflashtime;
13077 if (conf->timing.debouncetime >= 0)
13078 p.debouncetime = conf->timing.debouncetime;
13079 }
13080
13081
13082 if (tmp->subs[SUB_REAL].dfd >= 0)
13083 {
13084 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
13085 if (res < 0) {
13086 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
13087 destroy_dahdi_pvt(tmp);
13088 return NULL;
13089 }
13090 }
13091 #if 1
13092 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13093 memset(&bi, 0, sizeof(bi));
13094 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13095 if (!res) {
13096 bi.txbufpolicy = conf->chan.buf_policy;
13097 bi.rxbufpolicy = conf->chan.buf_policy;
13098 bi.numbufs = conf->chan.buf_no;
13099 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13100 if (res < 0) {
13101 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13102 }
13103 } else {
13104 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13105 }
13106 tmp->buf_policy = conf->chan.buf_policy;
13107 tmp->buf_no = conf->chan.buf_no;
13108 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13109 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13110 tmp->faxbuf_no = conf->chan.faxbuf_no;
13111
13112
13113
13114
13115 tmp->bufsize = bi.bufsize;
13116 }
13117 #endif
13118 tmp->immediate = conf->chan.immediate;
13119 tmp->transfertobusy = conf->chan.transfertobusy;
13120 if (chan_sig & __DAHDI_SIG_FXS) {
13121 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13122 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13123 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13124 }
13125 tmp->ringt_base = ringt_base;
13126 tmp->firstradio = 0;
13127 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13128 tmp->permcallwaiting = conf->chan.callwaiting;
13129 else
13130 tmp->permcallwaiting = 0;
13131
13132 tmp->destroy = 0;
13133 tmp->drings = conf->chan.drings;
13134
13135
13136 if (tmp->drings.ringnum[0].range == 0)
13137 tmp->drings.ringnum[0].range = 10;
13138 if (tmp->drings.ringnum[1].range == 0)
13139 tmp->drings.ringnum[1].range = 10;
13140 if (tmp->drings.ringnum[2].range == 0)
13141 tmp->drings.ringnum[2].range = 10;
13142
13143 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13144 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13145 tmp->threewaycalling = conf->chan.threewaycalling;
13146 tmp->adsi = conf->chan.adsi;
13147 tmp->use_smdi = conf->chan.use_smdi;
13148 tmp->permhidecallerid = conf->chan.hidecallerid;
13149 tmp->hidecalleridname = conf->chan.hidecalleridname;
13150 tmp->callreturn = conf->chan.callreturn;
13151 tmp->echocancel = conf->chan.echocancel;
13152 tmp->echotraining = conf->chan.echotraining;
13153 tmp->pulse = conf->chan.pulse;
13154 if (tmp->echocancel.head.tap_length) {
13155 tmp->echocanbridged = conf->chan.echocanbridged;
13156 } else {
13157 if (conf->chan.echocanbridged)
13158 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13159 tmp->echocanbridged = 0;
13160 }
13161 tmp->busydetect = conf->chan.busydetect;
13162 tmp->busycount = conf->chan.busycount;
13163 tmp->busy_cadence = conf->chan.busy_cadence;
13164 tmp->callprogress = conf->chan.callprogress;
13165 tmp->waitfordialtone = conf->chan.waitfordialtone;
13166 tmp->dialtone_detect = conf->chan.dialtone_detect;
13167 tmp->cancallforward = conf->chan.cancallforward;
13168 tmp->dtmfrelax = conf->chan.dtmfrelax;
13169 tmp->callwaiting = tmp->permcallwaiting;
13170 tmp->hidecallerid = tmp->permhidecallerid;
13171 tmp->channel = channel;
13172 tmp->stripmsd = conf->chan.stripmsd;
13173 tmp->use_callerid = conf->chan.use_callerid;
13174 tmp->cid_signalling = conf->chan.cid_signalling;
13175 tmp->cid_start = conf->chan.cid_start;
13176 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13177 tmp->restrictcid = conf->chan.restrictcid;
13178 tmp->use_callingpres = conf->chan.use_callingpres;
13179 if (tmp->usedistinctiveringdetection) {
13180 if (!tmp->use_callerid) {
13181 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13182 tmp->use_callerid = 1;
13183 }
13184 }
13185
13186 if (tmp->cid_signalling == CID_SIG_SMDI) {
13187 if (!tmp->use_smdi) {
13188 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13189 tmp->use_smdi = 1;
13190 }
13191 }
13192 if (tmp->use_smdi) {
13193 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13194 if (!(tmp->smdi_iface)) {
13195 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13196 tmp->use_smdi = 0;
13197 }
13198 }
13199
13200 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13201 tmp->amaflags = conf->chan.amaflags;
13202 if (!here) {
13203 tmp->confno = -1;
13204 tmp->propconfno = -1;
13205 }
13206 tmp->canpark = conf->chan.canpark;
13207 tmp->transfer = conf->chan.transfer;
13208 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13209 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13210 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13211 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13212 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13213 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13214 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13215 tmp->cid_ton = 0;
13216 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13217 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13218 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13219 } else {
13220 tmp->cid_num[0] = '\0';
13221 tmp->cid_name[0] = '\0';
13222 }
13223 #if defined(HAVE_PRI)
13224 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13225 tmp->cid_tag[0] = '\0';
13226 } else
13227 #endif
13228 {
13229 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13230 }
13231 tmp->cid_subaddr[0] = '\0';
13232 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13233 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13234 char *mailbox, *context;
13235 mailbox = context = ast_strdupa(tmp->mailbox);
13236 strsep(&context, "@");
13237 if (ast_strlen_zero(context))
13238 context = "default";
13239 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13240 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13241 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13242 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13243 AST_EVENT_IE_END);
13244 }
13245 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13246 tmp->mwisend_setting = conf->chan.mwisend_setting;
13247 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13248 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13249 #endif
13250
13251 tmp->group = conf->chan.group;
13252 tmp->callgroup = conf->chan.callgroup;
13253 tmp->pickupgroup= conf->chan.pickupgroup;
13254 ast_unref_namedgroups(tmp->named_callgroups);
13255 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13256 ast_unref_namedgroups(tmp->named_pickupgroups);
13257 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13258 if (conf->chan.vars) {
13259 struct ast_variable *v, *tmpvar;
13260 for (v = conf->chan.vars ; v ; v = v->next) {
13261 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13262 tmpvar->next = tmp->vars;
13263 tmp->vars = tmpvar;
13264 }
13265 }
13266 }
13267 tmp->cid_rxgain = conf->chan.cid_rxgain;
13268 tmp->rxgain = conf->chan.rxgain;
13269 tmp->txgain = conf->chan.txgain;
13270 tmp->txdrc = conf->chan.txdrc;
13271 tmp->rxdrc = conf->chan.rxdrc;
13272 tmp->tonezone = conf->chan.tonezone;
13273 if (tmp->subs[SUB_REAL].dfd > -1) {
13274 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13275 if (tmp->dsp)
13276 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13277 update_conf(tmp);
13278 if (!here) {
13279 switch (chan_sig) {
13280 case SIG_PRI_LIB_HANDLE_CASES:
13281 case SIG_SS7:
13282 case SIG_MFCR2:
13283 break;
13284 default:
13285
13286 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13287 break;
13288 }
13289 }
13290 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13291 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13292
13293 switch (tmp->sig) {
13294 #ifdef HAVE_PRI
13295 case SIG_PRI_LIB_HANDLE_CASES:
13296 sig_pri_set_alarm(tmp->sig_pvt, 1);
13297 break;
13298 #endif
13299 #if defined(HAVE_SS7)
13300 case SIG_SS7:
13301 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13302 break;
13303 #endif
13304 default:
13305
13306 analog_p = tmp->sig_pvt;
13307 if (analog_p) {
13308 analog_p->inalarm = 1;
13309 }
13310 tmp->inalarm = 1;
13311 break;
13312 }
13313 handle_alarms(tmp, res);
13314 }
13315 }
13316
13317 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13318 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13319 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13320 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13321 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13322
13323 if (!here) {
13324 tmp->locallyblocked = 0;
13325 tmp->remotelyblocked = 0;
13326 switch (tmp->sig) {
13327 #if defined(HAVE_PRI)
13328 case SIG_PRI_LIB_HANDLE_CASES:
13329 tmp->inservice = 1;
13330 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13331 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13332 if (chan_sig == SIG_PRI) {
13333 char db_chan_name[20];
13334 char db_answer[5];
13335
13336
13337
13338
13339
13340 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13341 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13342 unsigned *why;
13343
13344 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13345 if (tmp->pri->enable_service_message_support) {
13346 char state;
13347
13348 sscanf(db_answer, "%1c:%30u", &state, why);
13349
13350
13351 *why &= (SRVST_NEAREND | SRVST_FAREND);
13352 }
13353 if (!*why) {
13354 ast_db_del(db_chan_name, SRVST_DBKEY);
13355 }
13356 }
13357 }
13358 #endif
13359 break;
13360 #endif
13361 #if defined(HAVE_SS7)
13362 case SIG_SS7:
13363 tmp->inservice = 0;
13364 break;
13365 #endif
13366 default:
13367
13368 tmp->inservice = 1;
13369 break;
13370 }
13371 }
13372
13373 switch (tmp->sig) {
13374 #if defined(HAVE_PRI)
13375 case SIG_PRI_LIB_HANDLE_CASES:
13376 if (pri_chan) {
13377 pri_chan->channel = tmp->channel;
13378 pri_chan->hidecallerid = tmp->hidecallerid;
13379 pri_chan->hidecalleridname = tmp->hidecalleridname;
13380 pri_chan->immediate = tmp->immediate;
13381 pri_chan->inalarm = tmp->inalarm;
13382 pri_chan->priexclusive = tmp->priexclusive;
13383 pri_chan->priindication_oob = tmp->priindication_oob;
13384 pri_chan->use_callerid = tmp->use_callerid;
13385 pri_chan->use_callingpres = tmp->use_callingpres;
13386 ast_copy_string(pri_chan->context, tmp->context,
13387 sizeof(pri_chan->context));
13388 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13389 sizeof(pri_chan->mohinterpret));
13390 pri_chan->stripmsd = tmp->stripmsd;
13391 }
13392 break;
13393 #endif
13394 #if defined(HAVE_SS7)
13395 case SIG_SS7:
13396 if (ss7_chan) {
13397 ss7_chan->inalarm = tmp->inalarm;
13398
13399 ss7_chan->stripmsd = tmp->stripmsd;
13400 ss7_chan->hidecallerid = tmp->hidecallerid;
13401 ss7_chan->use_callerid = tmp->use_callerid;
13402 ss7_chan->use_callingpres = tmp->use_callingpres;
13403 ss7_chan->immediate = tmp->immediate;
13404 ss7_chan->locallyblocked = tmp->locallyblocked;
13405 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13406 ast_copy_string(ss7_chan->context, tmp->context,
13407 sizeof(ss7_chan->context));
13408 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13409 sizeof(ss7_chan->mohinterpret));
13410 }
13411 break;
13412 #endif
13413 default:
13414
13415 analog_p = tmp->sig_pvt;
13416 if (analog_p) {
13417 analog_p->channel = tmp->channel;
13418 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13419 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13420 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13421 analog_p->permcallwaiting = conf->chan.callwaiting;
13422 analog_p->callreturn = conf->chan.callreturn;
13423 analog_p->cancallforward = conf->chan.cancallforward;
13424 analog_p->canpark = conf->chan.canpark;
13425 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13426 analog_p->immediate = conf->chan.immediate;
13427 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13428 analog_p->pulse = conf->chan.pulse;
13429 analog_p->threewaycalling = conf->chan.threewaycalling;
13430 analog_p->transfer = conf->chan.transfer;
13431 analog_p->transfertobusy = conf->chan.transfertobusy;
13432 analog_p->use_callerid = tmp->use_callerid;
13433 analog_p->use_smdi = tmp->use_smdi;
13434 analog_p->smdi_iface = tmp->smdi_iface;
13435 analog_p->outsigmod = ANALOG_SIG_NONE;
13436 analog_p->echotraining = conf->chan.echotraining;
13437 analog_p->cid_signalling = conf->chan.cid_signalling;
13438 analog_p->stripmsd = conf->chan.stripmsd;
13439 switch (conf->chan.cid_start) {
13440 case CID_START_POLARITY:
13441 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13442 break;
13443 case CID_START_POLARITY_IN:
13444 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13445 break;
13446 case CID_START_DTMF_NOALERT:
13447 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13448 break;
13449 default:
13450 analog_p->cid_start = ANALOG_CID_START_RING;
13451 break;
13452 }
13453 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13454 analog_p->ringt = conf->chan.ringt;
13455 analog_p->ringt_base = ringt_base;
13456 analog_p->onhooktime = time(NULL);
13457 if (chan_sig & __DAHDI_SIG_FXO) {
13458 memset(&p, 0, sizeof(p));
13459 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13460 if (!res) {
13461 analog_p->fxsoffhookstate = p.rxisoffhook;
13462 }
13463 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13464 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13465 #endif
13466 }
13467 analog_p->msgstate = -1;
13468
13469 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13470 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13471 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13472
13473 analog_config_complete(analog_p);
13474 }
13475 break;
13476 }
13477 #if defined(HAVE_PRI)
13478 if (tmp->channel == CHAN_PSEUDO) {
13479
13480
13481
13482
13483 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13484 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13485 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13486 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13487 }
13488 #endif
13489 }
13490 if (tmp && !here) {
13491
13492 dahdi_iflist_insert(tmp);
13493 }
13494 return tmp;
13495 }
13496
13497 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13498 {
13499 #if defined(HAVE_PRI)
13500 if (0 < span) {
13501
13502 if (!p->pri || p->pri->span != span) {
13503 return 0;
13504 }
13505 if (!groupmatch && channelmatch == -1) {
13506
13507 *groupmatched = 1;
13508 return 1;
13509 }
13510 }
13511 #endif
13512
13513 if (groupmatch) {
13514 if ((p->group & groupmatch) != groupmatch)
13515
13516 return 0;
13517 *groupmatched = 1;
13518 }
13519
13520 if (channelmatch != -1) {
13521 if (p->channel != channelmatch)
13522
13523 return 0;
13524 *channelmatched = 1;
13525 }
13526
13527 return 1;
13528 }
13529
13530 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13531 {
13532 struct dahdi_pvt *p = *pvt;
13533
13534 if (p->inalarm)
13535 return 0;
13536
13537 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13538 return analog_available(p->sig_pvt);
13539
13540 switch (p->sig) {
13541 #if defined(HAVE_PRI)
13542 case SIG_PRI_LIB_HANDLE_CASES:
13543 {
13544 struct sig_pri_chan *pvt_chan;
13545 int res;
13546
13547 pvt_chan = p->sig_pvt;
13548 res = sig_pri_available(&pvt_chan, is_specific_channel);
13549 *pvt = pvt_chan->chan_pvt;
13550 return res;
13551 }
13552 #endif
13553 #if defined(HAVE_SS7)
13554 case SIG_SS7:
13555 return sig_ss7_available(p->sig_pvt);
13556 #endif
13557 default:
13558 break;
13559 }
13560
13561 if (p->locallyblocked || p->remotelyblocked) {
13562 return 0;
13563 }
13564
13565
13566 if (!p->owner) {
13567 #ifdef HAVE_OPENR2
13568
13569 if (p->mfcr2) {
13570 if (p->mfcr2call) {
13571 return 0;
13572 } else {
13573 return 1;
13574 }
13575 }
13576 #endif
13577 return 1;
13578 }
13579
13580 return 0;
13581 }
13582
13583 #if defined(HAVE_PRI)
13584 #if defined(HAVE_PRI_CALL_WAITING)
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595
13596
13597 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13598 {
13599 struct dahdi_pvt *pvt = priv;
13600
13601 pvt->stripmsd = pri->ch_cfg.stripmsd;
13602 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13603 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13604 pvt->immediate = pri->ch_cfg.immediate;
13605 pvt->priexclusive = pri->ch_cfg.priexclusive;
13606 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13607 pvt->use_callerid = pri->ch_cfg.use_callerid;
13608 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13609 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13610 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13611 }
13612 #endif
13613 #endif
13614
13615 #if defined(HAVE_PRI)
13616
13617
13618
13619
13620
13621
13622
13623
13624
13625
13626
13627
13628 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13629 {
13630 int pvt_idx;
13631 int res;
13632 unsigned idx;
13633 struct dahdi_pvt *pvt;
13634 struct sig_pri_chan *chan;
13635 struct dahdi_bufferinfo bi;
13636
13637 static int nobch_channel = CHAN_PSEUDO;
13638
13639
13640 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13641 if (!pri->pvts[pvt_idx]) {
13642 break;
13643 }
13644 }
13645 if (pri->numchans == pvt_idx) {
13646 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13647 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13648 return -1;
13649 }
13650
13651
13652 pri->pvts[pvt_idx] = NULL;
13653 ++pri->numchans;
13654 }
13655
13656 pvt = ast_calloc(1, sizeof(*pvt));
13657 if (!pvt) {
13658 return -1;
13659 }
13660 pvt->cc_params = ast_cc_config_params_init();
13661 if (!pvt->cc_params) {
13662 ast_free(pvt);
13663 return -1;
13664 }
13665 ast_mutex_init(&pvt->lock);
13666 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13667 pvt->subs[idx].dfd = -1;
13668 }
13669 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13670 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13671 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13672 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13673
13674 chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13675 if (!chan) {
13676 destroy_dahdi_pvt(pvt);
13677 return -1;
13678 }
13679 chan->no_b_channel = 1;
13680
13681
13682
13683
13684
13685
13686 pvt->law_default = DAHDI_LAW_ALAW;
13687
13688 pvt->sig = pri->sig;
13689 pvt->outsigmod = -1;
13690 pvt->pri = pri;
13691 pvt->sig_pvt = chan;
13692 pri->pvts[pvt_idx] = chan;
13693
13694 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13695 if (pvt->subs[SUB_REAL].dfd < 0) {
13696 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13697 strerror(errno));
13698 destroy_dahdi_pvt(pvt);
13699 return -1;
13700 }
13701 memset(&bi, 0, sizeof(bi));
13702 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13703 if (!res) {
13704 pvt->bufsize = bi.bufsize;
13705 bi.txbufpolicy = pvt->buf_policy;
13706 bi.rxbufpolicy = pvt->buf_policy;
13707 bi.numbufs = pvt->buf_no;
13708 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13709 if (res < 0) {
13710 ast_log(LOG_WARNING,
13711 "Unable to set buffer policy on no B channel interface: %s\n",
13712 strerror(errno));
13713 }
13714 } else
13715 ast_log(LOG_WARNING,
13716 "Unable to check buffer policy on no B channel interface: %s\n",
13717 strerror(errno));
13718
13719 --nobch_channel;
13720 if (CHAN_PSEUDO < nobch_channel) {
13721 nobch_channel = CHAN_PSEUDO - 1;
13722 }
13723 pvt->channel = nobch_channel;
13724 pvt->span = pri->span;
13725 chan->channel = pvt->channel;
13726
13727 dahdi_nobch_insert(pri, pvt);
13728
13729 return pvt_idx;
13730 }
13731 #endif
13732
13733
13734
13735
13736
13737
13738 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13739 {
13740 struct dahdi_pvt *p;
13741 struct dahdi_bufferinfo bi;
13742 int res;
13743
13744 p = ast_malloc(sizeof(*p));
13745 if (!p) {
13746 return NULL;
13747 }
13748 *p = *src;
13749
13750
13751 p->cc_params = ast_cc_config_params_init();
13752 if (!p->cc_params) {
13753 ast_free(p);
13754 return NULL;
13755 }
13756 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13757
13758 p->which_iflist = DAHDI_IFLIST_NONE;
13759 p->next = NULL;
13760 p->prev = NULL;
13761 ast_mutex_init(&p->lock);
13762 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13763 if (p->subs[SUB_REAL].dfd < 0) {
13764 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13765 destroy_dahdi_pvt(p);
13766 return NULL;
13767 }
13768 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13769 if (!res) {
13770 bi.txbufpolicy = src->buf_policy;
13771 bi.rxbufpolicy = src->buf_policy;
13772 bi.numbufs = src->buf_no;
13773 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13774 if (res < 0) {
13775 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13776 }
13777 } else
13778 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13779 p->destroy = 1;
13780 dahdi_iflist_insert(p);
13781 return p;
13782 }
13783
13784 struct dahdi_starting_point {
13785
13786 ast_group_t groupmatch;
13787
13788 int channelmatch;
13789
13790 int rr_starting_point;
13791
13792 int span;
13793
13794 int cadance;
13795
13796 char opt;
13797
13798 char backwards;
13799
13800 char roundrobin;
13801 };
13802 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13803 {
13804 char *dest;
13805 char *s;
13806 int x;
13807 int res = 0;
13808 struct dahdi_pvt *p;
13809 char *subdir = NULL;
13810 AST_DECLARE_APP_ARGS(args,
13811 AST_APP_ARG(group);
13812
13813
13814 AST_APP_ARG(other);
13815 );
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838
13839
13840 if (data) {
13841 dest = ast_strdupa(data);
13842 } else {
13843 ast_log(LOG_WARNING, "Channel requested with no data\n");
13844 return NULL;
13845 }
13846 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13847 if (!args.argc || ast_strlen_zero(args.group)) {
13848 ast_log(LOG_WARNING, "No channel/group specified\n");
13849 return NULL;
13850 }
13851
13852
13853 memset(param, 0, sizeof(*param));
13854 param->channelmatch = -1;
13855
13856 if (strchr(args.group, '!') != NULL) {
13857 char *prev = args.group;
13858 while ((s = strchr(prev, '!')) != NULL) {
13859 *s++ = '/';
13860 prev = s;
13861 }
13862 *(prev - 1) = '\0';
13863 subdir = args.group;
13864 args.group = prev;
13865 } else if (args.group[0] == 'i') {
13866
13867 res = sscanf(args.group + 1, "%30d", &x);
13868 if (res < 1) {
13869 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13870 return NULL;
13871 }
13872 param->span = x;
13873
13874
13875 s = strchr(args.group, '-');
13876 if (!s) {
13877
13878 return iflist;
13879 }
13880 args.group = s + 1;
13881 res = 0;
13882 }
13883 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13884
13885 s = args.group + 1;
13886 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13887 if (res < 1) {
13888 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13889 return NULL;
13890 }
13891 param->groupmatch = ((ast_group_t) 1 << x);
13892
13893 if (toupper(args.group[0]) == 'G') {
13894 if (args.group[0] == 'G') {
13895 param->backwards = 1;
13896 p = ifend;
13897 } else
13898 p = iflist;
13899 } else {
13900 if (ARRAY_LEN(round_robin) <= x) {
13901 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13902 x, data);
13903 return NULL;
13904 }
13905 if (args.group[0] == 'R') {
13906 param->backwards = 1;
13907 p = round_robin[x] ? round_robin[x]->prev : ifend;
13908 if (!p)
13909 p = ifend;
13910 } else {
13911 p = round_robin[x] ? round_robin[x]->next : iflist;
13912 if (!p)
13913 p = iflist;
13914 }
13915 param->roundrobin = 1;
13916 param->rr_starting_point = x;
13917 }
13918 } else {
13919 s = args.group;
13920 if (!strcasecmp(s, "pseudo")) {
13921
13922 x = CHAN_PSEUDO;
13923 param->channelmatch = x;
13924 } else {
13925 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13926 if (res < 1) {
13927 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13928 return NULL;
13929 } else {
13930 param->channelmatch = x;
13931 }
13932 }
13933 if (subdir) {
13934 char path[PATH_MAX];
13935 struct stat stbuf;
13936
13937 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13938 subdir, param->channelmatch);
13939 if (stat(path, &stbuf) < 0) {
13940 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13941 path, strerror(errno));
13942 return NULL;
13943 }
13944 if (!S_ISCHR(stbuf.st_mode)) {
13945 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13946 path);
13947 return NULL;
13948 }
13949 param->channelmatch = minor(stbuf.st_rdev);
13950 }
13951
13952 p = iflist;
13953 }
13954
13955 if (param->opt == 'r' && res < 3) {
13956 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13957 param->opt = '\0';
13958 }
13959
13960 return p;
13961 }
13962
13963 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
13964 {
13965 int callwait = 0;
13966 struct dahdi_pvt *p;
13967 struct ast_channel *tmp = NULL;
13968 struct dahdi_pvt *exitpvt;
13969 int channelmatched = 0;
13970 int groupmatched = 0;
13971 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13972 int transcapdigital = 0;
13973 #endif
13974 struct dahdi_starting_point start;
13975 struct ast_callid *callid = NULL;
13976 int callid_created = ast_callid_threadstorage_auto(&callid);
13977
13978 ast_mutex_lock(&iflock);
13979 p = determine_starting_point(data, &start);
13980 if (!p) {
13981
13982 ast_mutex_unlock(&iflock);
13983 ast_callid_threadstorage_auto_clean(callid, callid_created);
13984 return NULL;
13985 }
13986
13987
13988 exitpvt = p;
13989 while (p && !tmp) {
13990 if (start.roundrobin)
13991 round_robin[start.rr_starting_point] = p;
13992
13993 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13994 && available(&p, channelmatched)) {
13995 ast_debug(1, "Using channel %d\n", p->channel);
13996
13997 callwait = (p->owner != NULL);
13998 #ifdef HAVE_OPENR2
13999 if (p->mfcr2) {
14000 ast_mutex_lock(&p->lock);
14001 if (p->mfcr2call) {
14002 ast_mutex_unlock(&p->lock);
14003 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
14004 goto next;
14005 }
14006 p->mfcr2call = 1;
14007 ast_mutex_unlock(&p->lock);
14008 }
14009 #endif
14010 if (p->channel == CHAN_PSEUDO) {
14011 p = duplicate_pseudo(p);
14012 if (!p) {
14013 break;
14014 }
14015 }
14016
14017 p->distinctivering = 0;
14018
14019 switch (start.opt) {
14020 case '\0':
14021
14022 break;
14023 case 'c':
14024
14025 p->confirmanswer = 1;
14026 break;
14027 case 'r':
14028
14029 p->distinctivering = start.cadance;
14030 break;
14031 case 'd':
14032 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14033
14034 transcapdigital = AST_TRANS_CAP_DIGITAL;
14035 #endif
14036 break;
14037 default:
14038 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
14039 break;
14040 }
14041
14042 p->outgoing = 1;
14043 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
14044 tmp = analog_request(p->sig_pvt, &callwait, requestor);
14045 #ifdef HAVE_PRI
14046 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
14047
14048
14049
14050
14051
14052 ast_mutex_lock(&p->lock);
14053 ast_mutex_unlock(&p->lock);
14054
14055 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
14056 sizeof(p->dnid));
14057 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
14058 #endif
14059 #if defined(HAVE_SS7)
14060 } else if (p->sig == SIG_SS7) {
14061 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
14062 #endif
14063 } else {
14064 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "", callid);
14065 }
14066 if (!tmp) {
14067 p->outgoing = 0;
14068 #if defined(HAVE_PRI)
14069 switch (p->sig) {
14070 case SIG_PRI_LIB_HANDLE_CASES:
14071 #if defined(HAVE_PRI_CALL_WAITING)
14072 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14073 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14074 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14075 }
14076 #endif
14077
14078
14079
14080
14081 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14082 break;
14083 default:
14084 break;
14085 }
14086 #endif
14087 } else {
14088 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14089 }
14090 break;
14091 }
14092 #ifdef HAVE_OPENR2
14093 next:
14094 #endif
14095 if (start.backwards) {
14096 p = p->prev;
14097 if (!p)
14098 p = ifend;
14099 } else {
14100 p = p->next;
14101 if (!p)
14102 p = iflist;
14103 }
14104
14105 if (p == exitpvt)
14106 break;
14107 }
14108 ast_mutex_unlock(&iflock);
14109 restart_monitor();
14110 if (cause && !tmp) {
14111 if (callwait || channelmatched) {
14112 *cause = AST_CAUSE_BUSY;
14113 } else if (groupmatched) {
14114 *cause = AST_CAUSE_CONGESTION;
14115 } else {
14116
14117
14118
14119
14120 }
14121 }
14122
14123 ast_callid_threadstorage_auto_clean(callid, callid_created);
14124 return tmp;
14125 }
14126
14127
14128
14129
14130
14131
14132
14133
14134
14135
14136
14137 static int dahdi_devicestate(const char *data)
14138 {
14139 #if defined(HAVE_PRI)
14140 const char *device;
14141 unsigned span;
14142 int res;
14143
14144 device = data;
14145
14146 if (*device != 'I') {
14147
14148 return AST_DEVICE_UNKNOWN;
14149 }
14150 res = sscanf(device, "I%30u", &span);
14151 if (res != 1 || !span || NUM_SPANS < span) {
14152
14153 return AST_DEVICE_UNKNOWN;
14154 }
14155 device = strchr(device, '/');
14156 if (!device) {
14157
14158 return AST_DEVICE_UNKNOWN;
14159 }
14160
14161
14162
14163
14164
14165 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14166 ++device;
14167 if (!strcmp(device, "congestion"))
14168 #endif
14169 {
14170 return pris[span - 1].pri.congestion_devstate;
14171 }
14172 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14173 else if (!strcmp(device, "threshold")) {
14174 return pris[span - 1].pri.threshold_devstate;
14175 }
14176 return AST_DEVICE_UNKNOWN;
14177 #endif
14178 #else
14179 return AST_DEVICE_UNKNOWN;
14180 #endif
14181 }
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193
14194
14195
14196
14197
14198
14199 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14200 {
14201 struct dahdi_pvt *p;
14202 struct dahdi_pvt *exitpvt;
14203 struct dahdi_starting_point start;
14204 int groupmatched = 0;
14205 int channelmatched = 0;
14206
14207 ast_mutex_lock(&iflock);
14208 p = determine_starting_point(dest, &start);
14209 if (!p) {
14210 ast_mutex_unlock(&iflock);
14211 return -1;
14212 }
14213 exitpvt = p;
14214 for (;;) {
14215 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14216
14217 struct ast_str *device_name;
14218 char *dash;
14219 const char *monitor_type;
14220 char dialstring[AST_CHANNEL_NAME];
14221 char full_device_name[AST_CHANNEL_NAME];
14222
14223 switch (ast_get_cc_monitor_policy(p->cc_params)) {
14224 case AST_CC_MONITOR_NEVER:
14225 break;
14226 case AST_CC_MONITOR_NATIVE:
14227 case AST_CC_MONITOR_ALWAYS:
14228 case AST_CC_MONITOR_GENERIC:
14229 #if defined(HAVE_PRI)
14230 if (dahdi_sig_pri_lib_handles(p->sig)) {
14231
14232
14233
14234
14235 snprintf(full_device_name, sizeof(full_device_name),
14236 "DAHDI/I%d/congestion", p->pri->span);
14237 } else
14238 #endif
14239 {
14240 #if defined(HAVE_PRI)
14241 device_name = create_channel_name(p, 1, "");
14242 #else
14243 device_name = create_channel_name(p);
14244 #endif
14245 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14246 device_name ? ast_str_buffer(device_name) : "");
14247 ast_free(device_name);
14248
14249
14250
14251
14252
14253 dash = strrchr(full_device_name, '-');
14254 if (dash) {
14255 *dash = '\0';
14256 }
14257 }
14258 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14259
14260
14261
14262
14263
14264
14265
14266 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14267 callback(inbound,
14268 #if defined(HAVE_PRI)
14269 p->pri ? p->pri->cc_params : p->cc_params,
14270 #else
14271 p->cc_params,
14272 #endif
14273 monitor_type, full_device_name, dialstring, NULL);
14274 break;
14275 }
14276 }
14277 p = start.backwards ? p->prev : p->next;
14278 if (!p) {
14279 p = start.backwards ? ifend : iflist;
14280 }
14281 if (p == exitpvt) {
14282 break;
14283 }
14284 }
14285 ast_mutex_unlock(&iflock);
14286 return 0;
14287 }
14288
14289 #if defined(HAVE_SS7)
14290 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14291 {
14292 int i;
14293
14294 if (ss7) {
14295 for (i = 0; i < NUM_SPANS; i++) {
14296 if (linksets[i].ss7.ss7 == ss7) {
14297 ast_verbose_callid(NULL, "[%d] %s", i + 1, s);
14298 return;
14299 }
14300 }
14301 }
14302 ast_verbose_callid(NULL, "%s", s);
14303 }
14304 #endif
14305
14306 #if defined(HAVE_SS7)
14307 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14308 {
14309 int i;
14310
14311 if (ss7) {
14312 for (i = 0; i < NUM_SPANS; i++) {
14313 if (linksets[i].ss7.ss7 == ss7) {
14314 ast_log_callid(LOG_ERROR, NULL, "[%d] %s", i + 1, s);
14315 return;
14316 }
14317 }
14318 }
14319 ast_log_callid(LOG_ERROR, NULL, "%s", s);
14320 }
14321 #endif
14322
14323 #if defined(HAVE_OPENR2)
14324 static void *mfcr2_monitor(void *data)
14325 {
14326 struct dahdi_mfcr2 *mfcr2 = data;
14327
14328
14329
14330
14331
14332 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14333 int res = 0;
14334 int i = 0;
14335 int oldstate = 0;
14336 int quit_loop = 0;
14337 int maxsleep = 20;
14338 int was_idle = 0;
14339 int pollsize = 0;
14340
14341
14342 for (i = 0; i < mfcr2->numchans; i++) {
14343 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14344 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14345 }
14346 while (1) {
14347
14348
14349 pollsize = 0;
14350 for (i = 0; i < mfcr2->numchans; i++) {
14351 pollers[i].revents = 0;
14352 pollers[i].events = 0;
14353 if (mfcr2->pvts[i]->owner) {
14354 continue;
14355 }
14356 if (!mfcr2->pvts[i]->r2chan) {
14357 ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14358 quit_loop = 1;
14359 break;
14360 }
14361 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14362 pollers[i].events = POLLIN | POLLPRI;
14363 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14364 pollsize++;
14365 }
14366 if (quit_loop) {
14367 break;
14368 }
14369 if (pollsize == 0) {
14370 if (!was_idle) {
14371 ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14372 was_idle = 1;
14373 }
14374 poll(NULL, 0, maxsleep);
14375 continue;
14376 }
14377 was_idle = 0;
14378
14379
14380 pthread_testcancel();
14381 res = poll(pollers, mfcr2->numchans, maxsleep);
14382 pthread_testcancel();
14383 if ((res < 0) && (errno != EINTR)) {
14384 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14385 break;
14386 }
14387
14388 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14389 for (i = 0; i < mfcr2->numchans; i++) {
14390 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14391 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14392 }
14393 }
14394 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14395 }
14396 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14397 return 0;
14398 }
14399 #endif
14400
14401 #if defined(HAVE_PRI)
14402 static void dahdi_pri_message(struct pri *pri, char *s)
14403 {
14404 int x;
14405 int y;
14406 int dchan = -1;
14407 int span = -1;
14408 int dchancount = 0;
14409
14410 if (pri) {
14411 for (x = 0; x < NUM_SPANS; x++) {
14412 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14413 if (pris[x].pri.dchans[y]) {
14414 dchancount++;
14415 }
14416
14417 if (pris[x].pri.dchans[y] == pri) {
14418 dchan = y;
14419 }
14420 }
14421 if (dchan >= 0) {
14422 span = x;
14423 break;
14424 }
14425 dchancount = 0;
14426 }
14427 if (-1 < span) {
14428 if (1 < dchancount) {
14429 ast_verbose_callid(NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14430 } else {
14431 ast_verbose_callid(NULL, "PRI Span: %d %s", span + 1, s);
14432 }
14433 } else {
14434 ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14435 }
14436 } else {
14437 ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14438 }
14439
14440 ast_mutex_lock(&pridebugfdlock);
14441
14442 if (pridebugfd >= 0) {
14443 if (write(pridebugfd, s, strlen(s)) < 0) {
14444 ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14445 }
14446 }
14447
14448 ast_mutex_unlock(&pridebugfdlock);
14449 }
14450 #endif
14451
14452 #if defined(HAVE_PRI)
14453 static void dahdi_pri_error(struct pri *pri, char *s)
14454 {
14455 int x;
14456 int y;
14457 int dchan = -1;
14458 int span = -1;
14459 int dchancount = 0;
14460
14461 if (pri) {
14462 for (x = 0; x < NUM_SPANS; x++) {
14463 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14464 if (pris[x].pri.dchans[y]) {
14465 dchancount++;
14466 }
14467
14468 if (pris[x].pri.dchans[y] == pri) {
14469 dchan = y;
14470 }
14471 }
14472 if (dchan >= 0) {
14473 span = x;
14474 break;
14475 }
14476 dchancount = 0;
14477 }
14478 if (-1 < span) {
14479 if (1 < dchancount) {
14480 ast_log_callid(LOG_ERROR, NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14481 } else {
14482 ast_log_callid(LOG_ERROR, NULL, "PRI Span: %d %s", span + 1, s);
14483 }
14484 } else {
14485 ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14486 }
14487 } else {
14488 ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14489 }
14490
14491 ast_mutex_lock(&pridebugfdlock);
14492
14493 if (pridebugfd >= 0) {
14494 if (write(pridebugfd, s, strlen(s)) < 0) {
14495 ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14496 }
14497 }
14498
14499 ast_mutex_unlock(&pridebugfdlock);
14500 }
14501 #endif
14502
14503 #if defined(HAVE_PRI)
14504 static int prepare_pri(struct dahdi_pri *pri)
14505 {
14506 int i, res, x;
14507 struct dahdi_params p;
14508 struct dahdi_bufferinfo bi;
14509 struct dahdi_spaninfo si;
14510
14511 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14512 if (!pri->dchannels[i])
14513 break;
14514 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14515 x = pri->dchannels[i];
14516 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14517 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14518 return -1;
14519 }
14520 memset(&p, 0, sizeof(p));
14521 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14522 if (res) {
14523 dahdi_close_pri_fd(pri, i);
14524 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14525 return -1;
14526 }
14527 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14528 dahdi_close_pri_fd(pri, i);
14529 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14530 return -1;
14531 }
14532 memset(&si, 0, sizeof(si));
14533 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14534 if (res) {
14535 dahdi_close_pri_fd(pri, i);
14536 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14537 }
14538 if (!si.alarms) {
14539 pri_event_noalarm(&pri->pri, i, 1);
14540 } else {
14541 pri_event_alarm(&pri->pri, i, 1);
14542 }
14543 memset(&bi, 0, sizeof(bi));
14544 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14545 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14546 bi.numbufs = 32;
14547 bi.bufsize = 1024;
14548 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14549 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14550 dahdi_close_pri_fd(pri, i);
14551 return -1;
14552 }
14553 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14554 }
14555 return 0;
14556 }
14557 #endif
14558
14559 #if defined(HAVE_PRI)
14560 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14561 {
14562 int which, span;
14563 char *ret = NULL;
14564
14565 if (pos != rpos)
14566 return ret;
14567
14568 for (which = span = 0; span < NUM_SPANS; span++) {
14569 if (pris[span].pri.pri && ++which > state) {
14570 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14571 ret = NULL;
14572 }
14573 break;
14574 }
14575 }
14576 return ret;
14577 }
14578 #endif
14579
14580 #if defined(HAVE_PRI)
14581 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14582 {
14583 return complete_span_helper(line,word,pos,state,3);
14584 }
14585 #endif
14586
14587 #if defined(HAVE_PRI)
14588 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14589 {
14590 int myfd;
14591 switch (cmd) {
14592 case CLI_INIT:
14593 e->command = "pri set debug file";
14594 e->usage = "Usage: pri set debug file [output-file]\n"
14595 " Sends PRI debug output to the specified output file\n";
14596 return NULL;
14597 case CLI_GENERATE:
14598 return NULL;
14599 }
14600 if (a->argc < 5)
14601 return CLI_SHOWUSAGE;
14602
14603 if (ast_strlen_zero(a->argv[4]))
14604 return CLI_SHOWUSAGE;
14605
14606 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14607 if (myfd < 0) {
14608 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14609 return CLI_SUCCESS;
14610 }
14611
14612 ast_mutex_lock(&pridebugfdlock);
14613
14614 if (pridebugfd >= 0)
14615 close(pridebugfd);
14616
14617 pridebugfd = myfd;
14618 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14619 ast_mutex_unlock(&pridebugfdlock);
14620 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14621 return CLI_SUCCESS;
14622 }
14623 #endif
14624
14625 #if defined(HAVE_PRI)
14626 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14627 {
14628 int span;
14629 int x;
14630 int debugmask = 0;
14631 int level = 0;
14632 switch (cmd) {
14633 case CLI_INIT:
14634 e->command = "pri set debug {on|off|hex|intense|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15} span";
14635 e->usage =
14636 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14637 " Enables debugging on a given PRI span\n"
14638 " Level is a bitmap of the following values:\n"
14639 " 1 General debugging incl. state changes\n"
14640 " 2 Decoded Q.931 messages\n"
14641 " 4 Decoded Q.921 messages\n"
14642 " 8 Raw hex dumps of Q.921 frames\n"
14643 " on - equivalent to 3\n"
14644 " hex - equivalent to 8\n"
14645 " intense - equivalent to 15\n";
14646 return NULL;
14647 case CLI_GENERATE:
14648 return complete_span_4(a->line, a->word, a->pos, a->n);
14649 }
14650 if (a->argc < 6) {
14651 return CLI_SHOWUSAGE;
14652 }
14653
14654 if (!strcasecmp(a->argv[3], "on")) {
14655 level = 3;
14656 } else if (!strcasecmp(a->argv[3], "off")) {
14657 level = 0;
14658 } else if (!strcasecmp(a->argv[3], "intense")) {
14659 level = 15;
14660 } else if (!strcasecmp(a->argv[3], "hex")) {
14661 level = 8;
14662 } else {
14663 level = atoi(a->argv[3]);
14664 }
14665 span = atoi(a->argv[5]);
14666 if ((span < 1) || (span > NUM_SPANS)) {
14667 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14668 return CLI_SUCCESS;
14669 }
14670 if (!pris[span-1].pri.pri) {
14671 ast_cli(a->fd, "No PRI running on span %d\n", span);
14672 return CLI_SUCCESS;
14673 }
14674
14675 if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14676 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14677 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14678 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14679
14680
14681 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14682 if (pris[span - 1].pri.dchans[x]) {
14683 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14684 }
14685 }
14686 if (level == 0) {
14687
14688 ast_mutex_lock(&pridebugfdlock);
14689 if (0 <= pridebugfd) {
14690 close(pridebugfd);
14691 pridebugfd = -1;
14692 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14693 pridebugfilename);
14694 }
14695 ast_mutex_unlock(&pridebugfdlock);
14696 }
14697 pris[span - 1].pri.debug = (level) ? 1 : 0;
14698 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14699 return CLI_SUCCESS;
14700 }
14701 #endif
14702
14703 #if defined(HAVE_PRI)
14704 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14705 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14706 {
14707 unsigned *why;
14708 int channel;
14709 int trunkgroup;
14710 int x, y, fd = a->fd;
14711 int interfaceid = 0;
14712 char db_chan_name[20], db_answer[5];
14713 struct dahdi_pvt *tmp;
14714 struct dahdi_pri *pri;
14715
14716 if (a->argc < 5 || a->argc > 6)
14717 return CLI_SHOWUSAGE;
14718 if (strchr(a->argv[4], ':')) {
14719 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14720 return CLI_SHOWUSAGE;
14721 if ((trunkgroup < 1) || (channel < 1))
14722 return CLI_SHOWUSAGE;
14723 pri = NULL;
14724 for (x=0;x<NUM_SPANS;x++) {
14725 if (pris[x].pri.trunkgroup == trunkgroup) {
14726 pri = pris + x;
14727 break;
14728 }
14729 }
14730 if (!pri) {
14731 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14732 return CLI_FAILURE;
14733 }
14734 } else
14735 channel = atoi(a->argv[4]);
14736
14737 if (a->argc == 6)
14738 interfaceid = atoi(a->argv[5]);
14739
14740
14741 for (x = 0; x < NUM_SPANS; x++) {
14742 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14743 if (pris[x].dchannels[y] == channel) {
14744 pri = pris + x;
14745 if (pri->pri.enable_service_message_support) {
14746 ast_mutex_lock(&pri->pri.lock);
14747 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14748 ast_mutex_unlock(&pri->pri.lock);
14749 } else {
14750 ast_cli(fd,
14751 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14752 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14753 }
14754 return CLI_SUCCESS;
14755 }
14756 }
14757 }
14758
14759
14760 ast_mutex_lock(&iflock);
14761 for (tmp = iflist; tmp; tmp = tmp->next) {
14762 if (tmp->pri && tmp->channel == channel) {
14763 ast_mutex_unlock(&iflock);
14764 ast_mutex_lock(&tmp->pri->lock);
14765 if (!tmp->pri->enable_service_message_support) {
14766 ast_mutex_unlock(&tmp->pri->lock);
14767 ast_cli(fd,
14768 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14769 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14770 return CLI_SUCCESS;
14771 }
14772 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14773 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14774 switch(changestatus) {
14775 case 0:
14776
14777 ast_db_del(db_chan_name, SRVST_DBKEY);
14778 *why &= ~SRVST_NEAREND;
14779 if (*why) {
14780 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14781 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14782 } else {
14783 dahdi_pri_update_span_devstate(tmp->pri);
14784 }
14785 break;
14786
14787 case 2:
14788
14789 ast_db_del(db_chan_name, SRVST_DBKEY);
14790 *why |= SRVST_NEAREND;
14791 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14792 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14793 dahdi_pri_update_span_devstate(tmp->pri);
14794 break;
14795
14796
14797 default:
14798 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14799 break;
14800 }
14801 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14802 ast_mutex_unlock(&tmp->pri->lock);
14803 return CLI_SUCCESS;
14804 }
14805 }
14806 ast_mutex_unlock(&iflock);
14807
14808 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14809 return CLI_FAILURE;
14810 }
14811
14812 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14813 {
14814 switch (cmd) {
14815 case CLI_INIT:
14816 e->command = "pri service enable channel";
14817 e->usage =
14818 "Usage: pri service enable channel <channel> [<interface id>]\n"
14819 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14820 " to restore a channel to service, with optional interface id\n"
14821 " as agreed upon with remote switch operator\n";
14822 return NULL;
14823 case CLI_GENERATE:
14824 return NULL;
14825 }
14826 return handle_pri_service_generic(e, cmd, a, 0);
14827 }
14828
14829 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14830 {
14831 switch (cmd) {
14832 case CLI_INIT:
14833 e->command = "pri service disable channel";
14834 e->usage =
14835 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14836 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14837 " to remove a channel from service, with optional interface id\n"
14838 " as agreed upon with remote switch operator\n";
14839 return NULL;
14840 case CLI_GENERATE:
14841 return NULL;
14842 }
14843 return handle_pri_service_generic(e, cmd, a, 2);
14844 }
14845 #endif
14846 #endif
14847
14848 #if defined(HAVE_PRI)
14849 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14850 {
14851 int span;
14852
14853 switch (cmd) {
14854 case CLI_INIT:
14855 e->command = "pri show channels";
14856 e->usage =
14857 "Usage: pri show channels\n"
14858 " Displays PRI channel information such as the current mapping\n"
14859 " of DAHDI B channels to Asterisk channel names and which calls\n"
14860 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14861 " are not associated with any B channel.\n";
14862 return NULL;
14863 case CLI_GENERATE:
14864 return NULL;
14865 }
14866
14867 if (a->argc != 3)
14868 return CLI_SHOWUSAGE;
14869
14870 sig_pri_cli_show_channels_header(a->fd);
14871 for (span = 0; span < NUM_SPANS; ++span) {
14872 if (pris[span].pri.pri) {
14873 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14874 }
14875 }
14876 return CLI_SUCCESS;
14877 }
14878 #endif
14879
14880 #if defined(HAVE_PRI)
14881 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14882 {
14883 int span;
14884
14885 switch (cmd) {
14886 case CLI_INIT:
14887 e->command = "pri show spans";
14888 e->usage =
14889 "Usage: pri show spans\n"
14890 " Displays PRI span information\n";
14891 return NULL;
14892 case CLI_GENERATE:
14893 return NULL;
14894 }
14895
14896 if (a->argc != 3)
14897 return CLI_SHOWUSAGE;
14898
14899 for (span = 0; span < NUM_SPANS; span++) {
14900 if (pris[span].pri.pri) {
14901 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14902 }
14903 }
14904 return CLI_SUCCESS;
14905 }
14906 #endif
14907
14908 #if defined(HAVE_PRI)
14909 #define container_of(ptr, type, member) \
14910 ((type *)((char *)(ptr) - offsetof(type, member)))
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922
14923
14924 static int pri_destroy_dchan(struct sig_pri_span *pri)
14925 {
14926 int i;
14927 struct dahdi_pri* dahdi_pri;
14928
14929 if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14930 return 0;
14931 }
14932 pthread_cancel(pri->master);
14933 pthread_join(pri->master, NULL);
14934
14935
14936 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14937 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14938 ast_debug(4, "closing pri_fd %d\n", i);
14939 dahdi_close_pri_fd(dahdi_pri, i);
14940 }
14941 pri->pri = NULL;
14942 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14943 return 1;
14944 }
14945
14946 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14947 struct ast_cli_args *a)
14948 {
14949 int span;
14950 int i;
14951 int res;
14952
14953 switch (cmd) {
14954 case CLI_INIT:
14955 e->command = "pri destroy span";
14956 e->usage =
14957 "Usage: pri destroy span <span>\n"
14958 " Destorys D-channel of span and its B-channels.\n"
14959 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14960 return NULL;
14961 case CLI_GENERATE:
14962 return complete_span_4(a->line, a->word, a->pos, a->n);
14963 }
14964
14965 if (a->argc < 4) {
14966 return CLI_SHOWUSAGE;
14967 }
14968 res = sscanf(a->argv[3], "%30d", &span);
14969 if ((res != 1) || span < 1 || span > NUM_SPANS) {
14970 ast_cli(a->fd,
14971 "Invalid span '%s'. Should be a number from %d to %d\n",
14972 a->argv[3], 1, NUM_SPANS);
14973 return CLI_SUCCESS;
14974 }
14975 if (!pris[span - 1].pri.pri) {
14976 ast_cli(a->fd, "No PRI running on span %d\n", span);
14977 return CLI_SUCCESS;
14978 }
14979
14980 for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14981 int channel;
14982 struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14983
14984 if (!pvt) {
14985 continue;
14986 }
14987 channel = pvt->channel;
14988 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14989 dahdi_destroy_channel_bynum(channel);
14990 }
14991 ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14992 pri_destroy_dchan(&pris[span - 1].pri);
14993
14994 return CLI_SUCCESS;
14995 }
14996
14997 #endif
14998
14999 #if defined(HAVE_PRI)
15000 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15001 {
15002 int span;
15003
15004 switch (cmd) {
15005 case CLI_INIT:
15006 e->command = "pri show span";
15007 e->usage =
15008 "Usage: pri show span <span>\n"
15009 " Displays PRI Information on a given PRI span\n";
15010 return NULL;
15011 case CLI_GENERATE:
15012 return complete_span_4(a->line, a->word, a->pos, a->n);
15013 }
15014
15015 if (a->argc < 4)
15016 return CLI_SHOWUSAGE;
15017 span = atoi(a->argv[3]);
15018 if ((span < 1) || (span > NUM_SPANS)) {
15019 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15020 return CLI_SUCCESS;
15021 }
15022 if (!pris[span-1].pri.pri) {
15023 ast_cli(a->fd, "No PRI running on span %d\n", span);
15024 return CLI_SUCCESS;
15025 }
15026
15027 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15028
15029 return CLI_SUCCESS;
15030 }
15031 #endif
15032
15033 #if defined(HAVE_PRI)
15034 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15035 {
15036 int x;
15037 int span;
15038 int count=0;
15039 int debug;
15040
15041 switch (cmd) {
15042 case CLI_INIT:
15043 e->command = "pri show debug";
15044 e->usage =
15045 "Usage: pri show debug\n"
15046 " Show the debug state of pri spans\n";
15047 return NULL;
15048 case CLI_GENERATE:
15049 return NULL;
15050 }
15051
15052 for (span = 0; span < NUM_SPANS; span++) {
15053 if (pris[span].pri.pri) {
15054 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15055 if (pris[span].pri.dchans[x]) {
15056 debug = pri_get_debug(pris[span].pri.dchans[x]);
15057 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" );
15058 count++;
15059 }
15060 }
15061 }
15062
15063 }
15064 ast_mutex_lock(&pridebugfdlock);
15065 if (pridebugfd >= 0)
15066 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15067 ast_mutex_unlock(&pridebugfdlock);
15068
15069 if (!count)
15070 ast_cli(a->fd, "No PRI running\n");
15071 return CLI_SUCCESS;
15072 }
15073 #endif
15074
15075 #if defined(HAVE_PRI)
15076 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15077 {
15078 switch (cmd) {
15079 case CLI_INIT:
15080 e->command = "pri show version";
15081 e->usage =
15082 "Usage: pri show version\n"
15083 "Show libpri version information\n";
15084 return NULL;
15085 case CLI_GENERATE:
15086 return NULL;
15087 }
15088
15089 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15090
15091 return CLI_SUCCESS;
15092 }
15093 #endif
15094
15095 #if defined(HAVE_PRI)
15096 static struct ast_cli_entry dahdi_pri_cli[] = {
15097 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15098 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15099 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15100 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15101 #endif
15102 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15103 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15104 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15105 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15106 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15107 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15108 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15109 };
15110 #endif
15111
15112 #ifdef HAVE_OPENR2
15113
15114 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15115 {
15116 switch (cmd) {
15117 case CLI_INIT:
15118 e->command = "mfcr2 show version";
15119 e->usage =
15120 "Usage: mfcr2 show version\n"
15121 " Shows the version of the OpenR2 library being used.\n";
15122 return NULL;
15123 case CLI_GENERATE:
15124 return NULL;
15125 }
15126 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15127 return CLI_SUCCESS;
15128 }
15129
15130 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15131 {
15132 #define FORMAT "%4s %40s\n"
15133 int i = 0;
15134 int numvariants = 0;
15135 const openr2_variant_entry_t *variants;
15136 switch (cmd) {
15137 case CLI_INIT:
15138 e->command = "mfcr2 show variants";
15139 e->usage =
15140 "Usage: mfcr2 show variants\n"
15141 " Shows the list of MFC/R2 variants supported.\n";
15142 return NULL;
15143 case CLI_GENERATE:
15144 return NULL;
15145 }
15146 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15147 ast_cli(a->fd, "Failed to get list of variants.\n");
15148 return CLI_FAILURE;
15149 }
15150 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15151 for (i = 0; i < numvariants; i++) {
15152 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15153 }
15154 return CLI_SUCCESS;
15155 #undef FORMAT
15156 }
15157
15158 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15159 {
15160 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15161 int filtertype = 0;
15162 int targetnum = 0;
15163 char channo[5];
15164 char anino[5];
15165 char dnisno[5];
15166 struct dahdi_pvt *p;
15167 openr2_context_t *r2context;
15168 openr2_variant_t r2variant;
15169 switch (cmd) {
15170 case CLI_INIT:
15171 e->command = "mfcr2 show channels [group|context]";
15172 e->usage =
15173 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15174 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15175 return NULL;
15176 case CLI_GENERATE:
15177 return NULL;
15178 }
15179 if (!((a->argc == 3) || (a->argc == 5))) {
15180 return CLI_SHOWUSAGE;
15181 }
15182 if (a->argc == 5) {
15183 if (!strcasecmp(a->argv[3], "group")) {
15184 targetnum = atoi(a->argv[4]);
15185 if ((targetnum < 0) || (targetnum > 63))
15186 return CLI_SHOWUSAGE;
15187 targetnum = 1 << targetnum;
15188 filtertype = 1;
15189 } else if (!strcasecmp(a->argv[3], "context")) {
15190 filtertype = 2;
15191 } else {
15192 return CLI_SHOWUSAGE;
15193 }
15194 }
15195 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15196 ast_mutex_lock(&iflock);
15197 for (p = iflist; p; p = p->next) {
15198 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15199 continue;
15200 }
15201 if (filtertype) {
15202 switch(filtertype) {
15203 case 1:
15204 if (p->group != targetnum) {
15205 continue;
15206 }
15207 break;
15208 case 2:
15209 if (strcasecmp(p->context, a->argv[4])) {
15210 continue;
15211 }
15212 break;
15213 default:
15214 ;
15215 }
15216 }
15217 r2context = openr2_chan_get_context(p->r2chan);
15218 r2variant = openr2_context_get_variant(r2context);
15219 snprintf(channo, sizeof(channo), "%d", p->channel);
15220 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15221 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15222 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
15223 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15224 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15225 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15226 }
15227 ast_mutex_unlock(&iflock);
15228 return CLI_SUCCESS;
15229 #undef FORMAT
15230 }
15231
15232 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15233 {
15234 struct dahdi_pvt *p = NULL;
15235 int channo = 0;
15236 char *toklevel = NULL;
15237 char *saveptr = NULL;
15238 char *logval = NULL;
15239 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15240 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15241 switch (cmd) {
15242 case CLI_INIT:
15243 e->command = "mfcr2 set debug";
15244 e->usage =
15245 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15246 " Set a new logging level for the specified channel.\n"
15247 " If no channel is specified the logging level will be applied to all channels.\n";
15248 return NULL;
15249 case CLI_GENERATE:
15250 return NULL;
15251 }
15252 if (a->argc < 4) {
15253 return CLI_SHOWUSAGE;
15254 }
15255 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15256 logval = ast_strdupa(a->argv[3]);
15257 toklevel = strtok_r(logval, ",", &saveptr);
15258 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15259 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15260 return CLI_FAILURE;
15261 } else if (OR2_LOG_NOTHING == tmplevel) {
15262 loglevel = tmplevel;
15263 } else {
15264 loglevel |= tmplevel;
15265 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15266 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15267 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15268 continue;
15269 }
15270 loglevel |= tmplevel;
15271 }
15272 }
15273 ast_mutex_lock(&iflock);
15274 for (p = iflist; p; p = p->next) {
15275 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15276 continue;
15277 }
15278 if ((channo != -1) && (p->channel != channo )) {
15279 continue;
15280 }
15281 openr2_chan_set_log_level(p->r2chan, loglevel);
15282 if (channo != -1) {
15283 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15284 break;
15285 }
15286 }
15287 if ((channo != -1) && !p) {
15288 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15289 }
15290 if (channo == -1) {
15291 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15292 }
15293 ast_mutex_unlock(&iflock);
15294 return CLI_SUCCESS;
15295 }
15296
15297 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15298 {
15299 struct dahdi_pvt *p = NULL;
15300 int channo = 0;
15301 switch (cmd) {
15302 case CLI_INIT:
15303 e->command = "mfcr2 call files [on|off]";
15304 e->usage =
15305 "Usage: mfcr2 call files [on|off] <channel>\n"
15306 " Enable call files creation on the specified channel.\n"
15307 " If no channel is specified call files creation policy will be applied to all channels.\n";
15308 return NULL;
15309 case CLI_GENERATE:
15310 return NULL;
15311 }
15312 if (a->argc < 4) {
15313 return CLI_SHOWUSAGE;
15314 }
15315 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15316 ast_mutex_lock(&iflock);
15317 for (p = iflist; p; p = p->next) {
15318 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15319 continue;
15320 }
15321 if ((channo != -1) && (p->channel != channo )) {
15322 continue;
15323 }
15324 if (ast_true(a->argv[3])) {
15325 openr2_chan_enable_call_files(p->r2chan);
15326 } else {
15327 openr2_chan_disable_call_files(p->r2chan);
15328 }
15329 if (channo != -1) {
15330 if (ast_true(a->argv[3])) {
15331 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15332 } else {
15333 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15334 }
15335 break;
15336 }
15337 }
15338 if ((channo != -1) && !p) {
15339 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15340 }
15341 if (channo == -1) {
15342 if (ast_true(a->argv[3])) {
15343 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15344 } else {
15345 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15346 }
15347 }
15348 ast_mutex_unlock(&iflock);
15349 return CLI_SUCCESS;
15350 }
15351
15352 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15353 {
15354 struct dahdi_pvt *p = NULL;
15355 int channo = 0;
15356 switch (cmd) {
15357 case CLI_INIT:
15358 e->command = "mfcr2 set idle";
15359 e->usage =
15360 "Usage: mfcr2 set idle <channel>\n"
15361 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15362 " Force the given channel into IDLE state.\n"
15363 " If no channel is specified, all channels will be set to IDLE.\n";
15364 return NULL;
15365 case CLI_GENERATE:
15366 return NULL;
15367 }
15368 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15369 ast_mutex_lock(&iflock);
15370 for (p = iflist; p; p = p->next) {
15371 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15372 continue;
15373 }
15374 if ((channo != -1) && (p->channel != channo )) {
15375 continue;
15376 }
15377 openr2_chan_set_idle(p->r2chan);
15378 ast_mutex_lock(&p->lock);
15379 p->locallyblocked = 0;
15380 p->mfcr2call = 0;
15381 ast_mutex_unlock(&p->lock);
15382 if (channo != -1) {
15383 break;
15384 }
15385 }
15386 if ((channo != -1) && !p) {
15387 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15388 }
15389 ast_mutex_unlock(&iflock);
15390 return CLI_SUCCESS;
15391 }
15392
15393 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15394 {
15395 struct dahdi_pvt *p = NULL;
15396 int channo = 0;
15397 switch (cmd) {
15398 case CLI_INIT:
15399 e->command = "mfcr2 set blocked";
15400 e->usage =
15401 "Usage: mfcr2 set blocked <channel>\n"
15402 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15403 " Force the given channel into BLOCKED state.\n"
15404 " If no channel is specified, all channels will be set to BLOCKED.\n";
15405 return NULL;
15406 case CLI_GENERATE:
15407 return NULL;
15408 }
15409 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15410 ast_mutex_lock(&iflock);
15411 for (p = iflist; p; p = p->next) {
15412 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15413 continue;
15414 }
15415 if ((channo != -1) && (p->channel != channo )) {
15416 continue;
15417 }
15418 openr2_chan_set_blocked(p->r2chan);
15419 ast_mutex_lock(&p->lock);
15420 p->locallyblocked = 1;
15421 ast_mutex_unlock(&p->lock);
15422 if (channo != -1) {
15423 break;
15424 }
15425 }
15426 if ((channo != -1) && !p) {
15427 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15428 }
15429 ast_mutex_unlock(&iflock);
15430 return CLI_SUCCESS;
15431 }
15432
15433 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15434 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15435 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15436 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15437 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15438 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15439 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15440 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15441 };
15442
15443 #endif
15444
15445 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15446 {
15447 int channel;
15448 int ret;
15449 switch (cmd) {
15450 case CLI_INIT:
15451 e->command = "dahdi destroy channel";
15452 e->usage =
15453 "Usage: dahdi destroy channel <chan num>\n"
15454 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15455 return NULL;
15456 case CLI_GENERATE:
15457 return NULL;
15458 }
15459 if (a->argc != 4)
15460 return CLI_SHOWUSAGE;
15461
15462 channel = atoi(a->argv[3]);
15463 ret = dahdi_destroy_channel_bynum(channel);
15464 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15465 }
15466
15467 static void dahdi_softhangup_all(void)
15468 {
15469 struct dahdi_pvt *p;
15470 retry:
15471 ast_mutex_lock(&iflock);
15472 for (p = iflist; p; p = p->next) {
15473 ast_mutex_lock(&p->lock);
15474 if (p->owner && !p->restartpending) {
15475 if (ast_channel_trylock(p->owner)) {
15476 if (option_debug > 2)
15477 ast_verbose("Avoiding deadlock\n");
15478
15479 ast_mutex_unlock(&p->lock);
15480 ast_mutex_unlock(&iflock);
15481 goto retry;
15482 }
15483 if (option_debug > 2)
15484 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15485 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15486 p->restartpending = 1;
15487 num_restart_pending++;
15488 ast_channel_unlock(p->owner);
15489 }
15490 ast_mutex_unlock(&p->lock);
15491 }
15492 ast_mutex_unlock(&iflock);
15493 }
15494
15495 static int setup_dahdi(int reload);
15496 static int dahdi_restart(void)
15497 {
15498 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15499 int i, j;
15500 #endif
15501 int cancel_code;
15502 struct dahdi_pvt *p;
15503
15504 ast_mutex_lock(&restart_lock);
15505 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15506 dahdi_softhangup_all();
15507 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15508 #ifdef HAVE_OPENR2
15509 dahdi_r2_destroy_links();
15510 #endif
15511
15512 #if defined(HAVE_PRI)
15513 for (i = 0; i < NUM_SPANS; i++) {
15514 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15515 cancel_code = pthread_cancel(pris[i].pri.master);
15516 pthread_kill(pris[i].pri.master, SIGURG);
15517 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);
15518 pthread_join(pris[i].pri.master, NULL);
15519 ast_debug(4, "Joined thread of span %d\n", i);
15520 }
15521 }
15522 #endif
15523
15524 #if defined(HAVE_SS7)
15525 for (i = 0; i < NUM_SPANS; i++) {
15526 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15527 cancel_code = pthread_cancel(linksets[i].ss7.master);
15528 pthread_kill(linksets[i].ss7.master, SIGURG);
15529 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);
15530 pthread_join(linksets[i].ss7.master, NULL);
15531 ast_debug(4, "Joined thread of span %d\n", i);
15532 }
15533 }
15534 #endif
15535
15536 ast_mutex_lock(&monlock);
15537 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15538 cancel_code = pthread_cancel(monitor_thread);
15539 pthread_kill(monitor_thread, SIGURG);
15540 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15541 pthread_join(monitor_thread, NULL);
15542 ast_debug(4, "Joined monitor thread\n");
15543 }
15544 monitor_thread = AST_PTHREADT_NULL;
15545
15546 ast_mutex_lock(&ss_thread_lock);
15547 while (ss_thread_count > 0) {
15548 int x = DAHDI_FLASH;
15549 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15550
15551 ast_mutex_lock(&iflock);
15552 for (p = iflist; p; p = p->next) {
15553 if (p->owner) {
15554
15555 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15556 }
15557 }
15558 ast_mutex_unlock(&iflock);
15559 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15560 }
15561
15562
15563 dahdi_softhangup_all();
15564 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15565 destroy_all_channels();
15566 memset(round_robin, 0, sizeof(round_robin));
15567 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15568
15569 ast_mutex_unlock(&monlock);
15570
15571 #ifdef HAVE_PRI
15572 for (i = 0; i < NUM_SPANS; i++) {
15573 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15574 dahdi_close_pri_fd(&(pris[i]), j);
15575 }
15576
15577 memset(pris, 0, sizeof(pris));
15578 for (i = 0; i < NUM_SPANS; i++) {
15579 sig_pri_init_pri(&pris[i].pri);
15580 }
15581 pri_set_error(dahdi_pri_error);
15582 pri_set_message(dahdi_pri_message);
15583 #endif
15584 #if defined(HAVE_SS7)
15585 for (i = 0; i < NUM_SPANS; i++) {
15586 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15587 dahdi_close_ss7_fd(&(linksets[i]), j);
15588 }
15589
15590 memset(linksets, 0, sizeof(linksets));
15591 for (i = 0; i < NUM_SPANS; i++) {
15592 sig_ss7_init_linkset(&linksets[i].ss7);
15593 }
15594 ss7_set_error(dahdi_ss7_error);
15595 ss7_set_message(dahdi_ss7_message);
15596 #endif
15597
15598 if (setup_dahdi(2) != 0) {
15599 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15600 ast_mutex_unlock(&ss_thread_lock);
15601 return 1;
15602 }
15603 ast_mutex_unlock(&ss_thread_lock);
15604 ast_mutex_unlock(&restart_lock);
15605 return 0;
15606 }
15607
15608 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15609 {
15610 switch (cmd) {
15611 case CLI_INIT:
15612 e->command = "dahdi restart";
15613 e->usage =
15614 "Usage: dahdi restart\n"
15615 " Restarts the DAHDI channels: destroys them all and then\n"
15616 " re-reads them from chan_dahdi.conf.\n"
15617 " Note that this will STOP any running CALL on DAHDI channels.\n"
15618 "";
15619 return NULL;
15620 case CLI_GENERATE:
15621 return NULL;
15622 }
15623 if (a->argc != 2)
15624 return CLI_SHOWUSAGE;
15625
15626 if (dahdi_restart() != 0)
15627 return CLI_FAILURE;
15628 return CLI_SUCCESS;
15629 }
15630
15631 static int action_dahdirestart(struct mansession *s, const struct message *m)
15632 {
15633 if (dahdi_restart() != 0) {
15634 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15635 return 1;
15636 }
15637 astman_send_ack(s, m, "DAHDIRestart: Success");
15638 return 0;
15639 }
15640
15641 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15642 {
15643 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15644 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15645 ast_group_t targetnum = 0;
15646 int filtertype = 0;
15647 struct dahdi_pvt *tmp = NULL;
15648 char tmps[20] = "";
15649 char statestr[20] = "";
15650 char blockstr[20] = "";
15651
15652 switch (cmd) {
15653 case CLI_INIT:
15654 e->command = "dahdi show channels [group|context]";
15655 e->usage =
15656 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15657 " Shows a list of available channels with optional filtering\n"
15658 " <group> must be a number between 0 and 63\n";
15659 return NULL;
15660 case CLI_GENERATE:
15661 return NULL;
15662 }
15663
15664
15665
15666 if (!((a->argc == 3) || (a->argc == 5)))
15667 return CLI_SHOWUSAGE;
15668
15669 if (a->argc == 5) {
15670 if (!strcasecmp(a->argv[3], "group")) {
15671 targetnum = atoi(a->argv[4]);
15672 if (63 < targetnum) {
15673 return CLI_SHOWUSAGE;
15674 }
15675 targetnum = ((ast_group_t) 1) << targetnum;
15676 filtertype = 1;
15677 } else if (!strcasecmp(a->argv[3], "context")) {
15678 filtertype = 2;
15679 }
15680 }
15681
15682 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
15683 ast_mutex_lock(&iflock);
15684 for (tmp = iflist; tmp; tmp = tmp->next) {
15685 if (filtertype) {
15686 switch(filtertype) {
15687 case 1:
15688 if (!(tmp->group & targetnum)) {
15689 continue;
15690 }
15691 break;
15692 case 2:
15693 if (strcasecmp(tmp->context, a->argv[4])) {
15694 continue;
15695 }
15696 break;
15697 default:
15698 break;
15699 }
15700 }
15701 if (tmp->channel > 0) {
15702 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15703 } else
15704 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15705
15706 if (tmp->locallyblocked)
15707 blockstr[0] = 'L';
15708 else
15709 blockstr[0] = ' ';
15710
15711 if (tmp->remotelyblocked)
15712 blockstr[1] = 'R';
15713 else
15714 blockstr[1] = ' ';
15715
15716 blockstr[2] = '\0';
15717
15718 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15719
15720 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
15721 }
15722 ast_mutex_unlock(&iflock);
15723 return CLI_SUCCESS;
15724 #undef FORMAT
15725 #undef FORMAT2
15726 }
15727
15728 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15729 {
15730 int channel;
15731 struct dahdi_pvt *tmp = NULL;
15732 struct dahdi_confinfo ci;
15733 struct dahdi_params ps;
15734 int x;
15735
15736 switch (cmd) {
15737 case CLI_INIT:
15738 e->command = "dahdi show channel";
15739 e->usage =
15740 "Usage: dahdi show channel <chan num>\n"
15741 " Detailed information about a given channel\n";
15742 return NULL;
15743 case CLI_GENERATE:
15744 return NULL;
15745 }
15746
15747 if (a->argc != 4)
15748 return CLI_SHOWUSAGE;
15749
15750 channel = atoi(a->argv[3]);
15751
15752 ast_mutex_lock(&iflock);
15753 for (tmp = iflist; tmp; tmp = tmp->next) {
15754 if (tmp->channel == channel) {
15755 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15756 ast_cli(a->fd, "Description: %s\n", tmp->description);
15757 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15758 ast_cli(a->fd, "Span: %d\n", tmp->span);
15759 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15760 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15761 ast_cli(a->fd, "Context: %s\n", tmp->context);
15762 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15763 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15764 #if defined(HAVE_PRI)
15765 #if defined(HAVE_PRI_SUBADDR)
15766 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15767 #endif
15768 #endif
15769 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15770 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15771 if (tmp->vars) {
15772 struct ast_variable *v;
15773 ast_cli(a->fd, "Variables:\n");
15774 for (v = tmp->vars ; v ; v = v->next)
15775 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15776 }
15777 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15778 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15779 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15780 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15781 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
15782 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? ast_channel_name(tmp->subs[SUB_REAL].owner) : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15783 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? ast_channel_name(tmp->subs[SUB_CALLWAIT].owner) : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15784 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? ast_channel_name(tmp->subs[SUB_THREEWAY].owner) : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15785 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15786 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15787 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15788 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15789 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15790 if (tmp->busydetect) {
15791 #if defined(BUSYDETECT_TONEONLY)
15792 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15793 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15794 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15795 #endif
15796 #ifdef BUSYDETECT_DEBUG
15797 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15798 #endif
15799 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15800 ast_cli(a->fd, " Busy Pattern: %d,%d,%d,%d\n", tmp->busy_cadence.pattern[0], tmp->busy_cadence.pattern[1], (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[2] : 0, (tmp->busy_cadence.length == 4) ? tmp->busy_cadence.pattern[3] : 0);
15801 }
15802 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15803 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15804 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15805 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15806 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15807 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15808 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15809 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15810 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15811 ast_cli(a->fd, "Echo Cancellation:\n");
15812
15813 if (tmp->echocancel.head.tap_length) {
15814 ast_cli(a->fd, "\t%u taps\n", tmp->echocancel.head.tap_length);
15815 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15816 ast_cli(a->fd, "\t\t%s: %dd\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15817 }
15818 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15819 } else {
15820 ast_cli(a->fd, "\tnone\n");
15821 }
15822 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15823 if (tmp->master)
15824 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15825 for (x = 0; x < MAX_SLAVES; x++) {
15826 if (tmp->slaves[x])
15827 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15828 }
15829 #ifdef HAVE_OPENR2
15830 if (tmp->mfcr2) {
15831 char calldir[OR2_MAX_PATH];
15832 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15833 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15834 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15835 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15836 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15837 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15838 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15839 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15840 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15841 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15842 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15843 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15844 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15845 #endif
15846 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15847 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15848 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15849 #endif
15850 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15851 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15852 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15853 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15854 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15855 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15856 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15857 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15858 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15859 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15860 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15861 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15862 }
15863 #endif
15864 #if defined(HAVE_SS7)
15865 if (tmp->ss7) {
15866 struct sig_ss7_chan *chan = tmp->sig_pvt;
15867
15868 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15869 }
15870 #endif
15871 #ifdef HAVE_PRI
15872 if (tmp->pri) {
15873 struct sig_pri_chan *chan = tmp->sig_pvt;
15874
15875 ast_cli(a->fd, "PRI Flags: ");
15876 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15877 ast_cli(a->fd, "Resetting=%u ", chan->resetting);
15878 }
15879 if (chan->call)
15880 ast_cli(a->fd, "Call ");
15881 if (chan->allocated) {
15882 ast_cli(a->fd, "Allocated ");
15883 }
15884 ast_cli(a->fd, "\n");
15885 if (tmp->logicalspan)
15886 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15887 else
15888 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15889 }
15890 #endif
15891 memset(&ci, 0, sizeof(ci));
15892 ps.channo = tmp->channel;
15893 if (tmp->subs[SUB_REAL].dfd > -1) {
15894 memset(&ci, 0, sizeof(ci));
15895 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15896 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, (unsigned)ci.confmode);
15897 }
15898 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15899 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15900 }
15901 memset(&ps, 0, sizeof(ps));
15902 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15903 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15904 } else {
15905 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15906 }
15907 }
15908 ast_mutex_unlock(&iflock);
15909 return CLI_SUCCESS;
15910 }
15911 }
15912 ast_mutex_unlock(&iflock);
15913
15914 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15915 return CLI_FAILURE;
15916 }
15917
15918 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15919 {
15920 int i, j;
15921 switch (cmd) {
15922 case CLI_INIT:
15923 e->command = "dahdi show cadences";
15924 e->usage =
15925 "Usage: dahdi show cadences\n"
15926 " Shows all cadences currently defined\n";
15927 return NULL;
15928 case CLI_GENERATE:
15929 return NULL;
15930 }
15931 for (i = 0; i < num_cadence; i++) {
15932 char output[1024];
15933 char tmp[16], tmp2[64];
15934 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15935 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15936
15937 for (j = 0; j < 16; j++) {
15938 if (cadences[i].ringcadence[j] == 0)
15939 break;
15940 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15941 if (cidrings[i] * 2 - 1 == j)
15942 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15943 else
15944 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15945 if (j != 0)
15946 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15947 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15948 }
15949 ast_cli(a->fd,"%s\n",output);
15950 }
15951 return CLI_SUCCESS;
15952 }
15953
15954
15955 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15956 {
15957 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15958 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15959 int span;
15960 int res;
15961 char alarmstr[50];
15962
15963 int ctl;
15964 struct dahdi_spaninfo s;
15965
15966 switch (cmd) {
15967 case CLI_INIT:
15968 e->command = "dahdi show status";
15969 e->usage =
15970 "Usage: dahdi show status\n"
15971 " Shows a list of DAHDI cards with status\n";
15972 return NULL;
15973 case CLI_GENERATE:
15974 return NULL;
15975 }
15976 ctl = open("/dev/dahdi/ctl", O_RDWR);
15977 if (ctl < 0) {
15978 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15979 return CLI_FAILURE;
15980 }
15981 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15982
15983 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15984 s.spanno = span;
15985 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15986 if (res) {
15987 continue;
15988 }
15989 alarmstr[0] = '\0';
15990 if (s.alarms > 0) {
15991 if (s.alarms & DAHDI_ALARM_BLUE)
15992 strcat(alarmstr, "BLU/");
15993 if (s.alarms & DAHDI_ALARM_YELLOW)
15994 strcat(alarmstr, "YEL/");
15995 if (s.alarms & DAHDI_ALARM_RED)
15996 strcat(alarmstr, "RED/");
15997 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15998 strcat(alarmstr, "LB/");
15999 if (s.alarms & DAHDI_ALARM_RECOVER)
16000 strcat(alarmstr, "REC/");
16001 if (s.alarms & DAHDI_ALARM_NOTOPEN)
16002 strcat(alarmstr, "NOP/");
16003 if (!strlen(alarmstr))
16004 strcat(alarmstr, "UUU/");
16005 if (strlen(alarmstr)) {
16006
16007 alarmstr[strlen(alarmstr) - 1] = '\0';
16008 }
16009 } else {
16010 if (s.numchans)
16011 strcpy(alarmstr, "OK");
16012 else
16013 strcpy(alarmstr, "UNCONFIGURED");
16014 }
16015
16016 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16017 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16018 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16019 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16020 "CAS",
16021 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16022 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16023 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16024 "Unk",
16025 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16026 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16027 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16028 lbostr[s.lbo]
16029 );
16030 }
16031 close(ctl);
16032
16033 return CLI_SUCCESS;
16034 #undef FORMAT
16035 #undef FORMAT2
16036 }
16037
16038 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16039 {
16040 int pseudo_fd = -1;
16041 struct dahdi_versioninfo vi;
16042
16043 switch (cmd) {
16044 case CLI_INIT:
16045 e->command = "dahdi show version";
16046 e->usage =
16047 "Usage: dahdi show version\n"
16048 " Shows the DAHDI version in use\n";
16049 return NULL;
16050 case CLI_GENERATE:
16051 return NULL;
16052 }
16053 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16054 ast_cli(a->fd, "Failed to open control file to get version.\n");
16055 return CLI_SUCCESS;
16056 }
16057
16058 strcpy(vi.version, "Unknown");
16059 strcpy(vi.echo_canceller, "Unknown");
16060
16061 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16062 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16063 else
16064 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16065
16066 close(pseudo_fd);
16067
16068 return CLI_SUCCESS;
16069 }
16070
16071 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16072 {
16073 int channel;
16074 int gain;
16075 int tx;
16076 struct dahdi_hwgain hwgain;
16077 struct dahdi_pvt *tmp = NULL;
16078
16079 switch (cmd) {
16080 case CLI_INIT:
16081 e->command = "dahdi set hwgain {rx|tx}";
16082 e->usage =
16083 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16084 " Sets the hardware gain on a given channel. Changes take effect\n"
16085 " immediately whether the channel is in use or not.\n"
16086 "\n"
16087 " <rx|tx> which direction do you want to change (relative to our module)\n"
16088 " <chan num> is the channel number relative to the device\n"
16089 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16090 "\n"
16091 " Please note:\n"
16092 " * This is currently the only way to set hwgain by the channel driver.\n"
16093 " * hwgain is only supportable by hardware with analog ports because\n"
16094 " hwgain works on the analog side of an analog-digital conversion.\n";
16095 return NULL;
16096 case CLI_GENERATE:
16097 return NULL;
16098 }
16099
16100 if (a->argc != 6)
16101 return CLI_SHOWUSAGE;
16102
16103 if (!strcasecmp("rx", a->argv[3]))
16104 tx = 0;
16105 else if (!strcasecmp("tx", a->argv[3]))
16106 tx = 1;
16107 else
16108 return CLI_SHOWUSAGE;
16109
16110 channel = atoi(a->argv[4]);
16111 gain = atof(a->argv[5])*10.0;
16112
16113 ast_mutex_lock(&iflock);
16114
16115 for (tmp = iflist; tmp; tmp = tmp->next) {
16116
16117 if (tmp->channel != channel)
16118 continue;
16119
16120 if (tmp->subs[SUB_REAL].dfd == -1)
16121 break;
16122
16123 hwgain.newgain = gain;
16124 hwgain.tx = tx;
16125 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
16126 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16127 ast_mutex_unlock(&iflock);
16128 return CLI_FAILURE;
16129 }
16130 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
16131 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
16132 break;
16133 }
16134
16135 ast_mutex_unlock(&iflock);
16136
16137 if (tmp)
16138 return CLI_SUCCESS;
16139
16140 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16141 return CLI_FAILURE;
16142
16143 }
16144
16145 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16146 {
16147 int channel;
16148 float gain;
16149 int tx;
16150 int res;
16151 struct dahdi_pvt *tmp = NULL;
16152
16153 switch (cmd) {
16154 case CLI_INIT:
16155 e->command = "dahdi set swgain {rx|tx}";
16156 e->usage =
16157 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16158 " Sets the software gain on a given channel and overrides the\n"
16159 " value provided at module loadtime. Changes take effect\n"
16160 " immediately whether the channel is in use or not.\n"
16161 "\n"
16162 " <rx|tx> which direction do you want to change (relative to our module)\n"
16163 " <chan num> is the channel number relative to the device\n"
16164 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16165 return NULL;
16166 case CLI_GENERATE:
16167 return NULL;
16168 }
16169
16170 if (a->argc != 6)
16171 return CLI_SHOWUSAGE;
16172
16173 if (!strcasecmp("rx", a->argv[3]))
16174 tx = 0;
16175 else if (!strcasecmp("tx", a->argv[3]))
16176 tx = 1;
16177 else
16178 return CLI_SHOWUSAGE;
16179
16180 channel = atoi(a->argv[4]);
16181 gain = atof(a->argv[5]);
16182
16183 ast_mutex_lock(&iflock);
16184 for (tmp = iflist; tmp; tmp = tmp->next) {
16185
16186 if (tmp->channel != channel)
16187 continue;
16188
16189 if (tmp->subs[SUB_REAL].dfd == -1)
16190 break;
16191
16192 if (tx)
16193 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16194 else
16195 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16196
16197 if (res) {
16198 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16199 ast_mutex_unlock(&iflock);
16200 return CLI_FAILURE;
16201 }
16202
16203 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
16204 tx ? "tx" : "rx", gain, channel);
16205
16206 if (tx) {
16207 tmp->txgain = gain;
16208 } else {
16209 tmp->rxgain = gain;
16210 }
16211 break;
16212 }
16213 ast_mutex_unlock(&iflock);
16214
16215 if (tmp)
16216 return CLI_SUCCESS;
16217
16218 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16219 return CLI_FAILURE;
16220
16221 }
16222
16223 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16224 {
16225 int channel;
16226 int on;
16227 struct dahdi_pvt *dahdi_chan = NULL;
16228
16229 switch (cmd) {
16230 case CLI_INIT:
16231 e->command = "dahdi set dnd";
16232 e->usage =
16233 "Usage: dahdi set dnd <chan#> <on|off>\n"
16234 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16235 " Changes take effect immediately.\n"
16236 " <chan num> is the channel number\n"
16237 " <on|off> Enable or disable DND mode?\n"
16238 ;
16239 return NULL;
16240 case CLI_GENERATE:
16241 return NULL;
16242 }
16243
16244 if (a->argc != 5)
16245 return CLI_SHOWUSAGE;
16246
16247 if ((channel = atoi(a->argv[3])) <= 0) {
16248 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16249 return CLI_SHOWUSAGE;
16250 }
16251
16252 if (ast_true(a->argv[4]))
16253 on = 1;
16254 else if (ast_false(a->argv[4]))
16255 on = 0;
16256 else {
16257 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16258 return CLI_SHOWUSAGE;
16259 }
16260
16261 ast_mutex_lock(&iflock);
16262 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16263 if (dahdi_chan->channel != channel)
16264 continue;
16265
16266
16267 dahdi_dnd(dahdi_chan, on);
16268 break;
16269 }
16270 ast_mutex_unlock(&iflock);
16271
16272 if (!dahdi_chan) {
16273 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16274 return CLI_FAILURE;
16275 }
16276
16277 return CLI_SUCCESS;
16278 }
16279
16280 static struct ast_cli_entry dahdi_cli[] = {
16281 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16282 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16283 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16284 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16285 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16286 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16287 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16288 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16289 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16290 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16291 };
16292
16293 #define TRANSFER 0
16294 #define HANGUP 1
16295
16296 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16297 {
16298 if (p) {
16299 switch (mode) {
16300 case TRANSFER:
16301 p->fake_event = DAHDI_EVENT_WINKFLASH;
16302 break;
16303 case HANGUP:
16304 p->fake_event = DAHDI_EVENT_ONHOOK;
16305 break;
16306 default:
16307 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, ast_channel_name(p->owner));
16308 }
16309 }
16310 return 0;
16311 }
16312 static struct dahdi_pvt *find_channel(int channel)
16313 {
16314 struct dahdi_pvt *p;
16315
16316 ast_mutex_lock(&iflock);
16317 for (p = iflist; p; p = p->next) {
16318 if (p->channel == channel) {
16319 break;
16320 }
16321 }
16322 ast_mutex_unlock(&iflock);
16323 return p;
16324 }
16325
16326
16327
16328
16329
16330
16331
16332
16333
16334
16335 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16336 {
16337 int chan_num;
16338
16339 if (sscanf(channel, "%30d", &chan_num) != 1) {
16340
16341 return NULL;
16342 }
16343
16344 return find_channel(chan_num);
16345 }
16346
16347 static int action_dahdidndon(struct mansession *s, const struct message *m)
16348 {
16349 struct dahdi_pvt *p;
16350 const char *channel = astman_get_header(m, "DAHDIChannel");
16351
16352 if (ast_strlen_zero(channel)) {
16353 astman_send_error(s, m, "No channel specified");
16354 return 0;
16355 }
16356 p = find_channel_from_str(channel);
16357 if (!p) {
16358 astman_send_error(s, m, "No such channel");
16359 return 0;
16360 }
16361 dahdi_dnd(p, 1);
16362 astman_send_ack(s, m, "DND Enabled");
16363 return 0;
16364 }
16365
16366 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16367 {
16368 struct dahdi_pvt *p;
16369 const char *channel = astman_get_header(m, "DAHDIChannel");
16370
16371 if (ast_strlen_zero(channel)) {
16372 astman_send_error(s, m, "No channel specified");
16373 return 0;
16374 }
16375 p = find_channel_from_str(channel);
16376 if (!p) {
16377 astman_send_error(s, m, "No such channel");
16378 return 0;
16379 }
16380 dahdi_dnd(p, 0);
16381 astman_send_ack(s, m, "DND Disabled");
16382 return 0;
16383 }
16384
16385 static int action_transfer(struct mansession *s, const struct message *m)
16386 {
16387 struct dahdi_pvt *p;
16388 const char *channel = astman_get_header(m, "DAHDIChannel");
16389
16390 if (ast_strlen_zero(channel)) {
16391 astman_send_error(s, m, "No channel specified");
16392 return 0;
16393 }
16394 p = find_channel_from_str(channel);
16395 if (!p) {
16396 astman_send_error(s, m, "No such channel");
16397 return 0;
16398 }
16399 if (!analog_lib_handles(p->sig, 0, 0)) {
16400 astman_send_error(s, m, "Channel signaling is not analog");
16401 return 0;
16402 }
16403 dahdi_fake_event(p,TRANSFER);
16404 astman_send_ack(s, m, "DAHDITransfer");
16405 return 0;
16406 }
16407
16408 static int action_transferhangup(struct mansession *s, const struct message *m)
16409 {
16410 struct dahdi_pvt *p;
16411 const char *channel = astman_get_header(m, "DAHDIChannel");
16412
16413 if (ast_strlen_zero(channel)) {
16414 astman_send_error(s, m, "No channel specified");
16415 return 0;
16416 }
16417 p = find_channel_from_str(channel);
16418 if (!p) {
16419 astman_send_error(s, m, "No such channel");
16420 return 0;
16421 }
16422 if (!analog_lib_handles(p->sig, 0, 0)) {
16423 astman_send_error(s, m, "Channel signaling is not analog");
16424 return 0;
16425 }
16426 dahdi_fake_event(p,HANGUP);
16427 astman_send_ack(s, m, "DAHDIHangup");
16428 return 0;
16429 }
16430
16431 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16432 {
16433 struct dahdi_pvt *p;
16434 const char *channel = astman_get_header(m, "DAHDIChannel");
16435 const char *number = astman_get_header(m, "Number");
16436 int i;
16437
16438 if (ast_strlen_zero(channel)) {
16439 astman_send_error(s, m, "No channel specified");
16440 return 0;
16441 }
16442 if (ast_strlen_zero(number)) {
16443 astman_send_error(s, m, "No number specified");
16444 return 0;
16445 }
16446 p = find_channel_from_str(channel);
16447 if (!p) {
16448 astman_send_error(s, m, "No such channel");
16449 return 0;
16450 }
16451 if (!p->owner) {
16452 astman_send_error(s, m, "Channel does not have it's owner");
16453 return 0;
16454 }
16455 for (i = 0; i < strlen(number); i++) {
16456 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16457 dahdi_queue_frame(p, &f);
16458 }
16459 astman_send_ack(s, m, "DAHDIDialOffhook");
16460 return 0;
16461 }
16462
16463 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16464 {
16465 struct dahdi_pvt *tmp = NULL;
16466 const char *id = astman_get_header(m, "ActionID");
16467 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16468 char idText[256] = "";
16469 int channels = 0;
16470 int dahdichanquery;
16471
16472 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16473
16474 dahdichanquery = -1;
16475 }
16476
16477 astman_send_ack(s, m, "DAHDI channel status will follow");
16478 if (!ast_strlen_zero(id))
16479 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16480
16481 ast_mutex_lock(&iflock);
16482
16483 for (tmp = iflist; tmp; tmp = tmp->next) {
16484 if (tmp->channel > 0) {
16485 int alm;
16486
16487
16488 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16489 continue;
16490
16491 alm = get_alarms(tmp);
16492 channels++;
16493 if (tmp->owner) {
16494
16495 astman_append(s,
16496 "Event: DAHDIShowChannels\r\n"
16497 "DAHDIChannel: %d\r\n"
16498 "Channel: %s\r\n"
16499 "Uniqueid: %s\r\n"
16500 "AccountCode: %s\r\n"
16501 "Signalling: %s\r\n"
16502 "SignallingCode: %d\r\n"
16503 "Context: %s\r\n"
16504 "DND: %s\r\n"
16505 "Alarm: %s\r\n"
16506 "Description: %s\r\n"
16507 "%s"
16508 "\r\n",
16509 tmp->channel,
16510 ast_channel_name(tmp->owner),
16511 ast_channel_uniqueid(tmp->owner),
16512 ast_channel_accountcode(tmp->owner),
16513 sig2str(tmp->sig),
16514 tmp->sig,
16515 tmp->context,
16516 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16517 alarm2str(alm),
16518 tmp->description, idText);
16519 } else {
16520 astman_append(s,
16521 "Event: DAHDIShowChannels\r\n"
16522 "DAHDIChannel: %d\r\n"
16523 "Signalling: %s\r\n"
16524 "SignallingCode: %d\r\n"
16525 "Context: %s\r\n"
16526 "DND: %s\r\n"
16527 "Alarm: %s\r\n"
16528 "Description: %s\r\n"
16529 "%s"
16530 "\r\n",
16531 tmp->channel, sig2str(tmp->sig), tmp->sig,
16532 tmp->context,
16533 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16534 alarm2str(alm),
16535 tmp->description, idText);
16536 }
16537 }
16538 }
16539
16540 ast_mutex_unlock(&iflock);
16541
16542 astman_append(s,
16543 "Event: DAHDIShowChannelsComplete\r\n"
16544 "%s"
16545 "Items: %d\r\n"
16546 "\r\n",
16547 idText,
16548 channels);
16549 return 0;
16550 }
16551
16552 #if defined(HAVE_PRI)
16553 static int action_prishowspans(struct mansession *s, const struct message *m)
16554 {
16555 int count;
16556 int idx;
16557 int span_query;
16558 struct dahdi_pri *dspan;
16559 const char *id = astman_get_header(m, "ActionID");
16560 const char *span_str = astman_get_header(m, "Span");
16561 char action_id[256];
16562 const char *show_cmd = "PRIShowSpans";
16563
16564
16565 if (!ast_strlen_zero(span_str)) {
16566 span_query = atoi(span_str);
16567 } else {
16568 span_query = 0;
16569 }
16570
16571 if (!ast_strlen_zero(id)) {
16572 snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16573 } else {
16574 action_id[0] = '\0';
16575 }
16576
16577 astman_send_ack(s, m, "Span status will follow");
16578
16579 count = 0;
16580 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16581 dspan = &pris[idx];
16582
16583
16584 if (0 < span_query && dspan->pri.span != span_query) {
16585 continue;
16586 }
16587
16588 if (dspan->pri.pri) {
16589 count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16590 action_id);
16591 }
16592 }
16593
16594 astman_append(s,
16595 "Event: %sComplete\r\n"
16596 "Items: %d\r\n"
16597 "%s"
16598 "\r\n",
16599 show_cmd,
16600 count,
16601 action_id);
16602 return 0;
16603 }
16604 #endif
16605
16606 #if defined(HAVE_SS7)
16607 static int linkset_addsigchan(int sigchan)
16608 {
16609 struct dahdi_ss7 *link;
16610 int res;
16611 int curfd;
16612 struct dahdi_params params;
16613 struct dahdi_bufferinfo bi;
16614 struct dahdi_spaninfo si;
16615
16616 if (sigchan < 0) {
16617 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16618 return -1;
16619 }
16620 if (cur_ss7type < 0) {
16621 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16622 return -1;
16623 }
16624 if (cur_pointcode < 0) {
16625 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16626 return -1;
16627 }
16628 if (cur_adjpointcode < 0) {
16629 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16630 return -1;
16631 }
16632 if (cur_defaultdpc < 0) {
16633 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16634 return -1;
16635 }
16636 if (cur_networkindicator < 0) {
16637 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16638 return -1;
16639 }
16640 link = ss7_resolve_linkset(cur_linkset);
16641 if (!link) {
16642 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16643 return -1;
16644 }
16645 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16646 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16647 return -1;
16648 }
16649
16650 curfd = link->ss7.numsigchans;
16651
16652
16653 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16654 if (link->ss7.fds[curfd] < 0) {
16655 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16656 strerror(errno));
16657 return -1;
16658 }
16659 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16660 dahdi_close_ss7_fd(link, curfd);
16661 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16662 strerror(errno));
16663 return -1;
16664 }
16665
16666
16667 memset(¶ms, 0, sizeof(params));
16668 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16669 if (res) {
16670 dahdi_close_ss7_fd(link, curfd);
16671 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16672 strerror(errno));
16673 return -1;
16674 }
16675 if (params.sigtype != DAHDI_SIG_HDLCFCS
16676 && params.sigtype != DAHDI_SIG_HARDHDLC
16677 && params.sigtype != DAHDI_SIG_MTP2) {
16678 dahdi_close_ss7_fd(link, curfd);
16679 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16680 return -1;
16681 }
16682
16683
16684 memset(&bi, 0, sizeof(bi));
16685 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16686 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16687 bi.numbufs = 32;
16688 bi.bufsize = 512;
16689 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16690 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16691 sigchan, strerror(errno));
16692 dahdi_close_ss7_fd(link, curfd);
16693 return -1;
16694 }
16695
16696
16697 memset(&si, 0, sizeof(si));
16698 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16699 if (res) {
16700 dahdi_close_ss7_fd(link, curfd);
16701 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16702 strerror(errno));
16703 }
16704
16705 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16706 (params.sigtype == DAHDI_SIG_MTP2)
16707 ? SS7_TRANSPORT_DAHDIMTP2
16708 : SS7_TRANSPORT_DAHDIDCHAN,
16709 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16710 if (res) {
16711 dahdi_close_ss7_fd(link, curfd);
16712 return -1;
16713 }
16714
16715 ++link->ss7.numsigchans;
16716
16717 return 0;
16718 }
16719 #endif
16720
16721 #if defined(HAVE_SS7)
16722 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16723 {
16724 int span;
16725 switch (cmd) {
16726 case CLI_INIT:
16727 e->command = "ss7 set debug {on|off} linkset";
16728 e->usage =
16729 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16730 " Enables debugging on a given SS7 linkset\n";
16731 return NULL;
16732 case CLI_GENERATE:
16733 return NULL;
16734 }
16735 if (a->argc < 6)
16736 return CLI_SHOWUSAGE;
16737 span = atoi(a->argv[5]);
16738 if ((span < 1) || (span > NUM_SPANS)) {
16739 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16740 return CLI_SUCCESS;
16741 }
16742 if (!linksets[span-1].ss7.ss7) {
16743 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16744 } else {
16745 if (!strcasecmp(a->argv[3], "on")) {
16746 linksets[span - 1].ss7.debug = 1;
16747 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16748 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16749 } else {
16750 linksets[span - 1].ss7.debug = 0;
16751 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16752 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16753 }
16754 }
16755
16756 return CLI_SUCCESS;
16757 }
16758 #endif
16759
16760 #if defined(HAVE_SS7)
16761 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16762 {
16763 int linkset, cic;
16764 int blocked = -1, i;
16765 switch (cmd) {
16766 case CLI_INIT:
16767 e->command = "ss7 block cic";
16768 e->usage =
16769 "Usage: ss7 block cic <linkset> <CIC>\n"
16770 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16771 return NULL;
16772 case CLI_GENERATE:
16773 return NULL;
16774 }
16775 if (a->argc == 5)
16776 linkset = atoi(a->argv[3]);
16777 else
16778 return CLI_SHOWUSAGE;
16779
16780 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16781 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16782 return CLI_SUCCESS;
16783 }
16784
16785 if (!linksets[linkset-1].ss7.ss7) {
16786 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16787 return CLI_SUCCESS;
16788 }
16789
16790 cic = atoi(a->argv[4]);
16791
16792 if (cic < 1) {
16793 ast_cli(a->fd, "Invalid CIC specified!\n");
16794 return CLI_SUCCESS;
16795 }
16796
16797 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16798 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16799 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16800 if (!blocked) {
16801 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16802 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16803 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16804 }
16805 }
16806 }
16807
16808 if (blocked < 0) {
16809 ast_cli(a->fd, "Invalid CIC specified!\n");
16810 return CLI_SUCCESS;
16811 }
16812
16813 if (!blocked)
16814 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16815 else
16816 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16817
16818
16819 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16820
16821 return CLI_SUCCESS;
16822 }
16823 #endif
16824
16825 #if defined(HAVE_SS7)
16826 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16827 {
16828 int linkset;
16829 int i;
16830 switch (cmd) {
16831 case CLI_INIT:
16832 e->command = "ss7 block linkset";
16833 e->usage =
16834 "Usage: ss7 block linkset <linkset number>\n"
16835 " Sends a remote blocking request for all CICs on the given linkset\n";
16836 return NULL;
16837 case CLI_GENERATE:
16838 return NULL;
16839 }
16840 if (a->argc == 4)
16841 linkset = atoi(a->argv[3]);
16842 else
16843 return CLI_SHOWUSAGE;
16844
16845 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16846 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16847 return CLI_SUCCESS;
16848 }
16849
16850 if (!linksets[linkset-1].ss7.ss7) {
16851 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16852 return CLI_SUCCESS;
16853 }
16854
16855 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16856 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16857 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16858 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16859 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16860 }
16861
16862
16863 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16864
16865 return CLI_SUCCESS;
16866 }
16867 #endif
16868
16869 #if defined(HAVE_SS7)
16870 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16871 {
16872 int linkset, cic;
16873 int i, blocked = -1;
16874 switch (cmd) {
16875 case CLI_INIT:
16876 e->command = "ss7 unblock cic";
16877 e->usage =
16878 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16879 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16880 return NULL;
16881 case CLI_GENERATE:
16882 return NULL;
16883 }
16884
16885 if (a->argc == 5)
16886 linkset = atoi(a->argv[3]);
16887 else
16888 return CLI_SHOWUSAGE;
16889
16890 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16891 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16892 return CLI_SUCCESS;
16893 }
16894
16895 if (!linksets[linkset-1].ss7.ss7) {
16896 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16897 return CLI_SUCCESS;
16898 }
16899
16900 cic = atoi(a->argv[4]);
16901
16902 if (cic < 1) {
16903 ast_cli(a->fd, "Invalid CIC specified!\n");
16904 return CLI_SUCCESS;
16905 }
16906
16907 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16908 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16909 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16910 if (blocked) {
16911 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16912 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16913 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16914 }
16915 }
16916 }
16917
16918 if (blocked > 0)
16919 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16920
16921
16922 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16923
16924 return CLI_SUCCESS;
16925 }
16926 #endif
16927
16928 #if defined(HAVE_SS7)
16929 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16930 {
16931 int linkset;
16932 int i;
16933 switch (cmd) {
16934 case CLI_INIT:
16935 e->command = "ss7 unblock linkset";
16936 e->usage =
16937 "Usage: ss7 unblock linkset <linkset number>\n"
16938 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16939 return NULL;
16940 case CLI_GENERATE:
16941 return NULL;
16942 }
16943
16944 if (a->argc == 4)
16945 linkset = atoi(a->argv[3]);
16946 else
16947 return CLI_SHOWUSAGE;
16948
16949 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16950 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16951 return CLI_SUCCESS;
16952 }
16953
16954 if (!linksets[linkset-1].ss7.ss7) {
16955 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16956 return CLI_SUCCESS;
16957 }
16958
16959 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16960 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16961 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16962 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16963 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16964 }
16965
16966
16967 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16968
16969 return CLI_SUCCESS;
16970 }
16971 #endif
16972
16973 #if defined(HAVE_SS7)
16974 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16975 {
16976 int linkset;
16977 struct sig_ss7_linkset *ss7;
16978 switch (cmd) {
16979 case CLI_INIT:
16980 e->command = "ss7 show linkset";
16981 e->usage =
16982 "Usage: ss7 show linkset <span>\n"
16983 " Shows the status of an SS7 linkset.\n";
16984 return NULL;
16985 case CLI_GENERATE:
16986 return NULL;
16987 }
16988
16989 if (a->argc < 4)
16990 return CLI_SHOWUSAGE;
16991 linkset = atoi(a->argv[3]);
16992 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16993 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16994 return CLI_SUCCESS;
16995 }
16996 ss7 = &linksets[linkset - 1].ss7;
16997 if (!ss7->ss7) {
16998 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16999 return CLI_SUCCESS;
17000 }
17001
17002 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17003
17004 return CLI_SUCCESS;
17005 }
17006 #endif
17007
17008 #if defined(HAVE_SS7)
17009 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17010 {
17011 int linkset;
17012
17013 switch (cmd) {
17014 case CLI_INIT:
17015 e->command = "ss7 show channels";
17016 e->usage =
17017 "Usage: ss7 show channels\n"
17018 " Displays SS7 channel information at a glance.\n";
17019 return NULL;
17020 case CLI_GENERATE:
17021 return NULL;
17022 }
17023
17024 if (a->argc != 3)
17025 return CLI_SHOWUSAGE;
17026
17027 sig_ss7_cli_show_channels_header(a->fd);
17028 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17029 if (linksets[linkset].ss7.ss7) {
17030 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17031 }
17032 }
17033 return CLI_SUCCESS;
17034 }
17035 #endif
17036
17037 #if defined(HAVE_SS7)
17038 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17039 {
17040 switch (cmd) {
17041 case CLI_INIT:
17042 e->command = "ss7 show version";
17043 e->usage =
17044 "Usage: ss7 show version\n"
17045 " Show the libss7 version\n";
17046 return NULL;
17047 case CLI_GENERATE:
17048 return NULL;
17049 }
17050
17051 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17052
17053 return CLI_SUCCESS;
17054 }
17055 #endif
17056
17057 #if defined(HAVE_SS7)
17058 static struct ast_cli_entry dahdi_ss7_cli[] = {
17059 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17060 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
17061 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
17062 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
17063 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
17064 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17065 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17066 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17067 };
17068 #endif
17069
17070 #if defined(HAVE_PRI)
17071 #if defined(HAVE_PRI_CCSS)
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084
17085
17086
17087
17088
17089 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17090 {
17091 struct dahdi_pvt *pvt;
17092 struct sig_pri_chan *pvt_chan;
17093 int res;
17094
17095 ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17096
17097 pvt = ast_channel_tech_pvt(chan);
17098 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17099 pvt_chan = pvt->sig_pvt;
17100 } else {
17101 pvt_chan = NULL;
17102 }
17103 if (!pvt_chan) {
17104 return -1;
17105 }
17106
17107 ast_module_ref(ast_module_info->self);
17108
17109 res = sig_pri_cc_agent_init(agent, pvt_chan);
17110 if (res) {
17111 ast_module_unref(ast_module_info->self);
17112 }
17113 return res;
17114 }
17115 #endif
17116 #endif
17117
17118 #if defined(HAVE_PRI)
17119 #if defined(HAVE_PRI_CCSS)
17120
17121
17122
17123
17124
17125
17126
17127
17128
17129
17130
17131
17132
17133 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17134 {
17135 sig_pri_cc_agent_destructor(agent);
17136
17137 ast_module_unref(ast_module_info->self);
17138 }
17139 #endif
17140 #endif
17141
17142 #if defined(HAVE_PRI)
17143 #if defined(HAVE_PRI_CCSS)
17144 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17145 .type = dahdi_pri_cc_type,
17146 .init = dahdi_pri_cc_agent_init,
17147 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17148 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17149 .respond = sig_pri_cc_agent_req_rsp,
17150 .status_request = sig_pri_cc_agent_status_req,
17151 .stop_ringing = sig_pri_cc_agent_stop_ringing,
17152 .party_b_free = sig_pri_cc_agent_party_b_free,
17153 .start_monitoring = sig_pri_cc_agent_start_monitoring,
17154 .callee_available = sig_pri_cc_agent_callee_available,
17155 .destructor = dahdi_pri_cc_agent_destructor,
17156 };
17157 #endif
17158 #endif
17159
17160 #if defined(HAVE_PRI)
17161 #if defined(HAVE_PRI_CCSS)
17162 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17163 .type = dahdi_pri_cc_type,
17164 .request_cc = sig_pri_cc_monitor_req_cc,
17165 .suspend = sig_pri_cc_monitor_suspend,
17166 .unsuspend = sig_pri_cc_monitor_unsuspend,
17167 .status_response = sig_pri_cc_monitor_status_rsp,
17168 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17169 .destructor = sig_pri_cc_monitor_destructor,
17170 };
17171 #endif
17172 #endif
17173
17174 static int __unload_module(void)
17175 {
17176 struct dahdi_pvt *p;
17177 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17178 int i, j;
17179 #endif
17180
17181 #ifdef HAVE_PRI
17182 for (i = 0; i < NUM_SPANS; i++) {
17183 if (pris[i].pri.master != AST_PTHREADT_NULL) {
17184 pthread_cancel(pris[i].pri.master);
17185 pthread_kill(pris[i].pri.master, SIGURG);
17186 }
17187 }
17188 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17189 ast_unregister_application(dahdi_send_keypad_facility_app);
17190 #ifdef HAVE_PRI_PROG_W_CAUSE
17191 ast_unregister_application(dahdi_send_callrerouting_facility_app);
17192 #endif
17193 #endif
17194 #if defined(HAVE_SS7)
17195 for (i = 0; i < NUM_SPANS; i++) {
17196 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17197 pthread_cancel(linksets[i].ss7.master);
17198 pthread_kill(linksets[i].ss7.master, SIGURG);
17199 }
17200 }
17201 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17202 #endif
17203 #if defined(HAVE_OPENR2)
17204 dahdi_r2_destroy_links();
17205 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17206 ast_unregister_application(dahdi_accept_r2_call_app);
17207 #endif
17208
17209 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17210 ast_manager_unregister("DAHDIDialOffhook");
17211 ast_manager_unregister("DAHDIHangup");
17212 ast_manager_unregister("DAHDITransfer");
17213 ast_manager_unregister("DAHDIDNDoff");
17214 ast_manager_unregister("DAHDIDNDon");
17215 ast_manager_unregister("DAHDIShowChannels");
17216 ast_manager_unregister("DAHDIRestart");
17217 #if defined(HAVE_PRI)
17218 ast_manager_unregister("PRIShowSpans");
17219 #endif
17220 ast_data_unregister(NULL);
17221 ast_channel_unregister(&dahdi_tech);
17222
17223
17224 ast_mutex_lock(&iflock);
17225 for (p = iflist; p; p = p->next) {
17226 if (p->owner)
17227 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
17228 }
17229 ast_mutex_unlock(&iflock);
17230
17231 ast_mutex_lock(&monlock);
17232 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
17233 pthread_cancel(monitor_thread);
17234 pthread_kill(monitor_thread, SIGURG);
17235 pthread_join(monitor_thread, NULL);
17236 }
17237 monitor_thread = AST_PTHREADT_STOP;
17238 ast_mutex_unlock(&monlock);
17239
17240 destroy_all_channels();
17241
17242 #if defined(HAVE_PRI)
17243 for (i = 0; i < NUM_SPANS; i++) {
17244 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17245 pthread_join(pris[i].pri.master, NULL);
17246 }
17247 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17248 dahdi_close_pri_fd(&(pris[i]), j);
17249 }
17250 sig_pri_stop_pri(&pris[i].pri);
17251 }
17252 #if defined(HAVE_PRI_CCSS)
17253 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17254 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17255 #endif
17256 sig_pri_unload();
17257 #endif
17258
17259 #if defined(HAVE_SS7)
17260 for (i = 0; i < NUM_SPANS; i++) {
17261 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17262 pthread_join(linksets[i].ss7.master, NULL);
17263 }
17264 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17265 dahdi_close_ss7_fd(&(linksets[i]), j);
17266 }
17267 }
17268 #endif
17269 ast_cond_destroy(&ss_thread_complete);
17270
17271 dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
17272 return 0;
17273 }
17274
17275 static int unload_module(void)
17276 {
17277 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17278 int y;
17279 #endif
17280 #ifdef HAVE_PRI
17281 for (y = 0; y < NUM_SPANS; y++)
17282 ast_mutex_destroy(&pris[y].pri.lock);
17283 #endif
17284 #if defined(HAVE_SS7)
17285 for (y = 0; y < NUM_SPANS; y++)
17286 ast_mutex_destroy(&linksets[y].ss7.lock);
17287 #endif
17288 return __unload_module();
17289 }
17290
17291 static void string_replace(char *str, int char1, int char2)
17292 {
17293 for (; *str; str++) {
17294 if (*str == char1) {
17295 *str = char2;
17296 }
17297 }
17298 }
17299
17300 static char *parse_spanchan(char *chanstr, char **subdir)
17301 {
17302 char *p;
17303
17304 if ((p = strrchr(chanstr, '!')) == NULL) {
17305 *subdir = NULL;
17306 return chanstr;
17307 }
17308 *p++ = '\0';
17309 string_replace(chanstr, '!', '/');
17310 *subdir = chanstr;
17311 return p;
17312 }
17313
17314 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
17315 {
17316 char *c, *chan;
17317 char *subdir;
17318 int x, start, finish;
17319 struct dahdi_pvt *tmp;
17320
17321 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17322 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17323 return -1;
17324 }
17325
17326 c = ast_strdupa(value);
17327 c = parse_spanchan(c, &subdir);
17328
17329 while ((chan = strsep(&c, ","))) {
17330 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17331
17332 } else if (sscanf(chan, "%30d", &start)) {
17333
17334 finish = start;
17335 } else if (!strcasecmp(chan, "pseudo")) {
17336 finish = start = CHAN_PSEUDO;
17337 if (found_pseudo)
17338 *found_pseudo = 1;
17339 } else {
17340 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17341 return -1;
17342 }
17343 if (finish < start) {
17344 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17345 x = finish;
17346 finish = start;
17347 start = x;
17348 }
17349
17350 for (x = start; x <= finish; x++) {
17351 char fn[PATH_MAX];
17352 int real_channel = x;
17353
17354 if (!ast_strlen_zero(subdir)) {
17355 real_channel = device2chan(subdir, x, fn, sizeof(fn));
17356 if (real_channel < 0) {
17357 if (conf->ignore_failed_channels) {
17358 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17359 subdir, x, real_channel);
17360 continue;
17361 } else {
17362 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17363 subdir, x, real_channel);
17364 return -1;
17365 }
17366 }
17367 }
17368 tmp = mkintf(real_channel, conf, reload);
17369
17370 if (tmp) {
17371 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17372 } else {
17373 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17374 (reload == 1) ? "reconfigure" : "register", value);
17375 return -1;
17376 }
17377 }
17378 }
17379
17380 return 0;
17381 }
17382
17383
17384
17385 #define MAX_CHANLIST_LEN 80
17386
17387 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17388 {
17389 char *parse = ast_strdupa(data);
17390 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17391 unsigned int param_count;
17392 unsigned int x;
17393
17394 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17395 return;
17396
17397 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17398
17399
17400
17401 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17402
17403 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17404 confp->chan.echocancel.head.tap_length = x;
17405 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17406 confp->chan.echocancel.head.tap_length = 128;
17407
17408
17409
17410 for (x = 1; x < param_count; x++) {
17411 struct {
17412 char *name;
17413 char *value;
17414 } param;
17415
17416 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
17417 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, params[x]);
17418 continue;
17419 }
17420
17421 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17422 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %u: '%s'\n", line, param.name);
17423 continue;
17424 }
17425
17426 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17427
17428 if (param.value) {
17429 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17430 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %u: '%s'\n", line, param.value);
17431 continue;
17432 }
17433 }
17434 confp->chan.echocancel.head.param_count++;
17435 }
17436 }
17437
17438 #if defined(HAVE_PRI)
17439 #if defined(HAVE_PRI_DISPLAY_TEXT)
17440
17441
17442
17443
17444
17445
17446
17447
17448
17449 static unsigned long dahdi_display_text_option(const char *value)
17450 {
17451 char *val_str;
17452 char *opt_str;
17453 unsigned long options;
17454
17455 options = 0;
17456 val_str = ast_strdupa(value);
17457
17458 for (;;) {
17459 opt_str = strsep(&val_str, ",");
17460 if (!opt_str) {
17461 break;
17462 }
17463 opt_str = ast_strip(opt_str);
17464 if (!*opt_str) {
17465 continue;
17466 }
17467
17468 if (!strcasecmp(opt_str, "block")) {
17469 options |= PRI_DISPLAY_OPTION_BLOCK;
17470 } else if (!strcasecmp(opt_str, "name_initial")) {
17471 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17472 } else if (!strcasecmp(opt_str, "name_update")) {
17473 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17474 } else if (!strcasecmp(opt_str, "name")) {
17475 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17476 } else if (!strcasecmp(opt_str, "text")) {
17477 options |= PRI_DISPLAY_OPTION_TEXT;
17478 }
17479 }
17480 return options;
17481 }
17482 #endif
17483 #endif
17484
17485 #if defined(HAVE_PRI)
17486 #if defined(HAVE_PRI_DATETIME_SEND)
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496 static int dahdi_datetime_send_option(const char *value)
17497 {
17498 int option;
17499
17500 option = PRI_DATE_TIME_SEND_DEFAULT;
17501
17502 if (ast_false(value)) {
17503 option = PRI_DATE_TIME_SEND_NO;
17504 } else if (!strcasecmp(value, "date")) {
17505 option = PRI_DATE_TIME_SEND_DATE;
17506 } else if (!strcasecmp(value, "date_hh")) {
17507 option = PRI_DATE_TIME_SEND_DATE_HH;
17508 } else if (!strcasecmp(value, "date_hhmm")) {
17509 option = PRI_DATE_TIME_SEND_DATE_HHMM;
17510 } else if (!strcasecmp(value, "date_hhmmss")) {
17511 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17512 }
17513
17514 return option;
17515 }
17516 #endif
17517 #endif
17518
17519
17520 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17521
17522 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17523
17524 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17525 {
17526 int count_pattern = 0;
17527 int norval = 0;
17528 char *temp = NULL;
17529
17530 for (; ;) {
17531
17532 if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
17533 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17534 break;
17535 }
17536
17537 busy_cadence->pattern[count_pattern] = norval;
17538
17539 count_pattern++;
17540 if (count_pattern == 4) {
17541 break;
17542 }
17543
17544 temp = strchr(v->value, ',');
17545 if (temp == NULL) {
17546 break;
17547 }
17548 v->value = temp + 1;
17549 }
17550 busy_cadence->length = count_pattern;
17551
17552 if (count_pattern % 2 != 0) {
17553
17554 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17555 }
17556
17557 }
17558
17559 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17560 {
17561 struct dahdi_pvt *tmp;
17562 int y;
17563 int found_pseudo = 0;
17564 struct ast_variable *dahdichan = NULL;
17565
17566 for (; v; v = v->next) {
17567 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17568 continue;
17569
17570
17571 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17572 if (options & PROC_DAHDI_OPT_NOCHAN) {
17573 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17574 continue;
17575 }
17576 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17577 if (confp->ignore_failed_channels) {
17578 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17579 continue;
17580 } else {
17581 return -1;
17582 }
17583 }
17584 ast_debug(1, "Channel '%s' configured.\n", v->value);
17585 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17586 confp->ignore_failed_channels = ast_true(v->value);
17587 } else if (!strcasecmp(v->name, "buffers")) {
17588 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17589 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17590 confp->chan.buf_no = numbufs;
17591 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17592 }
17593 } else if (!strcasecmp(v->name, "faxbuffers")) {
17594 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17595 confp->chan.usefaxbuffers = 1;
17596 }
17597 } else if (!strcasecmp(v->name, "dahdichan")) {
17598
17599 dahdichan = v;
17600 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17601 usedistinctiveringdetection = ast_true(v->value);
17602 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17603 distinctiveringaftercid = ast_true(v->value);
17604 } else if (!strcasecmp(v->name, "dring1context")) {
17605 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17606 } else if (!strcasecmp(v->name, "dring2context")) {
17607 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17608 } else if (!strcasecmp(v->name, "dring3context")) {
17609 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17610 } else if (!strcasecmp(v->name, "dring1range")) {
17611 confp->chan.drings.ringnum[0].range = atoi(v->value);
17612 } else if (!strcasecmp(v->name, "dring2range")) {
17613 confp->chan.drings.ringnum[1].range = atoi(v->value);
17614 } else if (!strcasecmp(v->name, "dring3range")) {
17615 confp->chan.drings.ringnum[2].range = atoi(v->value);
17616 } else if (!strcasecmp(v->name, "dring1")) {
17617 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]);
17618 } else if (!strcasecmp(v->name, "dring2")) {
17619 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]);
17620 } else if (!strcasecmp(v->name, "dring3")) {
17621 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]);
17622 } else if (!strcasecmp(v->name, "usecallerid")) {
17623 confp->chan.use_callerid = ast_true(v->value);
17624 } else if (!strcasecmp(v->name, "cidsignalling")) {
17625 if (!strcasecmp(v->value, "bell"))
17626 confp->chan.cid_signalling = CID_SIG_BELL;
17627 else if (!strcasecmp(v->value, "v23"))
17628 confp->chan.cid_signalling = CID_SIG_V23;
17629 else if (!strcasecmp(v->value, "dtmf"))
17630 confp->chan.cid_signalling = CID_SIG_DTMF;
17631 else if (!strcasecmp(v->value, "smdi"))
17632 confp->chan.cid_signalling = CID_SIG_SMDI;
17633 else if (!strcasecmp(v->value, "v23_jp"))
17634 confp->chan.cid_signalling = CID_SIG_V23_JP;
17635 else if (ast_true(v->value))
17636 confp->chan.cid_signalling = CID_SIG_BELL;
17637 } else if (!strcasecmp(v->name, "cidstart")) {
17638 if (!strcasecmp(v->value, "ring"))
17639 confp->chan.cid_start = CID_START_RING;
17640 else if (!strcasecmp(v->value, "polarity_in"))
17641 confp->chan.cid_start = CID_START_POLARITY_IN;
17642 else if (!strcasecmp(v->value, "polarity"))
17643 confp->chan.cid_start = CID_START_POLARITY;
17644 else if (!strcasecmp(v->value, "dtmf"))
17645 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17646 else if (ast_true(v->value))
17647 confp->chan.cid_start = CID_START_RING;
17648 } else if (!strcasecmp(v->name, "threewaycalling")) {
17649 confp->chan.threewaycalling = ast_true(v->value);
17650 } else if (!strcasecmp(v->name, "cancallforward")) {
17651 confp->chan.cancallforward = ast_true(v->value);
17652 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17653 if (ast_true(v->value))
17654 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17655 else
17656 confp->chan.dtmfrelax = 0;
17657 } else if (!strcasecmp(v->name, "mailbox")) {
17658 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17659 } else if (!strcasecmp(v->name, "description")) {
17660 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
17661 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17662 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17663 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17664 }
17665 } else if (!strcasecmp(v->name, "adsi")) {
17666 confp->chan.adsi = ast_true(v->value);
17667 } else if (!strcasecmp(v->name, "usesmdi")) {
17668 confp->chan.use_smdi = ast_true(v->value);
17669 } else if (!strcasecmp(v->name, "smdiport")) {
17670 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17671 } else if (!strcasecmp(v->name, "transfer")) {
17672 confp->chan.transfer = ast_true(v->value);
17673 } else if (!strcasecmp(v->name, "canpark")) {
17674 confp->chan.canpark = ast_true(v->value);
17675 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17676 confp->chan.echocanbridged = ast_true(v->value);
17677 } else if (!strcasecmp(v->name, "busydetect")) {
17678 confp->chan.busydetect = ast_true(v->value);
17679 } else if (!strcasecmp(v->name, "busycount")) {
17680 confp->chan.busycount = atoi(v->value);
17681 } else if (!strcasecmp(v->name, "busypattern")) {
17682 parse_busy_pattern(v, &confp->chan.busy_cadence);
17683 } else if (!strcasecmp(v->name, "callprogress")) {
17684 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17685 if (ast_true(v->value))
17686 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17687 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17688 confp->chan.waitfordialtone = atoi(v->value);
17689 } else if (!strcasecmp(v->name, "dialtone_detect")) {
17690 if (!strcasecmp(v->value, "always")) {
17691 confp->chan.dialtone_detect = -1;
17692 } else if (ast_true(v->value)) {
17693 confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
17694 } else if (ast_false(v->value)) {
17695 confp->chan.dialtone_detect = 0;
17696 } else {
17697 confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
17698 }
17699 } else if (!strcasecmp(v->name, "faxdetect")) {
17700 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17701 if (!strcasecmp(v->value, "incoming")) {
17702 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17703 } else if (!strcasecmp(v->value, "outgoing")) {
17704 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17705 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17706 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17707 } else if (!strcasecmp(v->name, "echocancel")) {
17708 process_echocancel(confp, v->value, v->lineno);
17709 } else if (!strcasecmp(v->name, "echotraining")) {
17710 if (sscanf(v->value, "%30d", &y) == 1) {
17711 if ((y < 10) || (y > 4000)) {
17712 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17713 } else {
17714 confp->chan.echotraining = y;
17715 }
17716 } else if (ast_true(v->value)) {
17717 confp->chan.echotraining = 400;
17718 } else
17719 confp->chan.echotraining = 0;
17720 } else if (!strcasecmp(v->name, "hidecallerid")) {
17721 confp->chan.hidecallerid = ast_true(v->value);
17722 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17723 confp->chan.hidecalleridname = ast_true(v->value);
17724 } else if (!strcasecmp(v->name, "pulsedial")) {
17725 confp->chan.pulse = ast_true(v->value);
17726 } else if (!strcasecmp(v->name, "callreturn")) {
17727 confp->chan.callreturn = ast_true(v->value);
17728 } else if (!strcasecmp(v->name, "callwaiting")) {
17729 confp->chan.callwaiting = ast_true(v->value);
17730 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17731 confp->chan.callwaitingcallerid = ast_true(v->value);
17732 } else if (!strcasecmp(v->name, "context")) {
17733 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17734 } else if (!strcasecmp(v->name, "language")) {
17735 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17736 } else if (!strcasecmp(v->name, "progzone")) {
17737 ast_copy_string(progzone, v->value, sizeof(progzone));
17738 } else if (!strcasecmp(v->name, "mohinterpret")
17739 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17740 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17741 } else if (!strcasecmp(v->name, "mohsuggest")) {
17742 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17743 } else if (!strcasecmp(v->name, "parkinglot")) {
17744 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17745 } else if (!strcasecmp(v->name, "stripmsd")) {
17746 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17747 confp->chan.stripmsd = atoi(v->value);
17748 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17749 numbufs = atoi(v->value);
17750 } else if (!strcasecmp(v->name, "group")) {
17751 confp->chan.group = ast_get_group(v->value);
17752 } else if (!strcasecmp(v->name, "callgroup")) {
17753 if (!strcasecmp(v->value, "none"))
17754 confp->chan.callgroup = 0;
17755 else
17756 confp->chan.callgroup = ast_get_group(v->value);
17757 } else if (!strcasecmp(v->name, "pickupgroup")) {
17758 if (!strcasecmp(v->value, "none"))
17759 confp->chan.pickupgroup = 0;
17760 else
17761 confp->chan.pickupgroup = ast_get_group(v->value);
17762 } else if (!strcasecmp(v->name, "namedcallgroup")) {
17763 confp->chan.named_callgroups = ast_get_namedgroups(v->value);
17764 } else if (!strcasecmp(v->name, "namedpickupgroup")) {
17765 confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
17766 } else if (!strcasecmp(v->name, "setvar")) {
17767 char *varname = ast_strdupa(v->value), *varval = NULL;
17768 struct ast_variable *tmpvar;
17769 if (varname && (varval = strchr(varname, '='))) {
17770 *varval++ = '\0';
17771 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17772 tmpvar->next = confp->chan.vars;
17773 confp->chan.vars = tmpvar;
17774 }
17775 }
17776 } else if (!strcasecmp(v->name, "immediate")) {
17777 confp->chan.immediate = ast_true(v->value);
17778 } else if (!strcasecmp(v->name, "transfertobusy")) {
17779 confp->chan.transfertobusy = ast_true(v->value);
17780 } else if (!strcasecmp(v->name, "mwimonitor")) {
17781 confp->chan.mwimonitor_neon = 0;
17782 confp->chan.mwimonitor_fsk = 0;
17783 confp->chan.mwimonitor_rpas = 0;
17784 if (strcasestr(v->value, "fsk")) {
17785 confp->chan.mwimonitor_fsk = 1;
17786 }
17787 if (strcasestr(v->value, "rpas")) {
17788 confp->chan.mwimonitor_rpas = 1;
17789 }
17790 if (strcasestr(v->value, "neon")) {
17791 confp->chan.mwimonitor_neon = 1;
17792 }
17793
17794 if (ast_true(v->value)) {
17795 confp->chan.mwimonitor_fsk = 1;
17796 }
17797 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17798 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17799 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17800 }
17801 } else if (!strcasecmp(v->name, "rxgain")) {
17802 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17803 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17804 }
17805 } else if (!strcasecmp(v->name, "txgain")) {
17806 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17807 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17808 }
17809 } else if (!strcasecmp(v->name, "txdrc")) {
17810 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17811 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17812 }
17813 } else if (!strcasecmp(v->name, "rxdrc")) {
17814 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17815 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17816 }
17817 } else if (!strcasecmp(v->name, "tonezone")) {
17818 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17819 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17820 }
17821 } else if (!strcasecmp(v->name, "callerid")) {
17822 if (!strcasecmp(v->value, "asreceived")) {
17823 confp->chan.cid_num[0] = '\0';
17824 confp->chan.cid_name[0] = '\0';
17825 } else {
17826 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17827 }
17828 } else if (!strcasecmp(v->name, "fullname")) {
17829 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17830 } else if (!strcasecmp(v->name, "cid_number")) {
17831 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17832 } else if (!strcasecmp(v->name, "cid_tag")) {
17833 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17834 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17835 confp->chan.dahditrcallerid = ast_true(v->value);
17836 } else if (!strcasecmp(v->name, "restrictcid")) {
17837 confp->chan.restrictcid = ast_true(v->value);
17838 } else if (!strcasecmp(v->name, "usecallingpres")) {
17839 confp->chan.use_callingpres = ast_true(v->value);
17840 } else if (!strcasecmp(v->name, "accountcode")) {
17841 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17842 } else if (!strcasecmp(v->name, "amaflags")) {
17843 y = ast_cdr_amaflags2int(v->value);
17844 if (y < 0)
17845 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17846 else
17847 confp->chan.amaflags = y;
17848 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17849 confp->chan.polarityonanswerdelay = atoi(v->value);
17850 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17851 confp->chan.answeronpolarityswitch = ast_true(v->value);
17852 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17853 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17854 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17855 confp->chan.sendcalleridafter = atoi(v->value);
17856 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17857 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17858 } else if (ast_cc_is_config_param(v->name)) {
17859 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17860 } else if (!strcasecmp(v->name, "mwisendtype")) {
17861 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17862 if (!strcasecmp(v->value, "rpas")) {
17863 mwisend_rpas = 1;
17864 } else {
17865 mwisend_rpas = 0;
17866 }
17867 #else
17868
17869 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17870 if (strcasestr(v->value, "nofsk")) {
17871 confp->chan.mwisend_fsk = 0;
17872 } else {
17873 confp->chan.mwisend_fsk = 1;
17874 }
17875 if (strcasestr(v->value, "rpas")) {
17876 confp->chan.mwisend_rpas = 1;
17877 } else {
17878 confp->chan.mwisend_rpas = 0;
17879 }
17880 if (strcasestr(v->value, "lrev")) {
17881 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17882 }
17883 if (strcasestr(v->value, "hvdc")) {
17884 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17885 }
17886 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17887 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17888 }
17889 #endif
17890 } else if (reload != 1) {
17891 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17892 int orig_radio = confp->chan.radio;
17893 int orig_outsigmod = confp->chan.outsigmod;
17894 int orig_auto = confp->is_sig_auto;
17895
17896 confp->chan.radio = 0;
17897 confp->chan.outsigmod = -1;
17898 confp->is_sig_auto = 0;
17899 if (!strcasecmp(v->value, "em")) {
17900 confp->chan.sig = SIG_EM;
17901 } else if (!strcasecmp(v->value, "em_e1")) {
17902 confp->chan.sig = SIG_EM_E1;
17903 } else if (!strcasecmp(v->value, "em_w")) {
17904 confp->chan.sig = SIG_EMWINK;
17905 } else if (!strcasecmp(v->value, "fxs_ls")) {
17906 confp->chan.sig = SIG_FXSLS;
17907 } else if (!strcasecmp(v->value, "fxs_gs")) {
17908 confp->chan.sig = SIG_FXSGS;
17909 } else if (!strcasecmp(v->value, "fxs_ks")) {
17910 confp->chan.sig = SIG_FXSKS;
17911 } else if (!strcasecmp(v->value, "fxo_ls")) {
17912 confp->chan.sig = SIG_FXOLS;
17913 } else if (!strcasecmp(v->value, "fxo_gs")) {
17914 confp->chan.sig = SIG_FXOGS;
17915 } else if (!strcasecmp(v->value, "fxo_ks")) {
17916 confp->chan.sig = SIG_FXOKS;
17917 } else if (!strcasecmp(v->value, "fxs_rx")) {
17918 confp->chan.sig = SIG_FXSKS;
17919 confp->chan.radio = 1;
17920 } else if (!strcasecmp(v->value, "fxo_rx")) {
17921 confp->chan.sig = SIG_FXOLS;
17922 confp->chan.radio = 1;
17923 } else if (!strcasecmp(v->value, "fxs_tx")) {
17924 confp->chan.sig = SIG_FXSLS;
17925 confp->chan.radio = 1;
17926 } else if (!strcasecmp(v->value, "fxo_tx")) {
17927 confp->chan.sig = SIG_FXOGS;
17928 confp->chan.radio = 1;
17929 } else if (!strcasecmp(v->value, "em_rx")) {
17930 confp->chan.sig = SIG_EM;
17931 confp->chan.radio = 1;
17932 } else if (!strcasecmp(v->value, "em_tx")) {
17933 confp->chan.sig = SIG_EM;
17934 confp->chan.radio = 1;
17935 } else if (!strcasecmp(v->value, "em_rxtx")) {
17936 confp->chan.sig = SIG_EM;
17937 confp->chan.radio = 2;
17938 } else if (!strcasecmp(v->value, "em_txrx")) {
17939 confp->chan.sig = SIG_EM;
17940 confp->chan.radio = 2;
17941 } else if (!strcasecmp(v->value, "sf")) {
17942 confp->chan.sig = SIG_SF;
17943 } else if (!strcasecmp(v->value, "sf_w")) {
17944 confp->chan.sig = SIG_SFWINK;
17945 } else if (!strcasecmp(v->value, "sf_featd")) {
17946 confp->chan.sig = SIG_FEATD;
17947 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17948 confp->chan.sig = SIG_FEATDMF;
17949 } else if (!strcasecmp(v->value, "sf_featb")) {
17950 confp->chan.sig = SIG_SF_FEATB;
17951 } else if (!strcasecmp(v->value, "sf")) {
17952 confp->chan.sig = SIG_SF;
17953 } else if (!strcasecmp(v->value, "sf_rx")) {
17954 confp->chan.sig = SIG_SF;
17955 confp->chan.radio = 1;
17956 } else if (!strcasecmp(v->value, "sf_tx")) {
17957 confp->chan.sig = SIG_SF;
17958 confp->chan.radio = 1;
17959 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17960 confp->chan.sig = SIG_SF;
17961 confp->chan.radio = 2;
17962 } else if (!strcasecmp(v->value, "sf_txrx")) {
17963 confp->chan.sig = SIG_SF;
17964 confp->chan.radio = 2;
17965 } else if (!strcasecmp(v->value, "featd")) {
17966 confp->chan.sig = SIG_FEATD;
17967 } else if (!strcasecmp(v->value, "featdmf")) {
17968 confp->chan.sig = SIG_FEATDMF;
17969 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17970 confp->chan.sig = SIG_FEATDMF_TA;
17971 } else if (!strcasecmp(v->value, "e911")) {
17972 confp->chan.sig = SIG_E911;
17973 } else if (!strcasecmp(v->value, "fgccama")) {
17974 confp->chan.sig = SIG_FGC_CAMA;
17975 } else if (!strcasecmp(v->value, "fgccamamf")) {
17976 confp->chan.sig = SIG_FGC_CAMAMF;
17977 } else if (!strcasecmp(v->value, "featb")) {
17978 confp->chan.sig = SIG_FEATB;
17979 #ifdef HAVE_PRI
17980 } else if (!strcasecmp(v->value, "pri_net")) {
17981 confp->chan.sig = SIG_PRI;
17982 confp->pri.pri.nodetype = PRI_NETWORK;
17983 } else if (!strcasecmp(v->value, "pri_cpe")) {
17984 confp->chan.sig = SIG_PRI;
17985 confp->pri.pri.nodetype = PRI_CPE;
17986 } else if (!strcasecmp(v->value, "bri_cpe")) {
17987 confp->chan.sig = SIG_BRI;
17988 confp->pri.pri.nodetype = PRI_CPE;
17989 } else if (!strcasecmp(v->value, "bri_net")) {
17990 confp->chan.sig = SIG_BRI;
17991 confp->pri.pri.nodetype = PRI_NETWORK;
17992 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17993 confp->chan.sig = SIG_BRI_PTMP;
17994 confp->pri.pri.nodetype = PRI_CPE;
17995 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17996 #if defined(HAVE_PRI_CALL_HOLD)
17997 confp->chan.sig = SIG_BRI_PTMP;
17998 confp->pri.pri.nodetype = PRI_NETWORK;
17999 #else
18000 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
18001 #endif
18002 #endif
18003 #if defined(HAVE_SS7)
18004 } else if (!strcasecmp(v->value, "ss7")) {
18005 confp->chan.sig = SIG_SS7;
18006 #endif
18007 #ifdef HAVE_OPENR2
18008 } else if (!strcasecmp(v->value, "mfcr2")) {
18009 confp->chan.sig = SIG_MFCR2;
18010 #endif
18011 } else if (!strcasecmp(v->value, "auto")) {
18012 confp->is_sig_auto = 1;
18013 } else {
18014 confp->chan.outsigmod = orig_outsigmod;
18015 confp->chan.radio = orig_radio;
18016 confp->is_sig_auto = orig_auto;
18017 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18018 }
18019 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18020 if (!strcasecmp(v->value, "em")) {
18021 confp->chan.outsigmod = SIG_EM;
18022 } else if (!strcasecmp(v->value, "em_e1")) {
18023 confp->chan.outsigmod = SIG_EM_E1;
18024 } else if (!strcasecmp(v->value, "em_w")) {
18025 confp->chan.outsigmod = SIG_EMWINK;
18026 } else if (!strcasecmp(v->value, "sf")) {
18027 confp->chan.outsigmod = SIG_SF;
18028 } else if (!strcasecmp(v->value, "sf_w")) {
18029 confp->chan.outsigmod = SIG_SFWINK;
18030 } else if (!strcasecmp(v->value, "sf_featd")) {
18031 confp->chan.outsigmod = SIG_FEATD;
18032 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18033 confp->chan.outsigmod = SIG_FEATDMF;
18034 } else if (!strcasecmp(v->value, "sf_featb")) {
18035 confp->chan.outsigmod = SIG_SF_FEATB;
18036 } else if (!strcasecmp(v->value, "sf")) {
18037 confp->chan.outsigmod = SIG_SF;
18038 } else if (!strcasecmp(v->value, "featd")) {
18039 confp->chan.outsigmod = SIG_FEATD;
18040 } else if (!strcasecmp(v->value, "featdmf")) {
18041 confp->chan.outsigmod = SIG_FEATDMF;
18042 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18043 confp->chan.outsigmod = SIG_FEATDMF_TA;
18044 } else if (!strcasecmp(v->value, "e911")) {
18045 confp->chan.outsigmod = SIG_E911;
18046 } else if (!strcasecmp(v->value, "fgccama")) {
18047 confp->chan.outsigmod = SIG_FGC_CAMA;
18048 } else if (!strcasecmp(v->value, "fgccamamf")) {
18049 confp->chan.outsigmod = SIG_FGC_CAMAMF;
18050 } else if (!strcasecmp(v->value, "featb")) {
18051 confp->chan.outsigmod = SIG_FEATB;
18052 } else {
18053 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18054 }
18055 #ifdef HAVE_PRI
18056 } else if (!strcasecmp(v->name, "pridialplan")) {
18057 if (!strcasecmp(v->value, "national")) {
18058 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18059 } else if (!strcasecmp(v->value, "unknown")) {
18060 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18061 } else if (!strcasecmp(v->value, "private")) {
18062 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18063 } else if (!strcasecmp(v->value, "international")) {
18064 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18065 } else if (!strcasecmp(v->value, "local")) {
18066 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18067 } else if (!strcasecmp(v->value, "dynamic")) {
18068 confp->pri.pri.dialplan = -1;
18069 } else if (!strcasecmp(v->value, "redundant")) {
18070 confp->pri.pri.dialplan = -2;
18071 } else {
18072 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18073 }
18074 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18075 if (!strcasecmp(v->value, "national")) {
18076 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18077 } else if (!strcasecmp(v->value, "unknown")) {
18078 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18079 } else if (!strcasecmp(v->value, "private")) {
18080 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18081 } else if (!strcasecmp(v->value, "international")) {
18082 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18083 } else if (!strcasecmp(v->value, "local")) {
18084 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18085 } else if (!strcasecmp(v->value, "from_channel")) {
18086 confp->pri.pri.localdialplan = 0;
18087 } else if (!strcasecmp(v->value, "dynamic")) {
18088 confp->pri.pri.localdialplan = -1;
18089 } else if (!strcasecmp(v->value, "redundant")) {
18090 confp->pri.pri.localdialplan = -2;
18091 } else {
18092 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18093 }
18094 } else if (!strcasecmp(v->name, "pricpndialplan")) {
18095 if (!strcasecmp(v->value, "national")) {
18096 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18097 } else if (!strcasecmp(v->value, "unknown")) {
18098 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18099 } else if (!strcasecmp(v->value, "private")) {
18100 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18101 } else if (!strcasecmp(v->value, "international")) {
18102 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18103 } else if (!strcasecmp(v->value, "local")) {
18104 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18105 } else if (!strcasecmp(v->value, "from_channel")) {
18106 confp->pri.pri.cpndialplan = 0;
18107 } else if (!strcasecmp(v->value, "dynamic")) {
18108 confp->pri.pri.cpndialplan = -1;
18109 } else if (!strcasecmp(v->value, "redundant")) {
18110 confp->pri.pri.cpndialplan = -2;
18111 } else {
18112 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18113 }
18114 } else if (!strcasecmp(v->name, "switchtype")) {
18115 if (!strcasecmp(v->value, "national"))
18116 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18117 else if (!strcasecmp(v->value, "ni1"))
18118 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18119 else if (!strcasecmp(v->value, "dms100"))
18120 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18121 else if (!strcasecmp(v->value, "4ess"))
18122 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18123 else if (!strcasecmp(v->value, "5ess"))
18124 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18125 else if (!strcasecmp(v->value, "euroisdn"))
18126 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18127 else if (!strcasecmp(v->value, "qsig"))
18128 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18129 else {
18130 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18131 return -1;
18132 }
18133 } else if (!strcasecmp(v->name, "msn")) {
18134 ast_copy_string(confp->pri.pri.msn_list, v->value,
18135 sizeof(confp->pri.pri.msn_list));
18136 } else if (!strcasecmp(v->name, "nsf")) {
18137 if (!strcasecmp(v->value, "sdn"))
18138 confp->pri.pri.nsf = PRI_NSF_SDN;
18139 else if (!strcasecmp(v->value, "megacom"))
18140 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18141 else if (!strcasecmp(v->value, "tollfreemegacom"))
18142 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18143 else if (!strcasecmp(v->value, "accunet"))
18144 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18145 else if (!strcasecmp(v->value, "none"))
18146 confp->pri.pri.nsf = PRI_NSF_NONE;
18147 else {
18148 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18149 confp->pri.pri.nsf = PRI_NSF_NONE;
18150 }
18151 } else if (!strcasecmp(v->name, "priindication")) {
18152 if (!strcasecmp(v->value, "outofband"))
18153 confp->chan.priindication_oob = 1;
18154 else if (!strcasecmp(v->value, "inband"))
18155 confp->chan.priindication_oob = 0;
18156 else
18157 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18158 v->value, v->lineno);
18159 } else if (!strcasecmp(v->name, "priexclusive")) {
18160 confp->chan.priexclusive = ast_true(v->value);
18161 } else if (!strcasecmp(v->name, "internationalprefix")) {
18162 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
18163 } else if (!strcasecmp(v->name, "nationalprefix")) {
18164 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
18165 } else if (!strcasecmp(v->name, "localprefix")) {
18166 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
18167 } else if (!strcasecmp(v->name, "privateprefix")) {
18168 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
18169 } else if (!strcasecmp(v->name, "unknownprefix")) {
18170 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
18171 } else if (!strcasecmp(v->name, "resetinterval")) {
18172 if (!strcasecmp(v->value, "never"))
18173 confp->pri.pri.resetinterval = -1;
18174 else if (atoi(v->value) >= 60)
18175 confp->pri.pri.resetinterval = atoi(v->value);
18176 else
18177 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
18178 v->value, v->lineno);
18179 } else if (!strcasecmp(v->name, "minunused")) {
18180 confp->pri.pri.minunused = atoi(v->value);
18181 } else if (!strcasecmp(v->name, "minidle")) {
18182 confp->pri.pri.minidle = atoi(v->value);
18183 } else if (!strcasecmp(v->name, "idleext")) {
18184 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
18185 } else if (!strcasecmp(v->name, "idledial")) {
18186 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
18187 } else if (!strcasecmp(v->name, "overlapdial")) {
18188 if (ast_true(v->value)) {
18189 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18190 } else if (!strcasecmp(v->value, "incoming")) {
18191 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
18192 } else if (!strcasecmp(v->value, "outgoing")) {
18193 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
18194 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
18195 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18196 } else {
18197 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
18198 }
18199 #ifdef HAVE_PRI_PROG_W_CAUSE
18200 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
18201 if (!strcasecmp(v->value, "logical")) {
18202 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
18203 } else if (!strcasecmp(v->value, "physical")) {
18204 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18205 } else {
18206 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18207 }
18208 #endif
18209 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
18210 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
18211 #if defined(HAVE_PRI_SERVICE_MESSAGES)
18212 } else if (!strcasecmp(v->name, "service_message_support")) {
18213
18214 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
18215 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
18216 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
18217 confp->pri.pri.enable_service_message_support = 1;
18218 } else {
18219 confp->pri.pri.enable_service_message_support = 0;
18220 }
18221 #endif
18222 #ifdef HAVE_PRI_INBANDDISCONNECT
18223 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
18224 confp->pri.pri.inbanddisconnect = ast_true(v->value);
18225 #endif
18226 } else if (!strcasecmp(v->name, "pritimer")) {
18227 #ifdef PRI_GETSET_TIMERS
18228 char tmp[20];
18229 char *timerc;
18230 char *c;
18231 int timer;
18232 int timeridx;
18233
18234 ast_copy_string(tmp, v->value, sizeof(tmp));
18235 c = tmp;
18236 timerc = strsep(&c, ",");
18237 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
18238 timeridx = pri_timer2idx(timerc);
18239 timer = atoi(c);
18240 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
18241 ast_log(LOG_WARNING,
18242 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
18243 v->lineno);
18244 } else if (!timer) {
18245 ast_log(LOG_WARNING,
18246 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
18247 c, timerc, v->lineno);
18248 } else {
18249 confp->pri.pri.pritimers[timeridx] = timer;
18250 }
18251 } else {
18252 ast_log(LOG_WARNING,
18253 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
18254 v->value, v->lineno);
18255 }
18256 #endif
18257 } else if (!strcasecmp(v->name, "facilityenable")) {
18258 confp->pri.pri.facilityenable = ast_true(v->value);
18259 #if defined(HAVE_PRI_AOC_EVENTS)
18260 } else if (!strcasecmp(v->name, "aoc_enable")) {
18261 confp->pri.pri.aoc_passthrough_flag = 0;
18262 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
18263 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
18264 }
18265 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
18266 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
18267 }
18268 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
18269 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
18270 }
18271 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
18272 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
18273 #endif
18274 #if defined(HAVE_PRI_CALL_HOLD)
18275 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
18276 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
18277 #endif
18278 } else if (!strcasecmp(v->name, "moh_signaling")
18279 || !strcasecmp(v->name, "moh_signalling")) {
18280 if (!strcasecmp(v->value, "moh")) {
18281 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18282 } else if (!strcasecmp(v->value, "notify")) {
18283 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
18284 #if defined(HAVE_PRI_CALL_HOLD)
18285 } else if (!strcasecmp(v->value, "hold")) {
18286 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
18287 #endif
18288 } else {
18289 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18290 }
18291 #if defined(HAVE_PRI_CCSS)
18292 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
18293 if (!strcasecmp(v->value, "global")) {
18294 confp->pri.pri.cc_ptmp_recall_mode = 0;
18295 } else if (!strcasecmp(v->value, "specific")) {
18296 confp->pri.pri.cc_ptmp_recall_mode = 1;
18297 } else {
18298 confp->pri.pri.cc_ptmp_recall_mode = 1;
18299 }
18300 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
18301 if (!strcasecmp(v->value, "release")) {
18302 confp->pri.pri.cc_qsig_signaling_link_req = 0;
18303 } else if (!strcasecmp(v->value, "retain")) {
18304 confp->pri.pri.cc_qsig_signaling_link_req = 1;
18305 } else if (!strcasecmp(v->value, "do_not_care")) {
18306 confp->pri.pri.cc_qsig_signaling_link_req = 2;
18307 } else {
18308 confp->pri.pri.cc_qsig_signaling_link_req = 1;
18309 }
18310 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
18311 if (!strcasecmp(v->value, "release")) {
18312 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
18313 } else if (!strcasecmp(v->value, "retain")) {
18314 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
18315 } else {
18316 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
18317 }
18318 #endif
18319 #if defined(HAVE_PRI_CALL_WAITING)
18320 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
18321 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
18322 if (confp->pri.pri.max_call_waiting_calls < 0) {
18323
18324 confp->pri.pri.max_call_waiting_calls = 0;
18325 }
18326 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
18327 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
18328 #endif
18329 #if defined(HAVE_PRI_MWI)
18330 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
18331 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
18332 sizeof(confp->pri.pri.mwi_mailboxes));
18333 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
18334 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
18335 sizeof(confp->pri.pri.mwi_vm_numbers));
18336 #endif
18337 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
18338 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
18339 } else if (!strcasecmp(v->name, "inband_on_setup_ack")) {
18340 confp->pri.pri.inband_on_setup_ack = ast_true(v->value);
18341 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
18342 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
18343 #if defined(HAVE_PRI_DISPLAY_TEXT)
18344 } else if (!strcasecmp(v->name, "display_send")) {
18345 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
18346 } else if (!strcasecmp(v->name, "display_receive")) {
18347 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
18348 #endif
18349 #if defined(HAVE_PRI_MCID)
18350 } else if (!strcasecmp(v->name, "mcid_send")) {
18351 confp->pri.pri.mcid_send = ast_true(v->value);
18352 #endif
18353 #if defined(HAVE_PRI_DATETIME_SEND)
18354 } else if (!strcasecmp(v->name, "datetime_send")) {
18355 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
18356 #endif
18357 } else if (!strcasecmp(v->name, "layer1_presence")) {
18358 if (!strcasecmp(v->value, "required")) {
18359 confp->pri.pri.layer1_ignored = 0;
18360 } else if (!strcasecmp(v->value, "ignore")) {
18361 confp->pri.pri.layer1_ignored = 1;
18362 } else {
18363
18364 confp->pri.pri.layer1_ignored = 0;
18365 }
18366 #if defined(HAVE_PRI_L2_PERSISTENCE)
18367 } else if (!strcasecmp(v->name, "layer2_persistence")) {
18368 if (!strcasecmp(v->value, "keep_up")) {
18369 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
18370 } else if (!strcasecmp(v->value, "leave_down")) {
18371 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
18372 } else {
18373 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
18374 }
18375 #endif
18376 } else if (!strcasecmp(v->name, "colp_send")) {
18377 if (!strcasecmp(v->value, "block")) {
18378 confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
18379 } else if (!strcasecmp(v->value, "connect")) {
18380 confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
18381 } else if (!strcasecmp(v->value, "update")) {
18382 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18383 } else {
18384 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18385 }
18386 #endif
18387 #if defined(HAVE_SS7)
18388 } else if (!strcasecmp(v->name, "ss7type")) {
18389 if (!strcasecmp(v->value, "itu")) {
18390 cur_ss7type = SS7_ITU;
18391 } else if (!strcasecmp(v->value, "ansi")) {
18392 cur_ss7type = SS7_ANSI;
18393 } else
18394 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
18395 } else if (!strcasecmp(v->name, "linkset")) {
18396 cur_linkset = atoi(v->value);
18397 } else if (!strcasecmp(v->name, "pointcode")) {
18398 cur_pointcode = parse_pointcode(v->value);
18399 } else if (!strcasecmp(v->name, "adjpointcode")) {
18400 cur_adjpointcode = parse_pointcode(v->value);
18401 } else if (!strcasecmp(v->name, "defaultdpc")) {
18402 cur_defaultdpc = parse_pointcode(v->value);
18403 } else if (!strcasecmp(v->name, "cicbeginswith")) {
18404 cur_cicbeginswith = atoi(v->value);
18405 } else if (!strcasecmp(v->name, "networkindicator")) {
18406 if (!strcasecmp(v->value, "national"))
18407 cur_networkindicator = SS7_NI_NAT;
18408 else if (!strcasecmp(v->value, "national_spare"))
18409 cur_networkindicator = SS7_NI_NAT_SPARE;
18410 else if (!strcasecmp(v->value, "international"))
18411 cur_networkindicator = SS7_NI_INT;
18412 else if (!strcasecmp(v->value, "international_spare"))
18413 cur_networkindicator = SS7_NI_INT_SPARE;
18414 else
18415 cur_networkindicator = -1;
18416 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
18417 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
18418 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
18419 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
18420 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
18421 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
18422 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
18423 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
18424 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
18425 if (!strcasecmp(v->value, "national")) {
18426 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
18427 } else if (!strcasecmp(v->value, "international")) {
18428 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
18429 } else if (!strcasecmp(v->value, "subscriber")) {
18430 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
18431 } else if (!strcasecmp(v->value, "unknown")) {
18432 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
18433 } else if (!strcasecmp(v->value, "dynamic")) {
18434 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
18435 } else {
18436 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
18437 }
18438 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
18439 if (!strcasecmp(v->value, "national")) {
18440 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
18441 } else if (!strcasecmp(v->value, "international")) {
18442 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
18443 } else if (!strcasecmp(v->value, "subscriber")) {
18444 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
18445 } else if (!strcasecmp(v->value, "unknown")) {
18446 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
18447 } else if (!strcasecmp(v->value, "dynamic")) {
18448 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
18449 } else {
18450 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
18451 }
18452 } else if (!strcasecmp(v->name, "sigchan")) {
18453 int sigchan, res;
18454 sigchan = atoi(v->value);
18455 res = linkset_addsigchan(sigchan);
18456 if (res < 0)
18457 return -1;
18458
18459 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18460 struct dahdi_ss7 *link;
18461 link = ss7_resolve_linkset(cur_linkset);
18462 if (!link) {
18463 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18464 return -1;
18465 }
18466 if (ast_true(v->value))
18467 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18468 #endif
18469 #ifdef HAVE_OPENR2
18470 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
18471 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
18472 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);
18473 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
18474 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
18475 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
18476 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
18477 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
18478 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
18479 confp->mfcr2.variant = OR2_VAR_ITU;
18480 }
18481 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18482 confp->mfcr2.mfback_timeout = atoi(v->value);
18483 if (!confp->mfcr2.mfback_timeout) {
18484 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18485 confp->mfcr2.mfback_timeout = -1;
18486 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18487 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18488 }
18489 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18490 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18491 if (confp->mfcr2.metering_pulse_timeout > 500) {
18492 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18493 }
18494 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
18495 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
18496 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
18497 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
18498 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
18499 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
18500 confp->mfcr2.dtmf_time_on = atoi(v->value);
18501 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
18502 confp->mfcr2.dtmf_time_off = atoi(v->value);
18503 #endif
18504 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
18505 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
18506 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
18507 #endif
18508 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18509 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18510 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18511 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18512 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18513 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18514 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18515 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18516 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18517 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18518 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18519 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18520 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18521 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18522 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18523 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18524 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18525 #endif
18526 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18527 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18528 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18529 confp->mfcr2.max_ani = atoi(v->value);
18530 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18531 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18532 }
18533 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18534 confp->mfcr2.max_dnis = atoi(v->value);
18535 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18536 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18537 }
18538 } else if (!strcasecmp(v->name, "mfcr2_category")) {
18539 confp->mfcr2.category = openr2_proto_get_category(v->value);
18540 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18541 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18542 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18543 v->value, v->lineno);
18544 }
18545 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18546 openr2_log_level_t tmplevel;
18547 char *clevel;
18548 char *logval = ast_strdupa(v->value);
18549 while (logval) {
18550 clevel = strsep(&logval,",");
18551 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18552 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18553 continue;
18554 }
18555 confp->mfcr2.loglevel |= tmplevel;
18556 }
18557 #endif
18558 } else if (!strcasecmp(v->name, "cadence")) {
18559
18560 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18561 int i;
18562 struct dahdi_ring_cadence new_cadence;
18563 int cid_location = -1;
18564 int firstcadencepos = 0;
18565 char original_args[80];
18566 int cadence_is_ok = 1;
18567
18568 ast_copy_string(original_args, v->value, sizeof(original_args));
18569
18570 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]);
18571
18572
18573 if (element_count % 2 == 1) {
18574 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18575 cadence_is_ok = 0;
18576 }
18577
18578
18579 for (i = 0; i < element_count; i++) {
18580 if (c[i] == 0) {
18581 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18582 cadence_is_ok = 0;
18583 break;
18584 } else if (c[i] < 0) {
18585 if (i % 2 == 1) {
18586
18587 if (cid_location == -1) {
18588 cid_location = i;
18589 c[i] *= -1;
18590 } else {
18591 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18592 cadence_is_ok = 0;
18593 break;
18594 }
18595 } else {
18596 if (firstcadencepos == 0) {
18597 firstcadencepos = i;
18598
18599 } else {
18600 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18601 cadence_is_ok = 0;
18602 break;
18603 }
18604 }
18605 }
18606 }
18607
18608
18609 for (i = 0; i < 16; i++) {
18610 new_cadence.ringcadence[i] = c[i];
18611 }
18612
18613 if (cadence_is_ok) {
18614
18615 if (element_count < 2) {
18616 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18617 } else {
18618 if (cid_location == -1) {
18619
18620 cid_location = 1;
18621 } else {
18622
18623 cid_location = (cid_location + 1) / 2;
18624 }
18625
18626 if (!user_has_defined_cadences++)
18627
18628 num_cadence = 0;
18629 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18630 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18631 else {
18632 cadences[num_cadence] = new_cadence;
18633 cidrings[num_cadence++] = cid_location;
18634 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18635 }
18636 }
18637 }
18638 } else if (!strcasecmp(v->name, "ringtimeout")) {
18639 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18640 } else if (!strcasecmp(v->name, "prewink")) {
18641 confp->timing.prewinktime = atoi(v->value);
18642 } else if (!strcasecmp(v->name, "preflash")) {
18643 confp->timing.preflashtime = atoi(v->value);
18644 } else if (!strcasecmp(v->name, "wink")) {
18645 confp->timing.winktime = atoi(v->value);
18646 } else if (!strcasecmp(v->name, "flash")) {
18647 confp->timing.flashtime = atoi(v->value);
18648 } else if (!strcasecmp(v->name, "start")) {
18649 confp->timing.starttime = atoi(v->value);
18650 } else if (!strcasecmp(v->name, "rxwink")) {
18651 confp->timing.rxwinktime = atoi(v->value);
18652 } else if (!strcasecmp(v->name, "rxflash")) {
18653 confp->timing.rxflashtime = atoi(v->value);
18654 } else if (!strcasecmp(v->name, "debounce")) {
18655 confp->timing.debouncetime = atoi(v->value);
18656 } else if (!strcasecmp(v->name, "toneduration")) {
18657 int toneduration;
18658 int ctlfd;
18659 int res;
18660 struct dahdi_dialparams dps;
18661
18662 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18663 if (ctlfd == -1) {
18664 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18665 return -1;
18666 }
18667
18668 toneduration = atoi(v->value);
18669 if (toneduration > -1) {
18670 memset(&dps, 0, sizeof(dps));
18671
18672 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18673 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18674 if (res < 0) {
18675 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18676 close(ctlfd);
18677 return -1;
18678 }
18679 }
18680 close(ctlfd);
18681 } else if (!strcasecmp(v->name, "defaultcic")) {
18682 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18683 } else if (!strcasecmp(v->name, "defaultozz")) {
18684 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18685 } else if (!strcasecmp(v->name, "mwilevel")) {
18686 mwilevel = atoi(v->value);
18687 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18688 dtmfcid_level = atoi(v->value);
18689 } else if (!strcasecmp(v->name, "reportalarms")) {
18690 if (!strcasecmp(v->value, "all"))
18691 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18692 if (!strcasecmp(v->value, "none"))
18693 report_alarms = 0;
18694 else if (!strcasecmp(v->value, "channels"))
18695 report_alarms = REPORT_CHANNEL_ALARMS;
18696 else if (!strcasecmp(v->value, "spans"))
18697 report_alarms = REPORT_SPAN_ALARMS;
18698 }
18699 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18700 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18701 }
18702
18703
18704 if (confp->chan.vars) {
18705 ast_variables_destroy(confp->chan.vars);
18706 confp->chan.vars = NULL;
18707 }
18708
18709 if (dahdichan) {
18710
18711 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18712 &found_pseudo)) {
18713 if (confp->ignore_failed_channels) {
18714 ast_log(LOG_WARNING,
18715 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18716 dahdichan->value);
18717 } else {
18718 return -1;
18719 }
18720 }
18721 }
18722
18723
18724 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18725 if (!tmp->destroy && tmp->span != y) {
18726 tmp->manages_span_alarms = 1;
18727 y = tmp->span;
18728 } else {
18729 tmp->manages_span_alarms = 0;
18730 }
18731 }
18732
18733
18734
18735 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18736
18737
18738
18739
18740 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18741
18742 if (conf.chan.cc_params) {
18743 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18744 } else {
18745 tmp = NULL;
18746 }
18747 if (tmp) {
18748 ast_verb(3, "Automatically generated pseudo channel\n");
18749 } else {
18750 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18751 }
18752 ast_cc_config_params_destroy(conf.chan.cc_params);
18753 }
18754
18755
18756 confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
18757 confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
18758
18759 return 0;
18760 }
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18773 {
18774 struct ast_cc_config_params *cc_params;
18775
18776 cc_params = dest->chan.cc_params;
18777 *dest = *src;
18778 dest->chan.cc_params = cc_params;
18779 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18780 }
18781
18782
18783
18784
18785
18786
18787
18788
18789
18790
18791
18792
18793
18794 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18795 {
18796 struct ast_config *cfg;
18797 struct ast_config *ucfg;
18798 struct ast_variable *v;
18799 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18800 const char *chans;
18801 const char *cat;
18802 int res;
18803
18804 #ifdef HAVE_PRI
18805 char *c;
18806 int spanno;
18807 int i;
18808 int logicalspan;
18809 int trunkgroup;
18810 int dchannels[SIG_PRI_NUM_DCHANS];
18811 #endif
18812 int have_cfg_now;
18813 static int had_cfg_before = 1;
18814
18815 cfg = ast_config_load(config, config_flags);
18816 have_cfg_now = !!cfg;
18817 if (!cfg) {
18818
18819 if (had_cfg_before) {
18820 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18821 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18822 }
18823 cfg = ast_config_new();
18824 if (!cfg) {
18825 return 0;
18826 }
18827 ucfg = ast_config_load("users.conf", config_flags);
18828 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18829 ast_config_destroy(cfg);
18830 return 0;
18831 }
18832 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18833 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18834 ast_config_destroy(cfg);
18835 return 0;
18836 }
18837 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18838 ucfg = ast_config_load("users.conf", config_flags);
18839 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18840 return 0;
18841 }
18842 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18843 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18844 return 0;
18845 }
18846 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18847 cfg = ast_config_load(config, config_flags);
18848 have_cfg_now = !!cfg;
18849 if (!cfg) {
18850 if (had_cfg_before) {
18851
18852 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18853 ast_config_destroy(ucfg);
18854 return 0;
18855 }
18856 cfg = ast_config_new();
18857 if (!cfg) {
18858 ast_config_destroy(ucfg);
18859 return 0;
18860 }
18861 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18862 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18863 ast_config_destroy(ucfg);
18864 return 0;
18865 }
18866 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18867 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18868 return 0;
18869 } else {
18870 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18871 ucfg = ast_config_load("users.conf", config_flags);
18872 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18873 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18874 ast_config_destroy(cfg);
18875 return 0;
18876 }
18877 }
18878 had_cfg_before = have_cfg_now;
18879
18880
18881 ast_mutex_lock(&iflock);
18882 #ifdef HAVE_PRI
18883 if (reload != 1) {
18884
18885 v = ast_variable_browse(cfg, "trunkgroups");
18886 while (v) {
18887 if (!strcasecmp(v->name, "trunkgroup")) {
18888 trunkgroup = atoi(v->value);
18889 if (trunkgroup > 0) {
18890 if ((c = strchr(v->value, ','))) {
18891 i = 0;
18892 memset(dchannels, 0, sizeof(dchannels));
18893 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18894 dchannels[i] = atoi(c + 1);
18895 if (dchannels[i] < 0) {
18896 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);
18897 } else
18898 i++;
18899 c = strchr(c + 1, ',');
18900 }
18901 if (i) {
18902 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18903 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);
18904 } else
18905 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");
18906 } else
18907 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18908 } else
18909 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18910 } else
18911 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18912 } else if (!strcasecmp(v->name, "spanmap")) {
18913 spanno = atoi(v->value);
18914 if (spanno > 0) {
18915 if ((c = strchr(v->value, ','))) {
18916 trunkgroup = atoi(c + 1);
18917 if (trunkgroup > 0) {
18918 if ((c = strchr(c + 1, ',')))
18919 logicalspan = atoi(c + 1);
18920 else
18921 logicalspan = 0;
18922 if (logicalspan >= 0) {
18923 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18924 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18925 } else
18926 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18927 } else
18928 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);
18929 } else
18930 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18931 } else
18932 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18933 } else
18934 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18935 } else {
18936 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18937 }
18938 v = v->next;
18939 }
18940 }
18941 #endif
18942
18943
18944 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18945
18946 mwimonitornotify[0] = '\0';
18947
18948 v = ast_variable_browse(cfg, "channels");
18949 if ((res = process_dahdi(base_conf,
18950 "" ,
18951 v, reload, 0))) {
18952 ast_mutex_unlock(&iflock);
18953 ast_config_destroy(cfg);
18954 if (ucfg) {
18955 ast_config_destroy(ucfg);
18956 }
18957 return res;
18958 }
18959
18960
18961 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18962
18963
18964
18965 if (!strcasecmp(cat, "general") ||
18966 !strcasecmp(cat, "trunkgroups") ||
18967 !strcasecmp(cat, "globals") ||
18968 !strcasecmp(cat, "channels")) {
18969 continue;
18970 }
18971
18972 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18973 if (ast_strlen_zero(chans)) {
18974
18975 continue;
18976 }
18977
18978
18979 deep_copy_dahdi_chan_conf(conf, base_conf);
18980
18981 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18982 ast_mutex_unlock(&iflock);
18983 ast_config_destroy(cfg);
18984 if (ucfg) {
18985 ast_config_destroy(ucfg);
18986 }
18987 return res;
18988 }
18989 }
18990
18991 ast_config_destroy(cfg);
18992
18993 if (ucfg) {
18994
18995 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18996 process_dahdi(base_conf,
18997 "" ,
18998 ast_variable_browse(ucfg, "general"), 1, 0);
18999
19000 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
19001 if (!strcasecmp(cat, "general")) {
19002 continue;
19003 }
19004
19005 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
19006 if (ast_strlen_zero(chans)) {
19007
19008 continue;
19009 }
19010
19011
19012 deep_copy_dahdi_chan_conf(conf, base_conf);
19013
19014 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
19015 ast_config_destroy(ucfg);
19016 ast_mutex_unlock(&iflock);
19017 return res;
19018 }
19019 }
19020 ast_config_destroy(ucfg);
19021 }
19022 ast_mutex_unlock(&iflock);
19023
19024 #ifdef HAVE_PRI
19025 if (reload != 1) {
19026 int x;
19027 for (x = 0; x < NUM_SPANS; x++) {
19028 if (pris[x].pri.pvts[0]) {
19029 prepare_pri(pris + x);
19030 if (sig_pri_start_pri(&pris[x].pri)) {
19031 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
19032 return -1;
19033 } else
19034 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
19035 }
19036 }
19037 }
19038 #endif
19039 #if defined(HAVE_SS7)
19040 if (reload != 1) {
19041 int x;
19042 for (x = 0; x < NUM_SPANS; x++) {
19043 if (linksets[x].ss7.ss7) {
19044 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
19045 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
19046 return -1;
19047 } else
19048 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
19049 }
19050 }
19051 }
19052 #endif
19053 #ifdef HAVE_OPENR2
19054 if (reload != 1) {
19055 int x;
19056 for (x = 0; x < r2links_count; x++) {
19057 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
19058 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
19059 return -1;
19060 } else {
19061 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
19062 }
19063 }
19064 }
19065 #endif
19066
19067 restart_monitor();
19068 return 0;
19069 }
19070
19071
19072
19073
19074
19075
19076
19077
19078
19079
19080 static int setup_dahdi(int reload)
19081 {
19082 int res;
19083 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
19084 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
19085 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19086
19087 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
19088 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
19089 } else {
19090 res = -1;
19091 }
19092 ast_cc_config_params_destroy(default_conf.chan.cc_params);
19093 ast_cc_config_params_destroy(base_conf.chan.cc_params);
19094 ast_cc_config_params_destroy(conf.chan.cc_params);
19095
19096 return res;
19097 }
19098
19099
19100
19101
19102
19103
19104
19105
19106 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
19107 struct ast_data *data_root)
19108 {
19109 int ctl, res, span;
19110 struct ast_data *data_span, *data_alarms;
19111 struct dahdi_spaninfo s;
19112
19113 ctl = open("/dev/dahdi/ctl", O_RDWR);
19114 if (ctl < 0) {
19115 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
19116 return -1;
19117 }
19118 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
19119 s.spanno = span;
19120 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
19121 if (res) {
19122 continue;
19123 }
19124
19125 data_span = ast_data_add_node(data_root, "span");
19126 if (!data_span) {
19127 continue;
19128 }
19129 ast_data_add_str(data_span, "description", s.desc);
19130
19131
19132 data_alarms = ast_data_add_node(data_span, "alarms");
19133 if (!data_alarms) {
19134 continue;
19135 }
19136
19137 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
19138 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
19139 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
19140 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
19141 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
19142 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
19143
19144 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
19145 ast_data_add_int(data_span, "bpviol", s.bpvcount);
19146 ast_data_add_int(data_span, "crc4", s.crc4count);
19147 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
19148 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
19149 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
19150 "CAS");
19151 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
19152 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
19153 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
19154 "Unknown");
19155 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
19156 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
19157 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
19158 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
19159
19160
19161 if (!ast_data_search_match(search, data_span)) {
19162 ast_data_remove_node(data_root, data_span);
19163 }
19164 }
19165 close(ctl);
19166
19167 return 0;
19168 }
19169
19170
19171
19172
19173
19174
19175
19176
19177 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
19178 struct ast_data *data_root)
19179 {
19180 struct dahdi_pvt *tmp;
19181 struct ast_data *data_channel;
19182
19183 ast_mutex_lock(&iflock);
19184 for (tmp = iflist; tmp; tmp = tmp->next) {
19185 data_channel = ast_data_add_node(data_root, "channel");
19186 if (!data_channel) {
19187 continue;
19188 }
19189
19190 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
19191
19192
19193 if (!ast_data_search_match(search, data_channel)) {
19194 ast_data_remove_node(data_root, data_channel);
19195 }
19196 }
19197 ast_mutex_unlock(&iflock);
19198
19199 return 0;
19200 }
19201
19202
19203
19204
19205
19206
19207
19208
19209 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
19210 struct ast_data *data_root)
19211 {
19212 int pseudo_fd = -1;
19213 struct dahdi_versioninfo vi = {
19214 .version = "Unknown",
19215 .echo_canceller = "Unknown"
19216 };
19217
19218 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
19219 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
19220 return -1;
19221 }
19222
19223 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
19224 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
19225 }
19226
19227 close(pseudo_fd);
19228
19229 ast_data_add_str(data_root, "value", vi.version);
19230 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
19231
19232 return 0;
19233 }
19234
19235 static const struct ast_data_handler dahdi_status_data_provider = {
19236 .version = AST_DATA_HANDLER_VERSION,
19237 .get = dahdi_status_data_provider_get
19238 };
19239
19240 static const struct ast_data_handler dahdi_channels_data_provider = {
19241 .version = AST_DATA_HANDLER_VERSION,
19242 .get = dahdi_channels_data_provider_get
19243 };
19244
19245 static const struct ast_data_handler dahdi_version_data_provider = {
19246 .version = AST_DATA_HANDLER_VERSION,
19247 .get = dahdi_version_data_provider_get
19248 };
19249
19250 static const struct ast_data_entry dahdi_data_providers[] = {
19251 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
19252 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
19253 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
19254 };
19255
19256 static int load_module(void)
19257 {
19258 int res;
19259 struct ast_format tmpfmt;
19260 #if defined(HAVE_PRI) || defined(HAVE_SS7)
19261 int y;
19262 #endif
19263
19264 if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
19265 return AST_MODULE_LOAD_FAILURE;
19266 }
19267 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
19268 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
19269 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
19270
19271 #ifdef HAVE_PRI
19272 memset(pris, 0, sizeof(pris));
19273 for (y = 0; y < NUM_SPANS; y++) {
19274 sig_pri_init_pri(&pris[y].pri);
19275 }
19276 pri_set_error(dahdi_pri_error);
19277 pri_set_message(dahdi_pri_message);
19278 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
19279 #ifdef HAVE_PRI_PROG_W_CAUSE
19280 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
19281 #endif
19282 #if defined(HAVE_PRI_CCSS)
19283 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
19284 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
19285 __unload_module();
19286 return AST_MODULE_LOAD_FAILURE;
19287 }
19288 #endif
19289 if (sig_pri_load(
19290 #if defined(HAVE_PRI_CCSS)
19291 dahdi_pri_cc_type
19292 #else
19293 NULL
19294 #endif
19295 )) {
19296 __unload_module();
19297 return AST_MODULE_LOAD_FAILURE;
19298 }
19299 #endif
19300 #if defined(HAVE_SS7)
19301 memset(linksets, 0, sizeof(linksets));
19302 for (y = 0; y < NUM_SPANS; y++) {
19303 sig_ss7_init_linkset(&linksets[y].ss7);
19304 }
19305 ss7_set_error(dahdi_ss7_error);
19306 ss7_set_message(dahdi_ss7_message);
19307 #endif
19308 res = setup_dahdi(0);
19309
19310 if (res)
19311 return AST_MODULE_LOAD_DECLINE;
19312 if (ast_channel_register(&dahdi_tech)) {
19313 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
19314 __unload_module();
19315 return AST_MODULE_LOAD_FAILURE;
19316 }
19317 #ifdef HAVE_PRI
19318 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
19319 #endif
19320 #if defined(HAVE_SS7)
19321 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
19322 #endif
19323 #ifdef HAVE_OPENR2
19324 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
19325 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
19326 #endif
19327
19328 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
19329
19330 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
19331 memset(round_robin, 0, sizeof(round_robin));
19332 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
19333 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
19334 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
19335 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
19336 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
19337 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
19338 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
19339 #if defined(HAVE_PRI)
19340 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
19341 #endif
19342
19343 ast_cond_init(&ss_thread_complete, NULL);
19344
19345 return res;
19346 }
19347
19348 static int dahdi_sendtext(struct ast_channel *c, const char *text)
19349 {
19350 #define END_SILENCE_LEN 400
19351 #define HEADER_MS 50
19352 #define TRAILER_MS 5
19353 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
19354 #define ASCII_BYTES_PER_CHAR 80
19355
19356 unsigned char *buf,*mybuf;
19357 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
19358 struct pollfd fds[1];
19359 int size,res,fd,len,x;
19360 int bytes=0;
19361 int idx;
19362
19363
19364
19365
19366
19367
19368
19369 float cr = 1.0;
19370 float ci = 0.0;
19371 float scont = 0.0;
19372
19373 if (!text[0]) {
19374 return(0);
19375 }
19376 idx = dahdi_get_index(c, p, 0);
19377 if (idx < 0) {
19378 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
19379 return -1;
19380 }
19381 if ((!p->tdd) && (!p->mate)) {
19382 #if defined(HAVE_PRI)
19383 #if defined(HAVE_PRI_DISPLAY_TEXT)
19384 ast_mutex_lock(&p->lock);
19385 if (dahdi_sig_pri_lib_handles(p->sig)) {
19386 sig_pri_sendtext(p->sig_pvt, text);
19387 }
19388 ast_mutex_unlock(&p->lock);
19389 #endif
19390 #endif
19391 return(0);
19392 }
19393 if (p->mate)
19394 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
19395 else
19396 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
19397 if (!buf)
19398 return -1;
19399 mybuf = buf;
19400 if (p->mate) {
19401 struct ast_format tmp;
19402
19403 struct ast_format *codec = &tmp;
19404 ast_format_set(codec, AST_LAW(p), 0);
19405 for (x = 0; x < HEADER_MS; x++) {
19406 PUT_CLID_MARKMS;
19407 }
19408
19409 for (x = 0; text[x]; x++) {
19410 PUT_CLID(text[x]);
19411 }
19412 for (x = 0; x < TRAILER_MS; x++) {
19413 PUT_CLID_MARKMS;
19414 }
19415 len = bytes;
19416 buf = mybuf;
19417 } else {
19418 len = tdd_generate(p->tdd, buf, text);
19419 if (len < 1) {
19420 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
19421 ast_free(mybuf);
19422 return -1;
19423 }
19424 }
19425 memset(buf + len, 0x7f, END_SILENCE_LEN);
19426 len += END_SILENCE_LEN;
19427 fd = p->subs[idx].dfd;
19428 while (len) {
19429 if (ast_check_hangup(c)) {
19430 ast_free(mybuf);
19431 return -1;
19432 }
19433 size = len;
19434 if (size > READ_SIZE)
19435 size = READ_SIZE;
19436 fds[0].fd = fd;
19437 fds[0].events = POLLOUT | POLLPRI;
19438 fds[0].revents = 0;
19439 res = poll(fds, 1, -1);
19440 if (!res) {
19441 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
19442 continue;
19443 }
19444
19445 if (fds[0].revents & POLLPRI) {
19446 ast_free(mybuf);
19447 return -1;
19448 }
19449 if (!(fds[0].revents & POLLOUT)) {
19450 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
19451 continue;
19452 }
19453 res = write(fd, buf, size);
19454 if (res != size) {
19455 if (res == -1) {
19456 ast_free(mybuf);
19457 return -1;
19458 }
19459 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19460 break;
19461 }
19462 len -= size;
19463 buf += size;
19464 }
19465 ast_free(mybuf);
19466 return(0);
19467 }
19468
19469
19470 static int reload(void)
19471 {
19472 int res = 0;
19473
19474 res = setup_dahdi(1);
19475 if (res) {
19476 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19477 return -1;
19478 }
19479 return 0;
19480 }
19481
19482
19483
19484
19485
19486 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
19487 .load = load_module,
19488 .unload = unload_module,
19489 .reload = reload,
19490 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19491 .nonoptreq = "res_smdi",
19492 );