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: 407818 $")
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_proceeding = 1,
01413
01414 #if defined(HAVE_PRI_CCSS)
01415 .cc_ptmp_recall_mode = 1,
01416 .cc_qsig_signaling_link_req = 1,
01417 .cc_qsig_signaling_link_rsp = 1,
01418 #endif
01419
01420 .minunused = 2,
01421 .idleext = "",
01422 .idledial = "",
01423 .internationalprefix = "",
01424 .nationalprefix = "",
01425 .localprefix = "",
01426 .privateprefix = "",
01427 .unknownprefix = "",
01428 .colp_send = SIG_PRI_COLP_UPDATE,
01429 .resetinterval = -1,
01430 },
01431 #endif
01432 #if defined(HAVE_SS7)
01433 .ss7.ss7 = {
01434 .called_nai = SS7_NAI_NATIONAL,
01435 .calling_nai = SS7_NAI_NATIONAL,
01436 .internationalprefix = "",
01437 .nationalprefix = "",
01438 .subscriberprefix = "",
01439 .unknownprefix = ""
01440 },
01441 #endif
01442 #ifdef HAVE_OPENR2
01443 .mfcr2 = {
01444 .variant = OR2_VAR_ITU,
01445 .mfback_timeout = -1,
01446 .metering_pulse_timeout = -1,
01447 .max_ani = 10,
01448 .max_dnis = 4,
01449 .get_ani_first = -1,
01450 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01451 .skip_category_request = -1,
01452 #endif
01453 .call_files = 0,
01454 .allow_collect_calls = 0,
01455 .charge_calls = 1,
01456 .accept_on_offer = 1,
01457 .forced_release = 0,
01458 .double_answer = 0,
01459 .immediate_accept = -1,
01460 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
01461 .dtmf_dialing = -1,
01462 .dtmf_detection = -1,
01463 .dtmf_time_on = OR2_DEFAULT_DTMF_ON,
01464 .dtmf_time_off = OR2_DEFAULT_DTMF_OFF,
01465 #endif
01466 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
01467 .dtmf_end_timeout = -1,
01468 #endif
01469 .logdir = "",
01470 .r2proto_file = "",
01471 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01472 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01473 },
01474 #endif
01475 .chan = {
01476 .context = "default",
01477 .cid_num = "",
01478 .cid_name = "",
01479 .cid_tag = "",
01480 .mohinterpret = "default",
01481 .mohsuggest = "",
01482 .parkinglot = "",
01483 .transfertobusy = 1,
01484
01485 .cid_signalling = CID_SIG_BELL,
01486 .cid_start = CID_START_RING,
01487 .dahditrcallerid = 0,
01488 .use_callerid = 1,
01489 .sig = -1,
01490 .outsigmod = -1,
01491
01492 .cid_rxgain = +5.0,
01493
01494 .tonezone = -1,
01495
01496 .echocancel.head.tap_length = 1,
01497
01498 .busycount = 3,
01499
01500 .accountcode = "",
01501
01502 .mailbox = "",
01503
01504 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01505 .mwisend_fsk = 1,
01506 #endif
01507 .polarityonanswerdelay = 600,
01508
01509 .sendcalleridafter = DEFAULT_CIDRINGS,
01510
01511 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01512 .buf_no = numbufs,
01513 .usefaxbuffers = 0,
01514 .cc_params = ast_cc_config_params_init(),
01515 },
01516 .timing = {
01517 .prewinktime = -1,
01518 .preflashtime = -1,
01519 .winktime = -1,
01520 .flashtime = -1,
01521 .starttime = -1,
01522 .rxwinktime = -1,
01523 .rxflashtime = -1,
01524 .debouncetime = -1
01525 },
01526 .is_sig_auto = 1,
01527 .smdi_port = "/dev/ttyS0",
01528 };
01529
01530 return conf;
01531 }
01532
01533
01534 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
01535 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01536 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01537 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01538 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout);
01539 static int dahdi_hangup(struct ast_channel *ast);
01540 static int dahdi_answer(struct ast_channel *ast);
01541 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01542 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01543 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01544 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01545 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01546 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01547 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01548 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01549 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01550 static int dahdi_devicestate(const char *data);
01551 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01552
01553 static struct ast_channel_tech dahdi_tech = {
01554 .type = "DAHDI",
01555 .description = tdesc,
01556 .requester = dahdi_request,
01557 .send_digit_begin = dahdi_digit_begin,
01558 .send_digit_end = dahdi_digit_end,
01559 .send_text = dahdi_sendtext,
01560 .call = dahdi_call,
01561 .hangup = dahdi_hangup,
01562 .answer = dahdi_answer,
01563 .read = dahdi_read,
01564 .write = dahdi_write,
01565 .bridge = dahdi_bridge,
01566 .exception = dahdi_exception,
01567 .indicate = dahdi_indicate,
01568 .fixup = dahdi_fixup,
01569 .setoption = dahdi_setoption,
01570 .queryoption = dahdi_queryoption,
01571 .func_channel_read = dahdi_func_read,
01572 .func_channel_write = dahdi_func_write,
01573 .devicestate = dahdi_devicestate,
01574 .cc_callback = dahdi_cc_callback,
01575 };
01576
01577 #define GET_CHANNEL(p) ((p)->channel)
01578
01579 #define SIG_PRI_LIB_HANDLE_CASES \
01580 SIG_PRI: \
01581 case SIG_BRI: \
01582 case SIG_BRI_PTMP
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593 static inline int dahdi_sig_pri_lib_handles(int signaling)
01594 {
01595 int handles;
01596
01597 switch (signaling) {
01598 case SIG_PRI_LIB_HANDLE_CASES:
01599 handles = 1;
01600 break;
01601 default:
01602 handles = 0;
01603 break;
01604 }
01605
01606 return handles;
01607 }
01608
01609 static int analog_lib_handles(int signalling, int radio, int oprmode)
01610 {
01611 switch (signalling) {
01612 case SIG_FXOLS:
01613 case SIG_FXOGS:
01614 case SIG_FXOKS:
01615 case SIG_FXSLS:
01616 case SIG_FXSGS:
01617 case SIG_FXSKS:
01618 case SIG_EMWINK:
01619 case SIG_EM:
01620 case SIG_EM_E1:
01621 case SIG_FEATD:
01622 case SIG_FEATDMF:
01623 case SIG_E911:
01624 case SIG_FGC_CAMA:
01625 case SIG_FGC_CAMAMF:
01626 case SIG_FEATB:
01627 case SIG_SFWINK:
01628 case SIG_SF:
01629 case SIG_SF_FEATD:
01630 case SIG_SF_FEATDMF:
01631 case SIG_FEATDMF_TA:
01632 case SIG_SF_FEATB:
01633 break;
01634 default:
01635
01636 return 0;
01637 }
01638
01639 if (radio) {
01640 return 0;
01641 }
01642
01643 if (oprmode) {
01644 return 0;
01645 }
01646
01647 return 1;
01648 }
01649
01650 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01651 {
01652 switch (sig) {
01653 case SIG_FXOLS:
01654 return ANALOG_SIG_FXOLS;
01655 case SIG_FXOGS:
01656 return ANALOG_SIG_FXOGS;
01657 case SIG_FXOKS:
01658 return ANALOG_SIG_FXOKS;
01659 case SIG_FXSLS:
01660 return ANALOG_SIG_FXSLS;
01661 case SIG_FXSGS:
01662 return ANALOG_SIG_FXSGS;
01663 case SIG_FXSKS:
01664 return ANALOG_SIG_FXSKS;
01665 case SIG_EMWINK:
01666 return ANALOG_SIG_EMWINK;
01667 case SIG_EM:
01668 return ANALOG_SIG_EM;
01669 case SIG_EM_E1:
01670 return ANALOG_SIG_EM_E1;
01671 case SIG_FEATD:
01672 return ANALOG_SIG_FEATD;
01673 case SIG_FEATDMF:
01674 return ANALOG_SIG_FEATDMF;
01675 case SIG_E911:
01676 return SIG_E911;
01677 case SIG_FGC_CAMA:
01678 return ANALOG_SIG_FGC_CAMA;
01679 case SIG_FGC_CAMAMF:
01680 return ANALOG_SIG_FGC_CAMAMF;
01681 case SIG_FEATB:
01682 return ANALOG_SIG_FEATB;
01683 case SIG_SFWINK:
01684 return ANALOG_SIG_SFWINK;
01685 case SIG_SF:
01686 return ANALOG_SIG_SF;
01687 case SIG_SF_FEATD:
01688 return ANALOG_SIG_SF_FEATD;
01689 case SIG_SF_FEATDMF:
01690 return ANALOG_SIG_SF_FEATDMF;
01691 case SIG_FEATDMF_TA:
01692 return ANALOG_SIG_FEATDMF_TA;
01693 case SIG_SF_FEATB:
01694 return ANALOG_SIG_FEATB;
01695 default:
01696 return -1;
01697 }
01698 }
01699
01700
01701 static int analog_tone_to_dahditone(enum analog_tone tone)
01702 {
01703 switch (tone) {
01704 case ANALOG_TONE_RINGTONE:
01705 return DAHDI_TONE_RINGTONE;
01706 case ANALOG_TONE_STUTTER:
01707 return DAHDI_TONE_STUTTER;
01708 case ANALOG_TONE_CONGESTION:
01709 return DAHDI_TONE_CONGESTION;
01710 case ANALOG_TONE_DIALTONE:
01711 return DAHDI_TONE_DIALTONE;
01712 case ANALOG_TONE_DIALRECALL:
01713 return DAHDI_TONE_DIALRECALL;
01714 case ANALOG_TONE_INFO:
01715 return DAHDI_TONE_INFO;
01716 default:
01717 return -1;
01718 }
01719 }
01720
01721 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01722 {
01723 int index;
01724
01725 switch (analogsub) {
01726 case ANALOG_SUB_REAL:
01727 index = SUB_REAL;
01728 break;
01729 case ANALOG_SUB_CALLWAIT:
01730 index = SUB_CALLWAIT;
01731 break;
01732 case ANALOG_SUB_THREEWAY:
01733 index = SUB_THREEWAY;
01734 break;
01735 default:
01736 ast_log(LOG_ERROR, "Unidentified sub!\n");
01737 index = SUB_REAL;
01738 }
01739
01740 return index;
01741 }
01742
01743 static enum analog_event dahdievent_to_analogevent(int event);
01744 static int bump_gains(struct dahdi_pvt *p);
01745 static int dahdi_setlinear(int dfd, int linear);
01746
01747 static int my_start_cid_detect(void *pvt, int cid_signalling)
01748 {
01749 struct dahdi_pvt *p = pvt;
01750 int index = SUB_REAL;
01751 p->cs = callerid_new(cid_signalling);
01752 if (!p->cs) {
01753 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01754 return -1;
01755 }
01756 bump_gains(p);
01757 dahdi_setlinear(p->subs[index].dfd, 0);
01758
01759 return 0;
01760 }
01761
01762 static int my_stop_cid_detect(void *pvt)
01763 {
01764 struct dahdi_pvt *p = pvt;
01765 int index = SUB_REAL;
01766 if (p->cs)
01767 callerid_free(p->cs);
01768 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01769 return 0;
01770 }
01771
01772 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01773 {
01774 struct dahdi_pvt *p = pvt;
01775 struct analog_pvt *analog_p = p->sig_pvt;
01776 struct pollfd poller;
01777 char *name, *num;
01778 int index = SUB_REAL;
01779 int res;
01780 unsigned char buf[256];
01781 int flags;
01782 struct ast_format tmpfmt;
01783
01784 poller.fd = p->subs[SUB_REAL].dfd;
01785 poller.events = POLLPRI | POLLIN;
01786 poller.revents = 0;
01787
01788 res = poll(&poller, 1, timeout);
01789
01790 if (poller.revents & POLLPRI) {
01791 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01792 return 1;
01793 }
01794
01795 if (poller.revents & POLLIN) {
01796
01797
01798
01799
01800
01801 res = read(p->subs[index].dfd, buf, sizeof(buf));
01802 if (res < 0) {
01803 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01804 return -1;
01805 }
01806
01807 if (analog_p->ringt > 0) {
01808 if (!(--analog_p->ringt)) {
01809
01810 return -1;
01811 }
01812 }
01813
01814 if (p->cid_signalling == CID_SIG_V23_JP) {
01815 res = callerid_feed_jp(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01816 } else {
01817 res = callerid_feed(p->cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
01818 }
01819 if (res < 0) {
01820
01821
01822
01823
01824 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01825 return -1;
01826 }
01827
01828 if (res == 1) {
01829 callerid_get(p->cs, &name, &num, &flags);
01830 if (name)
01831 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01832 if (num)
01833 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01834
01835 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01836 return 0;
01837 }
01838 }
01839
01840 *ev = ANALOG_EVENT_NONE;
01841 return 2;
01842 }
01843
01844 static const char *event2str(int event);
01845 static int restore_gains(struct dahdi_pvt *p);
01846
01847 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01848 {
01849 unsigned char buf[256];
01850 int distMatches;
01851 int curRingData[RING_PATTERNS];
01852 int receivedRingT;
01853 int counter1;
01854 int counter;
01855 int i;
01856 int res;
01857 int checkaftercid = 0;
01858
01859 struct dahdi_pvt *p = pvt;
01860 struct analog_pvt *analog_p = p->sig_pvt;
01861
01862 if (ringdata == NULL) {
01863 ringdata = curRingData;
01864 } else {
01865 checkaftercid = 1;
01866 }
01867
01868
01869
01870 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01871
01872 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01873 ringdata[receivedRingT] = 0;
01874 receivedRingT = 0;
01875 if (checkaftercid && distinctiveringaftercid)
01876 ast_verb(3, "Detecting post-CID distinctive ring\n");
01877
01878 else if (strcmp(p->context,p->defcontext) != 0) {
01879 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01880 ast_channel_context_set(chan, p->defcontext);
01881 }
01882
01883 for (;;) {
01884 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01885 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01886 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01887 ast_hangup(chan);
01888 return 1;
01889 }
01890 if (i & DAHDI_IOMUX_SIGEVENT) {
01891 res = dahdi_get_event(p->subs[idx].dfd);
01892 if (res == DAHDI_EVENT_NOALARM) {
01893 p->inalarm = 0;
01894 analog_p->inalarm = 0;
01895 }
01896 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01897 res = 0;
01898
01899
01900 ringdata[receivedRingT] = analog_p->ringt;
01901
01902 if (analog_p->ringt < analog_p->ringt_base/2)
01903 break;
01904
01905
01906 if (++receivedRingT == RING_PATTERNS)
01907 break;
01908 } else if (i & DAHDI_IOMUX_READ) {
01909 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01910 if (res < 0) {
01911 if (errno != ELAST) {
01912 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01913 ast_hangup(chan);
01914 return 1;
01915 }
01916 break;
01917 }
01918 if (analog_p->ringt > 0) {
01919 if (!(--analog_p->ringt)) {
01920 res = -1;
01921 break;
01922 }
01923 }
01924 }
01925 }
01926 }
01927 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01928
01929 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01930 for (counter = 0; counter < 3; counter++) {
01931
01932 distMatches = 0;
01933
01934 ast_verb(3, "Checking %d,%d,%d\n",
01935 p->drings.ringnum[counter].ring[0],
01936 p->drings.ringnum[counter].ring[1],
01937 p->drings.ringnum[counter].ring[2]);
01938 for (counter1 = 0; counter1 < 3; counter1++) {
01939 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01940 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01941 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01942 ringdata[counter1]);
01943 distMatches++;
01944 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01945 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01946 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01947 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01948 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01949 distMatches++;
01950 }
01951 }
01952
01953 if (distMatches == 3) {
01954
01955 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01956 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
01957 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01958 break;
01959 }
01960 }
01961 }
01962
01963 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01964 restore_gains(p);
01965
01966 return 0;
01967 }
01968
01969 static int my_stop_callwait(void *pvt)
01970 {
01971 struct dahdi_pvt *p = pvt;
01972 p->callwaitingrepeat = 0;
01973 p->cidcwexpire = 0;
01974 p->cid_suppress_expire = 0;
01975
01976 return 0;
01977 }
01978
01979 static int send_callerid(struct dahdi_pvt *p);
01980 static int save_conference(struct dahdi_pvt *p);
01981 static int restore_conference(struct dahdi_pvt *p);
01982
01983 static int my_callwait(void *pvt)
01984 {
01985 struct dahdi_pvt *p = pvt;
01986 struct ast_format tmpfmt;
01987 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01988 if (p->cidspill) {
01989 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01990 ast_free(p->cidspill);
01991 }
01992
01993
01994
01995
01996
01997 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01998 return -1;
01999 save_conference(p);
02000
02001 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02002 if (!p->callwaitrings && p->callwaitingcallerid) {
02003 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02004 p->callwaitcas = 1;
02005 p->cidlen = 2400 + 680 + READ_SIZE * 4;
02006 } else {
02007 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
02008 p->callwaitcas = 0;
02009 p->cidlen = 2400 + READ_SIZE * 4;
02010 }
02011 p->cidpos = 0;
02012 send_callerid(p);
02013
02014 return 0;
02015 }
02016
02017 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
02018 {
02019 struct dahdi_pvt *p = pvt;
02020 struct ast_format tmpfmt;
02021
02022 ast_debug(2, "Starting cid spill\n");
02023
02024 if (p->cidspill) {
02025 ast_log(LOG_WARNING, "cidspill already exists??\n");
02026 ast_free(p->cidspill);
02027 }
02028
02029 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02030 if (cwcid == 0) {
02031 p->cidlen = ast_callerid_generate(p->cidspill,
02032 caller->id.name.str,
02033 caller->id.number.str,
02034 ast_format_set(&tmpfmt, AST_LAW(p), 0));
02035 } else {
02036 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
02037 caller->id.name.str, caller->id.number.str);
02038 p->callwaitcas = 0;
02039 p->cidcwexpire = 0;
02040 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02041 caller->id.name.str,
02042 caller->id.number.str,
02043 ast_format_set(&tmpfmt, AST_LAW(p), 0));
02044 p->cidlen += READ_SIZE * 4;
02045 }
02046 p->cidpos = 0;
02047 p->cid_suppress_expire = 0;
02048 send_callerid(p);
02049 }
02050 return 0;
02051 }
02052
02053 static int my_dsp_reset_and_flush_digits(void *pvt)
02054 {
02055 struct dahdi_pvt *p = pvt;
02056 if (p->dsp)
02057 ast_dsp_digitreset(p->dsp);
02058
02059 return 0;
02060 }
02061
02062 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02063 {
02064 struct dahdi_pvt *p = pvt;
02065
02066 if (p->channel == CHAN_PSEUDO)
02067 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02068
02069 if (mode == ANALOG_DIGITMODE_DTMF) {
02070
02071 if (p->hardwaredtmf) {
02072 if (p->dsp) {
02073 ast_dsp_free(p->dsp);
02074 p->dsp = NULL;
02075 }
02076 return 0;
02077 }
02078
02079 if (!p->dsp) {
02080 p->dsp = ast_dsp_new();
02081 if (!p->dsp) {
02082 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02083 return -1;
02084 }
02085 }
02086
02087 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02088 } else if (mode == ANALOG_DIGITMODE_MF) {
02089 if (!p->dsp) {
02090 p->dsp = ast_dsp_new();
02091 if (!p->dsp) {
02092 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02093 return -1;
02094 }
02095 }
02096 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02097 }
02098 return 0;
02099 }
02100
02101 static int dahdi_wink(struct dahdi_pvt *p, int index);
02102
02103 static int my_wink(void *pvt, enum analog_sub sub)
02104 {
02105 struct dahdi_pvt *p = pvt;
02106 int index = analogsub_to_dahdisub(sub);
02107 if (index != SUB_REAL) {
02108 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02109 }
02110 return dahdi_wink(p, index);
02111 }
02112
02113 static void wakeup_sub(struct dahdi_pvt *p, int a);
02114
02115 static int reset_conf(struct dahdi_pvt *p);
02116
02117 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02118
02119 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02120 {
02121 struct ast_frame *f = *dest;
02122 struct dahdi_pvt *p = pvt;
02123 int idx = analogsub_to_dahdisub(analog_index);
02124
02125 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02126 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02127 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
02128
02129 if (f->subclass.integer == 'f') {
02130 if (f->frametype == AST_FRAME_DTMF_END) {
02131
02132 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02133
02134 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02135 struct dahdi_bufferinfo bi = {
02136 .txbufpolicy = p->faxbuf_policy,
02137 .bufsize = p->bufsize,
02138 .numbufs = p->faxbuf_no
02139 };
02140 int res;
02141
02142 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02143 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
02144 } else {
02145 p->bufferoverrideinuse = 1;
02146 }
02147 }
02148 p->faxhandled = 1;
02149 if (p->dsp) {
02150 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02151 ast_dsp_set_features(p->dsp, p->dsp_features);
02152 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
02153 }
02154 if (strcmp(ast_channel_exten(ast), "fax")) {
02155 const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
02156
02157
02158
02159
02160
02161 ast_mutex_unlock(&p->lock);
02162 ast_channel_unlock(ast);
02163 if (ast_exists_extension(ast, target_context, "fax", 1,
02164 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
02165 ast_channel_lock(ast);
02166 ast_mutex_lock(&p->lock);
02167 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
02168
02169 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
02170 if (ast_async_goto(ast, target_context, "fax", 1))
02171 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
02172 } else {
02173 ast_channel_lock(ast);
02174 ast_mutex_lock(&p->lock);
02175 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02176 }
02177 } else {
02178 ast_debug(1, "Already in a fax extension, not redirecting\n");
02179 }
02180 } else {
02181 ast_debug(1, "Fax already handled\n");
02182 }
02183 dahdi_confmute(p, 0);
02184 }
02185 p->subs[idx].f.frametype = AST_FRAME_NULL;
02186 p->subs[idx].f.subclass.integer = 0;
02187 *dest = &p->subs[idx].f;
02188 }
02189 }
02190
02191 static void my_lock_private(void *pvt)
02192 {
02193 struct dahdi_pvt *p = pvt;
02194 ast_mutex_lock(&p->lock);
02195 }
02196
02197 static void my_unlock_private(void *pvt)
02198 {
02199 struct dahdi_pvt *p = pvt;
02200 ast_mutex_unlock(&p->lock);
02201 }
02202
02203 static void my_deadlock_avoidance_private(void *pvt)
02204 {
02205 struct dahdi_pvt *p = pvt;
02206
02207 DEADLOCK_AVOIDANCE(&p->lock);
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02221 {
02222 char ch_name[20];
02223
02224 if (p->channel < CHAN_PSEUDO) {
02225
02226 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02227 } else if (p->channel == CHAN_PSEUDO) {
02228
02229 strcpy(ch_name, "pseudo");
02230 } else {
02231
02232 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02233 }
02234
02235
02236
02237
02238
02239 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02240 "Channel: %s\r\n"
02241 "Uniqueid: %s\r\n"
02242 "DAHDISpan: %d\r\n"
02243 "DAHDIChannel: %s\r\n",
02244 ast_channel_name(chan),
02245 ast_channel_uniqueid(chan),
02246 p->span,
02247 ch_name);
02248 }
02249
02250 #ifdef HAVE_PRI
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02262 {
02263 struct dahdi_pvt *p = pvt;
02264
02265 dahdi_ami_channel_event(p, chan);
02266 }
02267 #endif
02268
02269
02270
02271
02272 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02273 {
02274 struct dahdi_pvt *p = pvt;
02275 int oldval;
02276 int idx = analogsub_to_dahdisub(sub);
02277
02278 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02279 oldval = p->subs[idx].linear;
02280 p->subs[idx].linear = linear_mode ? 1 : 0;
02281 return oldval;
02282 }
02283
02284 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02285 {
02286 struct dahdi_pvt *p = pvt;
02287 int idx = analogsub_to_dahdisub(sub);
02288
02289 p->subs[idx].inthreeway = inthreeway;
02290 }
02291
02292 static int get_alarms(struct dahdi_pvt *p);
02293 static void handle_alarms(struct dahdi_pvt *p, int alms);
02294 static void my_get_and_handle_alarms(void *pvt)
02295 {
02296 int res;
02297 struct dahdi_pvt *p = pvt;
02298
02299 res = get_alarms(p);
02300 handle_alarms(p, res);
02301 }
02302
02303 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02304 {
02305 struct ast_channel *bridged = ast_bridged_channel(chan);
02306
02307 if (bridged && ast_channel_tech(bridged) == &dahdi_tech) {
02308 struct dahdi_pvt *p = ast_channel_tech_pvt(bridged);
02309
02310 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02311 return p->sig_pvt;
02312 }
02313 }
02314 return NULL;
02315 }
02316
02317 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02318 {
02319 struct dahdi_pvt *p = pvt;
02320 int dahdi_sub = analogsub_to_dahdisub(sub);
02321 return p->subs[dahdi_sub].dfd;
02322 }
02323
02324 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02325 {
02326 struct dahdi_pvt *p = pvt;
02327
02328
02329 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02330 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02331 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast_channel_name(ast), strerror(errno));
02332 *cid_rings = cidrings[p->distinctivering - 1];
02333 } else {
02334 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02335 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast_channel_name(ast), strerror(errno));
02336 *cid_rings = p->sendcalleridafter;
02337 }
02338 }
02339
02340 static void my_set_alarm(void *pvt, int in_alarm)
02341 {
02342 struct dahdi_pvt *p = pvt;
02343
02344 p->inalarm = in_alarm;
02345 }
02346
02347 static void my_set_dialing(void *pvt, int is_dialing)
02348 {
02349 struct dahdi_pvt *p = pvt;
02350
02351 p->dialing = is_dialing;
02352 }
02353
02354 static void my_set_outgoing(void *pvt, int is_outgoing)
02355 {
02356 struct dahdi_pvt *p = pvt;
02357
02358 p->outgoing = is_outgoing;
02359 }
02360
02361 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02362 static void my_set_digital(void *pvt, int is_digital)
02363 {
02364 struct dahdi_pvt *p = pvt;
02365
02366 p->digital = is_digital;
02367 }
02368 #endif
02369
02370 #if defined(HAVE_SS7)
02371 static void my_set_inservice(void *pvt, int is_inservice)
02372 {
02373 struct dahdi_pvt *p = pvt;
02374
02375 p->inservice = is_inservice;
02376 }
02377 #endif
02378
02379 #if defined(HAVE_SS7)
02380 static void my_set_locallyblocked(void *pvt, int is_blocked)
02381 {
02382 struct dahdi_pvt *p = pvt;
02383
02384 p->locallyblocked = is_blocked;
02385 }
02386 #endif
02387
02388 #if defined(HAVE_SS7)
02389 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02390 {
02391 struct dahdi_pvt *p = pvt;
02392
02393 p->remotelyblocked = is_blocked;
02394 }
02395 #endif
02396
02397 static void my_set_ringtimeout(void *pvt, int ringt)
02398 {
02399 struct dahdi_pvt *p = pvt;
02400 p->ringt = ringt;
02401 }
02402
02403 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02404 {
02405 struct dahdi_pvt *p = pvt;
02406
02407 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02408 ast_debug(1, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02409 gettimeofday(&p->waitingfordt, NULL);
02410 ast_setstate(ast, AST_STATE_OFFHOOK);
02411 }
02412 }
02413
02414 static int my_check_waitingfordt(void *pvt)
02415 {
02416 struct dahdi_pvt *p = pvt;
02417
02418 if (p->waitingfordt.tv_usec) {
02419 return 1;
02420 }
02421
02422 return 0;
02423 }
02424
02425 static void my_set_confirmanswer(void *pvt, int flag)
02426 {
02427 struct dahdi_pvt *p = pvt;
02428 p->confirmanswer = flag;
02429 }
02430
02431 static int my_check_confirmanswer(void *pvt)
02432 {
02433 struct dahdi_pvt *p = pvt;
02434 if (p->confirmanswer) {
02435 return 1;
02436 }
02437
02438 return 0;
02439 }
02440
02441 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02442 {
02443 struct dahdi_pvt *p = pvt;
02444
02445 p->callwaiting = callwaiting_enable;
02446 }
02447
02448 static void my_cancel_cidspill(void *pvt)
02449 {
02450 struct dahdi_pvt *p = pvt;
02451
02452 ast_free(p->cidspill);
02453 p->cidspill = NULL;
02454 restore_conference(p);
02455 }
02456
02457 static int my_confmute(void *pvt, int mute)
02458 {
02459 struct dahdi_pvt *p = pvt;
02460 return dahdi_confmute(p, mute);
02461 }
02462
02463 static void my_set_pulsedial(void *pvt, int flag)
02464 {
02465 struct dahdi_pvt *p = pvt;
02466 p->pulsedial = flag;
02467 }
02468
02469 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02470 {
02471 struct dahdi_pvt *p = pvt;
02472
02473 p->owner = new_owner;
02474 }
02475
02476 static const char *my_get_orig_dialstring(void *pvt)
02477 {
02478 struct dahdi_pvt *p = pvt;
02479
02480 return p->dialstring;
02481 }
02482
02483 static void my_increase_ss_count(void)
02484 {
02485 ast_mutex_lock(&ss_thread_lock);
02486 ss_thread_count++;
02487 ast_mutex_unlock(&ss_thread_lock);
02488 }
02489
02490 static void my_decrease_ss_count(void)
02491 {
02492 ast_mutex_lock(&ss_thread_lock);
02493 ss_thread_count--;
02494 ast_cond_signal(&ss_thread_complete);
02495 ast_mutex_unlock(&ss_thread_lock);
02496 }
02497
02498 static void my_all_subchannels_hungup(void *pvt)
02499 {
02500 struct dahdi_pvt *p = pvt;
02501 int res, law;
02502
02503 p->faxhandled = 0;
02504 p->didtdd = 0;
02505
02506 if (p->dsp) {
02507 ast_dsp_free(p->dsp);
02508 p->dsp = NULL;
02509 }
02510
02511 p->law = p->law_default;
02512 law = p->law_default;
02513 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02514 if (res < 0)
02515 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02516
02517 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02518
02519 #if 1
02520 {
02521 int i;
02522 p->owner = NULL;
02523
02524 for (i = 0; i < 3; i++) {
02525 p->subs[i].owner = NULL;
02526 }
02527 }
02528 #endif
02529
02530 reset_conf(p);
02531 if (num_restart_pending == 0) {
02532 restart_monitor();
02533 }
02534 }
02535
02536 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02537
02538 static int my_conf_del(void *pvt, enum analog_sub sub)
02539 {
02540 struct dahdi_pvt *p = pvt;
02541 int x = analogsub_to_dahdisub(sub);
02542
02543 return conf_del(p, &p->subs[x], x);
02544 }
02545
02546 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02547
02548 static int my_conf_add(void *pvt, enum analog_sub sub)
02549 {
02550 struct dahdi_pvt *p = pvt;
02551 int x = analogsub_to_dahdisub(sub);
02552
02553 return conf_add(p, &p->subs[x], x, 0);
02554 }
02555
02556 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02557
02558 static int my_complete_conference_update(void *pvt, int needconference)
02559 {
02560 struct dahdi_pvt *p = pvt;
02561 int needconf = needconference;
02562 int x;
02563 int useslavenative;
02564 struct dahdi_pvt *slave = NULL;
02565
02566 useslavenative = isslavenative(p, &slave);
02567
02568
02569
02570 for (x = 0; x < MAX_SLAVES; x++) {
02571 if (p->slaves[x]) {
02572 if (useslavenative)
02573 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02574 else {
02575 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02576 needconf++;
02577 }
02578 }
02579 }
02580
02581 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02582 if (useslavenative)
02583 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02584 else {
02585 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02586 needconf++;
02587 }
02588 }
02589
02590 if (p->master) {
02591 if (isslavenative(p->master, NULL)) {
02592 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02593 } else {
02594 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02595 }
02596 }
02597 if (!needconf) {
02598
02599
02600 p->confno = -1;
02601 }
02602
02603 return 0;
02604 }
02605
02606 static int check_for_conference(struct dahdi_pvt *p);
02607
02608 static int my_check_for_conference(void *pvt)
02609 {
02610 struct dahdi_pvt *p = pvt;
02611 return check_for_conference(p);
02612 }
02613
02614 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)
02615 {
02616 struct dahdi_pvt *p = pvt;
02617 int da, db;
02618 int tchan;
02619 int tinthreeway;
02620
02621 da = analogsub_to_dahdisub(a);
02622 db = analogsub_to_dahdisub(b);
02623
02624 tchan = p->subs[da].chan;
02625 p->subs[da].chan = p->subs[db].chan;
02626 p->subs[db].chan = tchan;
02627
02628 tinthreeway = p->subs[da].inthreeway;
02629 p->subs[da].inthreeway = p->subs[db].inthreeway;
02630 p->subs[db].inthreeway = tinthreeway;
02631
02632 p->subs[da].owner = ast_a;
02633 p->subs[db].owner = ast_b;
02634
02635 if (ast_a)
02636 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02637 if (ast_b)
02638 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02639
02640 wakeup_sub(p, a);
02641 wakeup_sub(p, b);
02642
02643 return;
02644 }
02645
02646
02647
02648
02649
02650
02651
02652
02653 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);
02654
02655 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);
02656
02657 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02658 {
02659 struct ast_callid *callid = NULL;
02660 int callid_created = ast_callid_threadstorage_auto(&callid);
02661 struct dahdi_pvt *p = pvt;
02662 int dsub = analogsub_to_dahdisub(sub);
02663
02664 return dahdi_new_callid_clean(p, state, startpbx, dsub, 0, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02665 }
02666
02667 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02668 static int dahdi_setlaw(int dfd, int law)
02669 {
02670 int res;
02671 res = ioctl(dfd, DAHDI_SETLAW, &law);
02672 if (res)
02673 return res;
02674 return 0;
02675 }
02676 #endif
02677
02678 #if defined(HAVE_PRI)
02679 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)
02680 {
02681 struct dahdi_pvt *p = pvt;
02682 int audio;
02683 int newlaw = -1;
02684 struct ast_callid *callid = NULL;
02685 int callid_created = ast_callid_threadstorage_auto(&callid);
02686
02687 switch (p->sig) {
02688 case SIG_PRI_LIB_HANDLE_CASES:
02689 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02690
02691 break;
02692 }
02693
02694 default:
02695
02696 audio = 1;
02697 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02698 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02699 p->channel, audio, strerror(errno));
02700 }
02701 break;
02702 }
02703
02704 if (law != SIG_PRI_DEFLAW) {
02705 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02706 }
02707
02708 ast_copy_string(p->exten, exten, sizeof(p->exten));
02709
02710 switch (law) {
02711 case SIG_PRI_DEFLAW:
02712 newlaw = 0;
02713 break;
02714 case SIG_PRI_ALAW:
02715 newlaw = DAHDI_LAW_ALAW;
02716 break;
02717 case SIG_PRI_ULAW:
02718 newlaw = DAHDI_LAW_MULAW;
02719 break;
02720 }
02721
02722 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
02723 }
02724 #endif
02725
02726 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02727
02728 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738 static void my_pri_ss7_open_media(void *p)
02739 {
02740 struct dahdi_pvt *pvt = p;
02741 int res;
02742 int dfd;
02743 int set_val;
02744
02745 dfd = pvt->subs[SUB_REAL].dfd;
02746
02747
02748 set_val = 1;
02749 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02750 if (res < 0) {
02751 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02752 pvt->channel, strerror(errno));
02753 }
02754
02755
02756 res = dahdi_setlaw(dfd, pvt->law);
02757 if (res < 0) {
02758 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02759 }
02760
02761
02762 if (pvt->digital) {
02763 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02764 } else {
02765 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02766 pvt->law);
02767 }
02768 if (res < 0) {
02769 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02770 }
02771
02772 if (pvt->dsp_features && pvt->dsp) {
02773 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02774 pvt->dsp_features = 0;
02775 }
02776 }
02777 #endif
02778
02779 #if defined(HAVE_PRI)
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792 static void my_pri_dial_digits(void *p, const char *dial_string)
02793 {
02794 struct dahdi_dialoperation zo = {
02795 .op = DAHDI_DIAL_OP_APPEND,
02796 };
02797 struct dahdi_pvt *pvt = p;
02798 int res;
02799
02800 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02801 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02802 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02803 if (res) {
02804 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02805 pvt->channel, dial_string, strerror(errno));
02806 } else {
02807 pvt->dialing = 1;
02808 }
02809 }
02810 #endif
02811
02812 static int unalloc_sub(struct dahdi_pvt *p, int x);
02813
02814 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02815 {
02816 struct dahdi_pvt *p = pvt;
02817
02818 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02819 }
02820
02821 static int alloc_sub(struct dahdi_pvt *p, int x);
02822
02823 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02824 {
02825 struct dahdi_pvt *p = pvt;
02826
02827 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02828 }
02829
02830 static int has_voicemail(struct dahdi_pvt *p);
02831
02832 static int my_has_voicemail(void *pvt)
02833 {
02834 struct dahdi_pvt *p = pvt;
02835
02836 return has_voicemail(p);
02837 }
02838
02839 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02840 {
02841 struct dahdi_pvt *p = pvt;
02842 int index;
02843
02844 index = analogsub_to_dahdisub(sub);
02845
02846 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02847 }
02848
02849 static enum analog_event dahdievent_to_analogevent(int event)
02850 {
02851 enum analog_event res;
02852
02853 switch (event) {
02854 case DAHDI_EVENT_ONHOOK:
02855 res = ANALOG_EVENT_ONHOOK;
02856 break;
02857 case DAHDI_EVENT_RINGOFFHOOK:
02858 res = ANALOG_EVENT_RINGOFFHOOK;
02859 break;
02860 case DAHDI_EVENT_WINKFLASH:
02861 res = ANALOG_EVENT_WINKFLASH;
02862 break;
02863 case DAHDI_EVENT_ALARM:
02864 res = ANALOG_EVENT_ALARM;
02865 break;
02866 case DAHDI_EVENT_NOALARM:
02867 res = ANALOG_EVENT_NOALARM;
02868 break;
02869 case DAHDI_EVENT_DIALCOMPLETE:
02870 res = ANALOG_EVENT_DIALCOMPLETE;
02871 break;
02872 case DAHDI_EVENT_RINGERON:
02873 res = ANALOG_EVENT_RINGERON;
02874 break;
02875 case DAHDI_EVENT_RINGEROFF:
02876 res = ANALOG_EVENT_RINGEROFF;
02877 break;
02878 case DAHDI_EVENT_HOOKCOMPLETE:
02879 res = ANALOG_EVENT_HOOKCOMPLETE;
02880 break;
02881 case DAHDI_EVENT_PULSE_START:
02882 res = ANALOG_EVENT_PULSE_START;
02883 break;
02884 case DAHDI_EVENT_POLARITY:
02885 res = ANALOG_EVENT_POLARITY;
02886 break;
02887 case DAHDI_EVENT_RINGBEGIN:
02888 res = ANALOG_EVENT_RINGBEGIN;
02889 break;
02890 case DAHDI_EVENT_EC_DISABLED:
02891 res = ANALOG_EVENT_EC_DISABLED;
02892 break;
02893 case DAHDI_EVENT_REMOVED:
02894 res = ANALOG_EVENT_REMOVED;
02895 break;
02896 case DAHDI_EVENT_NEONMWI_ACTIVE:
02897 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02898 break;
02899 case DAHDI_EVENT_NEONMWI_INACTIVE:
02900 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02901 break;
02902 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02903 case DAHDI_EVENT_TX_CED_DETECTED:
02904 res = ANALOG_EVENT_TX_CED_DETECTED;
02905 break;
02906 case DAHDI_EVENT_RX_CED_DETECTED:
02907 res = ANALOG_EVENT_RX_CED_DETECTED;
02908 break;
02909 case DAHDI_EVENT_EC_NLP_DISABLED:
02910 res = ANALOG_EVENT_EC_NLP_DISABLED;
02911 break;
02912 case DAHDI_EVENT_EC_NLP_ENABLED:
02913 res = ANALOG_EVENT_EC_NLP_ENABLED;
02914 break;
02915 #endif
02916 case DAHDI_EVENT_PULSEDIGIT:
02917 res = ANALOG_EVENT_PULSEDIGIT;
02918 break;
02919 case DAHDI_EVENT_DTMFDOWN:
02920 res = ANALOG_EVENT_DTMFDOWN;
02921 break;
02922 case DAHDI_EVENT_DTMFUP:
02923 res = ANALOG_EVENT_DTMFUP;
02924 break;
02925 default:
02926 switch(event & 0xFFFF0000) {
02927 case DAHDI_EVENT_PULSEDIGIT:
02928 case DAHDI_EVENT_DTMFDOWN:
02929 case DAHDI_EVENT_DTMFUP:
02930
02931
02932
02933
02934 return event;
02935 }
02936
02937 res = ANALOG_EVENT_ERROR;
02938 break;
02939 }
02940
02941 return res;
02942 }
02943
02944 static inline int dahdi_wait_event(int fd);
02945
02946 static int my_wait_event(void *pvt)
02947 {
02948 struct dahdi_pvt *p = pvt;
02949
02950 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02951 }
02952
02953 static int my_get_event(void *pvt)
02954 {
02955 struct dahdi_pvt *p = pvt;
02956 int res;
02957
02958 if (p->fake_event) {
02959 res = p->fake_event;
02960 p->fake_event = 0;
02961 } else
02962 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02963
02964 return dahdievent_to_analogevent(res);
02965 }
02966
02967 static int my_is_off_hook(void *pvt)
02968 {
02969 struct dahdi_pvt *p = pvt;
02970 int res;
02971 struct dahdi_params par;
02972
02973 memset(&par, 0, sizeof(par));
02974
02975 if (p->subs[SUB_REAL].dfd > -1)
02976 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02977 else {
02978
02979 res = 0;
02980 par.rxisoffhook = 0;
02981 }
02982 if (res) {
02983 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02984 }
02985
02986 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02987
02988
02989
02990 return (par.rxbits > -1) || par.rxisoffhook;
02991 }
02992
02993 return par.rxisoffhook;
02994 }
02995
02996 static void dahdi_enable_ec(struct dahdi_pvt *p);
02997 static void dahdi_disable_ec(struct dahdi_pvt *p);
02998
02999 static int my_set_echocanceller(void *pvt, int enable)
03000 {
03001 struct dahdi_pvt *p = pvt;
03002
03003 if (enable)
03004 dahdi_enable_ec(p);
03005 else
03006 dahdi_disable_ec(p);
03007
03008 return 0;
03009 }
03010
03011 static int dahdi_ring_phone(struct dahdi_pvt *p);
03012
03013 static int my_ring(void *pvt)
03014 {
03015 struct dahdi_pvt *p = pvt;
03016
03017 return dahdi_ring_phone(p);
03018 }
03019
03020 static int my_flash(void *pvt)
03021 {
03022 struct dahdi_pvt *p = pvt;
03023 int func = DAHDI_FLASH;
03024 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
03025 }
03026
03027 static inline int dahdi_set_hook(int fd, int hs);
03028
03029 static int my_off_hook(void *pvt)
03030 {
03031 struct dahdi_pvt *p = pvt;
03032 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03033 }
03034
03035 static void my_set_needringing(void *pvt, int value)
03036 {
03037 struct dahdi_pvt *p = pvt;
03038 p->subs[SUB_REAL].needringing = value;
03039 }
03040
03041 static void my_set_polarity(void *pvt, int value)
03042 {
03043 struct dahdi_pvt *p = pvt;
03044
03045 if (p->channel == CHAN_PSEUDO) {
03046 return;
03047 }
03048 p->polarity = value;
03049 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
03050 }
03051
03052 static void my_start_polarityswitch(void *pvt)
03053 {
03054 struct dahdi_pvt *p = pvt;
03055
03056 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03057 my_set_polarity(pvt, 0);
03058 }
03059 }
03060
03061 static void my_answer_polarityswitch(void *pvt)
03062 {
03063 struct dahdi_pvt *p = pvt;
03064
03065 if (!p->answeronpolarityswitch) {
03066 return;
03067 }
03068
03069 my_set_polarity(pvt, 1);
03070 }
03071
03072 static void my_hangup_polarityswitch(void *pvt)
03073 {
03074 struct dahdi_pvt *p = pvt;
03075
03076 if (!p->hanguponpolarityswitch) {
03077 return;
03078 }
03079
03080 if (p->answeronpolarityswitch) {
03081 my_set_polarity(pvt, 0);
03082 } else {
03083 my_set_polarity(pvt, 1);
03084 }
03085 }
03086
03087 static int my_start(void *pvt)
03088 {
03089 struct dahdi_pvt *p = pvt;
03090 int x = DAHDI_START;
03091
03092 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03093 }
03094
03095 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03096 {
03097 int index = analogsub_to_dahdisub(sub);
03098 int res;
03099 struct dahdi_pvt *p = pvt;
03100 struct dahdi_dialoperation ddop;
03101
03102 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03103 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03104 return -1;
03105 }
03106
03107 if (sub != ANALOG_SUB_REAL) {
03108 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03109 dop->dialstr, p->channel, sub);
03110 return -1;
03111 }
03112
03113 ddop.op = DAHDI_DIAL_OP_REPLACE;
03114 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03115
03116 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03117
03118 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03119 if (res == -1) {
03120 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
03121 }
03122
03123 return res;
03124 }
03125
03126 static void dahdi_train_ec(struct dahdi_pvt *p);
03127
03128 static int my_train_echocanceller(void *pvt)
03129 {
03130 struct dahdi_pvt *p = pvt;
03131
03132 dahdi_train_ec(p);
03133
03134 return 0;
03135 }
03136
03137 static int my_is_dialing(void *pvt, enum analog_sub sub)
03138 {
03139 struct dahdi_pvt *p = pvt;
03140 int index;
03141 int x;
03142
03143 index = analogsub_to_dahdisub(sub);
03144
03145 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03146 ast_debug(1, "DAHDI_DIALING ioctl failed!\n");
03147 return -1;
03148 }
03149
03150 return x;
03151 }
03152
03153 static int my_on_hook(void *pvt)
03154 {
03155 struct dahdi_pvt *p = pvt;
03156 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03157 }
03158
03159 #if defined(HAVE_PRI)
03160 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03161 {
03162 struct dahdi_pvt *old_chan = chan_old;
03163 struct dahdi_pvt *new_chan = chan_new;
03164
03165 new_chan->owner = old_chan->owner;
03166 old_chan->owner = NULL;
03167 if (new_chan->owner) {
03168 ast_channel_tech_pvt_set(new_chan->owner, new_chan);
03169 ast_channel_internal_fd_set(new_chan->owner, 0, new_chan->subs[SUB_REAL].dfd);
03170 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03171 old_chan->subs[SUB_REAL].owner = NULL;
03172 }
03173
03174 new_chan->dsp = old_chan->dsp;
03175 new_chan->dsp_features = old_chan->dsp_features;
03176 old_chan->dsp = NULL;
03177 old_chan->dsp_features = 0;
03178
03179
03180 new_chan->dialing = old_chan->dialing;
03181 new_chan->digital = old_chan->digital;
03182 new_chan->outgoing = old_chan->outgoing;
03183 old_chan->dialing = 0;
03184 old_chan->digital = 0;
03185 old_chan->outgoing = 0;
03186
03187
03188 new_chan->law = old_chan->law;
03189 strcpy(new_chan->dialstring, old_chan->dialstring);
03190 }
03191 #endif
03192
03193 #if defined(HAVE_PRI)
03194 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03195 {
03196 switch (tone) {
03197 case SIG_PRI_TONE_RINGTONE:
03198 return DAHDI_TONE_RINGTONE;
03199 case SIG_PRI_TONE_STUTTER:
03200 return DAHDI_TONE_STUTTER;
03201 case SIG_PRI_TONE_CONGESTION:
03202 return DAHDI_TONE_CONGESTION;
03203 case SIG_PRI_TONE_DIALTONE:
03204 return DAHDI_TONE_DIALTONE;
03205 case SIG_PRI_TONE_DIALRECALL:
03206 return DAHDI_TONE_DIALRECALL;
03207 case SIG_PRI_TONE_INFO:
03208 return DAHDI_TONE_INFO;
03209 case SIG_PRI_TONE_BUSY:
03210 return DAHDI_TONE_BUSY;
03211 default:
03212 return -1;
03213 }
03214 }
03215 #endif
03216
03217 #if defined(HAVE_PRI)
03218 static int pri_destroy_dchan(struct sig_pri_span *pri);
03219
03220 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03221 {
03222 int x;
03223
03224 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03225 switch (x) {
03226 case DAHDI_EVENT_NONE:
03227 break;
03228 case DAHDI_EVENT_ALARM:
03229 case DAHDI_EVENT_NOALARM:
03230 if (sig_pri_is_alarm_ignored(pri)) {
03231 break;
03232 }
03233
03234 default:
03235 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03236 event2str(x), x, pri->span);
03237 break;
03238 }
03239
03240 switch (x) {
03241 case DAHDI_EVENT_ALARM:
03242 pri_event_alarm(pri, index, 0);
03243 break;
03244 case DAHDI_EVENT_NOALARM:
03245 pri_event_noalarm(pri, index, 0);
03246 break;
03247 case DAHDI_EVENT_REMOVED:
03248 pri_destroy_dchan(pri);
03249 break;
03250 default:
03251 break;
03252 }
03253 }
03254 #endif
03255
03256 #if defined(HAVE_PRI)
03257 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03258 {
03259 struct dahdi_pvt *p = pvt;
03260
03261 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03262 }
03263 #endif
03264
03265 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03277 {
03278 struct dahdi_pvt *p = pvt;
03279
03280 ast_copy_string(p->cid_num,
03281 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03282 sizeof(p->cid_num));
03283 ast_copy_string(p->cid_name,
03284 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03285 sizeof(p->cid_name));
03286 ast_copy_string(p->cid_subaddr,
03287 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03288 sizeof(p->cid_subaddr));
03289 p->cid_ton = caller->id.number.plan;
03290 p->callingpres = ast_party_id_presentation(&caller->id);
03291 if (caller->id.tag) {
03292 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03293 }
03294 ast_copy_string(p->cid_ani,
03295 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03296 sizeof(p->cid_ani));
03297 p->cid_ani2 = caller->ani2;
03298 }
03299 #endif
03300
03301 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312 static void my_set_dnid(void *pvt, const char *dnid)
03313 {
03314 struct dahdi_pvt *p = pvt;
03315
03316 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03317 }
03318 #endif
03319
03320 #if defined(HAVE_PRI)
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331 static void my_set_rdnis(void *pvt, const char *rdnis)
03332 {
03333 struct dahdi_pvt *p = pvt;
03334
03335 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03336 }
03337 #endif
03338
03339 #if defined(HAVE_PRI)
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03365 {
03366 char *dial;
03367 struct dahdi_pvt *pvt;
03368 AST_DECLARE_APP_ARGS(args,
03369 AST_APP_ARG(tech);
03370 AST_APP_ARG(group);
03371
03372
03373
03374 );
03375
03376 pvt = priv;
03377 dial = ast_strdupa(pvt->dialstring);
03378 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03379 if (!args.tech) {
03380 ast_copy_string(buf, pvt->dialstring, buf_size);
03381 return;
03382 }
03383 if (!args.group) {
03384
03385 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03386 return;
03387 }
03388 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03389
03390
03391 ast_copy_string(buf, pvt->dialstring, buf_size);
03392 return;
03393 }
03394
03395 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03396 }
03397 #endif
03398
03399 #if defined(HAVE_PRI)
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03412 {
03413 unsigned idx;
03414 unsigned num_b_chans;
03415 unsigned in_use;
03416 unsigned in_alarm;
03417 enum ast_device_state new_state;
03418
03419
03420 num_b_chans = 0;
03421 in_use = 0;
03422 in_alarm = 1;
03423 for (idx = pri->numchans; idx--;) {
03424 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03425
03426 ++num_b_chans;
03427 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03428 ++in_use;
03429 }
03430 if (!pri->pvts[idx]->inalarm) {
03431
03432 in_alarm = 0;
03433 }
03434 }
03435 }
03436
03437
03438 if (in_alarm) {
03439 new_state = AST_DEVICE_UNAVAILABLE;
03440 } else {
03441 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03442 }
03443 if (pri->congestion_devstate != new_state) {
03444 pri->congestion_devstate = new_state;
03445 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03446 }
03447 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03448
03449 if (in_alarm) {
03450 new_state = AST_DEVICE_UNAVAILABLE;
03451 } else if (!in_use) {
03452 new_state = AST_DEVICE_NOT_INUSE;
03453 } else if (!pri->user_busy_threshold) {
03454 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03455 } else {
03456 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03457 : AST_DEVICE_BUSY;
03458 }
03459 if (pri->threshold_devstate != new_state) {
03460 pri->threshold_devstate = new_state;
03461 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03462 }
03463 #endif
03464 }
03465 #endif
03466
03467 #if defined(HAVE_PRI)
03468
03469
03470
03471
03472
03473
03474
03475 static void my_module_ref(void)
03476 {
03477 ast_module_ref(ast_module_info->self);
03478 }
03479 #endif
03480
03481 #if defined(HAVE_PRI)
03482
03483
03484
03485
03486
03487
03488
03489 static void my_module_unref(void)
03490 {
03491 ast_module_unref(ast_module_info->self);
03492 }
03493 #endif
03494
03495 #if defined(HAVE_PRI)
03496 #if defined(HAVE_PRI_CALL_WAITING)
03497 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03498 #endif
03499 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03500
03501 struct sig_pri_callback sig_pri_callbacks =
03502 {
03503 .handle_dchan_exception = my_handle_dchan_exception,
03504 .play_tone = my_pri_play_tone,
03505 .set_echocanceller = my_set_echocanceller,
03506 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03507 .lock_private = my_lock_private,
03508 .unlock_private = my_unlock_private,
03509 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03510 .new_ast_channel = my_new_pri_ast_channel,
03511 .fixup_chans = my_pri_fixup_chans,
03512 .set_alarm = my_set_alarm,
03513 .set_dialing = my_set_dialing,
03514 .set_outgoing = my_set_outgoing,
03515 .set_digital = my_set_digital,
03516 .set_callerid = my_set_callerid,
03517 .set_dnid = my_set_dnid,
03518 .set_rdnis = my_set_rdnis,
03519 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03520 #if defined(HAVE_PRI_CALL_WAITING)
03521 .init_config = my_pri_init_config,
03522 #endif
03523 .get_orig_dialstring = my_get_orig_dialstring,
03524 .make_cc_dialstring = my_pri_make_cc_dialstring,
03525 .update_span_devstate = dahdi_pri_update_span_devstate,
03526 .module_ref = my_module_ref,
03527 .module_unref = my_module_unref,
03528 .dial_digits = my_pri_dial_digits,
03529 .open_media = my_pri_ss7_open_media,
03530 .ami_channel_event = my_ami_channel_event,
03531 };
03532 #endif
03533
03534 #if defined(HAVE_SS7)
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03546 {
03547 int event;
03548
03549 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03550 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03551 linkset->span, which);
03552 return;
03553 }
03554 switch (event) {
03555 case DAHDI_EVENT_NONE:
03556 break;
03557 case DAHDI_EVENT_ALARM:
03558 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03559 event2str(event), event, linkset->span, which);
03560 sig_ss7_link_alarm(linkset, which);
03561 break;
03562 case DAHDI_EVENT_NOALARM:
03563 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03564 event2str(event), event, linkset->span, which);
03565 sig_ss7_link_noalarm(linkset, which);
03566 break;
03567 default:
03568 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03569 event2str(event), event, linkset->span, which);
03570 break;
03571 }
03572 }
03573 #endif
03574
03575 #if defined(HAVE_SS7)
03576 static void my_ss7_set_loopback(void *pvt, int enable)
03577 {
03578 struct dahdi_pvt *p = pvt;
03579
03580 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03581 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03582 strerror(errno));
03583 }
03584 }
03585 #endif
03586
03587 #if defined(HAVE_SS7)
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602 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)
03603 {
03604 struct dahdi_pvt *p = pvt;
03605 int audio;
03606 int newlaw;
03607 struct ast_callid *callid = NULL;
03608 int callid_created = ast_callid_threadstorage_auto(&callid);
03609
03610
03611 audio = 1;
03612 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03613 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03614 p->channel, audio, strerror(errno));
03615
03616 if (law != SIG_SS7_DEFLAW) {
03617 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03618 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03619 }
03620
03621 ast_copy_string(p->exten, exten, sizeof(p->exten));
03622
03623 newlaw = -1;
03624 switch (law) {
03625 case SIG_SS7_DEFLAW:
03626 newlaw = 0;
03627 break;
03628 case SIG_SS7_ALAW:
03629 newlaw = DAHDI_LAW_ALAW;
03630 break;
03631 case SIG_SS7_ULAW:
03632 newlaw = DAHDI_LAW_MULAW;
03633 break;
03634 }
03635 return dahdi_new_callid_clean(p, state, 0, SUB_REAL, newlaw, requestor ? ast_channel_linkedid(requestor) : "", callid, callid_created);
03636 }
03637 #endif
03638
03639 #if defined(HAVE_SS7)
03640 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03641 {
03642 switch (tone) {
03643 case SIG_SS7_TONE_RINGTONE:
03644 return DAHDI_TONE_RINGTONE;
03645 case SIG_SS7_TONE_STUTTER:
03646 return DAHDI_TONE_STUTTER;
03647 case SIG_SS7_TONE_CONGESTION:
03648 return DAHDI_TONE_CONGESTION;
03649 case SIG_SS7_TONE_DIALTONE:
03650 return DAHDI_TONE_DIALTONE;
03651 case SIG_SS7_TONE_DIALRECALL:
03652 return DAHDI_TONE_DIALRECALL;
03653 case SIG_SS7_TONE_INFO:
03654 return DAHDI_TONE_INFO;
03655 case SIG_SS7_TONE_BUSY:
03656 return DAHDI_TONE_BUSY;
03657 default:
03658 return -1;
03659 }
03660 }
03661 #endif
03662
03663 #if defined(HAVE_SS7)
03664 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03665 {
03666 struct dahdi_pvt *p = pvt;
03667
03668 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03669 }
03670 #endif
03671
03672 #if defined(HAVE_SS7)
03673 struct sig_ss7_callback sig_ss7_callbacks =
03674 {
03675 .lock_private = my_lock_private,
03676 .unlock_private = my_unlock_private,
03677 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03678
03679 .set_echocanceller = my_set_echocanceller,
03680 .set_loopback = my_ss7_set_loopback,
03681
03682 .new_ast_channel = my_new_ss7_ast_channel,
03683 .play_tone = my_ss7_play_tone,
03684
03685 .handle_link_exception = my_handle_link_exception,
03686 .set_alarm = my_set_alarm,
03687 .set_dialing = my_set_dialing,
03688 .set_outgoing = my_set_outgoing,
03689 .set_digital = my_set_digital,
03690 .set_inservice = my_set_inservice,
03691 .set_locallyblocked = my_set_locallyblocked,
03692 .set_remotelyblocked = my_set_remotelyblocked,
03693 .set_callerid = my_set_callerid,
03694 .set_dnid = my_set_dnid,
03695 .open_media = my_pri_ss7_open_media,
03696 };
03697 #endif
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717 static void notify_message(char *mailbox_full, int thereornot)
03718 {
03719 char s[sizeof(mwimonitornotify) + 80];
03720 struct ast_event *event;
03721 char *mailbox, *context;
03722
03723
03724 context = mailbox = ast_strdupa(mailbox_full);
03725 strsep(&context, "@");
03726 if (ast_strlen_zero(context))
03727 context = "default";
03728
03729 if (!(event = ast_event_new(AST_EVENT_MWI,
03730 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03731 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03732 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03733 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03734 AST_EVENT_IE_END))) {
03735 return;
03736 }
03737
03738 ast_event_queue_and_cache(event);
03739
03740 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03741 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03742 ast_safe_system(s);
03743 }
03744 }
03745
03746 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03747 {
03748 struct dahdi_pvt *p = pvt;
03749
03750 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03751 return;
03752
03753 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03754 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03755 notify_message(p->mailbox, 1);
03756 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03757 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03758 notify_message(p->mailbox, 0);
03759 }
03760
03761
03762 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03763 ast_hangup(chan);
03764 return;
03765 }
03766 }
03767
03768 static int my_have_progressdetect(void *pvt)
03769 {
03770 struct dahdi_pvt *p = pvt;
03771
03772 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03773 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03774 return 1;
03775 } else {
03776
03777 return 0;
03778 }
03779 }
03780
03781 struct analog_callback analog_callbacks =
03782 {
03783 .play_tone = my_play_tone,
03784 .get_event = my_get_event,
03785 .wait_event = my_wait_event,
03786 .is_off_hook = my_is_off_hook,
03787 .set_echocanceller = my_set_echocanceller,
03788 .ring = my_ring,
03789 .flash = my_flash,
03790 .off_hook = my_off_hook,
03791 .dial_digits = my_dial_digits,
03792 .train_echocanceller = my_train_echocanceller,
03793 .on_hook = my_on_hook,
03794 .is_dialing = my_is_dialing,
03795 .allocate_sub = my_allocate_sub,
03796 .unallocate_sub = my_unallocate_sub,
03797 .swap_subs = my_swap_subchannels,
03798 .has_voicemail = my_has_voicemail,
03799 .check_for_conference = my_check_for_conference,
03800 .conf_add = my_conf_add,
03801 .conf_del = my_conf_del,
03802 .complete_conference_update = my_complete_conference_update,
03803 .start = my_start,
03804 .all_subchannels_hungup = my_all_subchannels_hungup,
03805 .lock_private = my_lock_private,
03806 .unlock_private = my_unlock_private,
03807 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03808 .handle_dtmf = my_handle_dtmf,
03809 .wink = my_wink,
03810 .new_ast_channel = my_new_analog_ast_channel,
03811 .dsp_set_digitmode = my_dsp_set_digitmode,
03812 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03813 .send_callerid = my_send_callerid,
03814 .callwait = my_callwait,
03815 .stop_callwait = my_stop_callwait,
03816 .get_callerid = my_get_callerid,
03817 .start_cid_detect = my_start_cid_detect,
03818 .stop_cid_detect = my_stop_cid_detect,
03819 .handle_notify_message = my_handle_notify_message,
03820 .increase_ss_count = my_increase_ss_count,
03821 .decrease_ss_count = my_decrease_ss_count,
03822 .distinctive_ring = my_distinctive_ring,
03823 .set_linear_mode = my_set_linear_mode,
03824 .set_inthreeway = my_set_inthreeway,
03825 .get_and_handle_alarms = my_get_and_handle_alarms,
03826 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03827 .get_sub_fd = my_get_sub_fd,
03828 .set_cadence = my_set_cadence,
03829 .set_alarm = my_set_alarm,
03830 .set_dialing = my_set_dialing,
03831 .set_outgoing = my_set_outgoing,
03832 .set_ringtimeout = my_set_ringtimeout,
03833 .set_waitingfordt = my_set_waitingfordt,
03834 .check_waitingfordt = my_check_waitingfordt,
03835 .set_confirmanswer = my_set_confirmanswer,
03836 .check_confirmanswer = my_check_confirmanswer,
03837 .set_callwaiting = my_set_callwaiting,
03838 .cancel_cidspill = my_cancel_cidspill,
03839 .confmute = my_confmute,
03840 .set_pulsedial = my_set_pulsedial,
03841 .set_new_owner = my_set_new_owner,
03842 .get_orig_dialstring = my_get_orig_dialstring,
03843 .set_needringing = my_set_needringing,
03844 .set_polarity = my_set_polarity,
03845 .start_polarityswitch = my_start_polarityswitch,
03846 .answer_polarityswitch = my_answer_polarityswitch,
03847 .hangup_polarityswitch = my_hangup_polarityswitch,
03848 .have_progressdetect = my_have_progressdetect,
03849 };
03850
03851
03852 static struct dahdi_pvt *round_robin[32];
03853
03854 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03855 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03856 {
03857 int res;
03858 if (p->subs[SUB_REAL].owner == ast)
03859 res = 0;
03860 else if (p->subs[SUB_CALLWAIT].owner == ast)
03861 res = 1;
03862 else if (p->subs[SUB_THREEWAY].owner == ast)
03863 res = 2;
03864 else {
03865 res = -1;
03866 if (!nullok)
03867 ast_log(LOG_WARNING,
03868 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03869 ast ? ast_channel_name(ast) : "", p->channel, fname, line);
03870 }
03871 return res;
03872 }
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03890 {
03891 for (;;) {
03892 if (!pvt->subs[sub_idx].owner) {
03893
03894 break;
03895 }
03896 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03897
03898 break;
03899 }
03900
03901 DEADLOCK_AVOIDANCE(&pvt->lock);
03902 }
03903 }
03904
03905 static void wakeup_sub(struct dahdi_pvt *p, int a)
03906 {
03907 dahdi_lock_sub_owner(p, a);
03908 if (p->subs[a].owner) {
03909 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03910 ast_channel_unlock(p->subs[a].owner);
03911 }
03912 }
03913
03914 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03915 {
03916 for (;;) {
03917 if (p->owner) {
03918 if (ast_channel_trylock(p->owner)) {
03919 DEADLOCK_AVOIDANCE(&p->lock);
03920 } else {
03921 ast_queue_frame(p->owner, f);
03922 ast_channel_unlock(p->owner);
03923 break;
03924 }
03925 } else
03926 break;
03927 }
03928 }
03929
03930 static void handle_clear_alarms(struct dahdi_pvt *p)
03931 {
03932 #if defined(HAVE_PRI)
03933 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03934 return;
03935 }
03936 #endif
03937
03938 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03939 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03940
03941
03942
03943
03944
03945 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03946 }
03947 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03948 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03949
03950
03951
03952
03953
03954 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03955 }
03956 }
03957
03958 #ifdef HAVE_OPENR2
03959
03960 static int dahdi_r2_answer(struct dahdi_pvt *p)
03961 {
03962 int res = 0;
03963
03964
03965
03966 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03967 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03968 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03969 if (!double_answer) {
03970
03971
03972 res = openr2_chan_answer_call(p->r2chan);
03973 } else if (wants_double_answer) {
03974 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03975 } else {
03976 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03977 }
03978 #else
03979 res = openr2_chan_answer_call(p->r2chan);
03980 #endif
03981 return res;
03982 }
03983
03984
03985
03986
03987 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03988 {
03989 openr2_calling_party_category_t cat;
03990 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03991 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
03992 if (ast_strlen_zero(catstr)) {
03993 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03994 ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
03995 return p->mfcr2_category;
03996 }
03997 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03998 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03999 catstr, ast_channel_name(c), openr2_proto_get_category_string(p->mfcr2_category));
04000 return p->mfcr2_category;
04001 }
04002 ast_debug(1, "Using category %s\n", catstr);
04003 return cat;
04004 }
04005
04006 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
04007 {
04008 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04009 ast_mutex_lock(&p->lock);
04010 if (p->mfcr2call) {
04011 ast_mutex_unlock(&p->lock);
04012
04013
04014
04015
04016
04017 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
04018 return;
04019 }
04020 p->mfcr2call = 1;
04021
04022 p->cid_name[0] = '\0';
04023 p->cid_num[0] = '\0';
04024 p->cid_subaddr[0] = '\0';
04025 p->rdnis[0] = '\0';
04026 p->exten[0] = '\0';
04027 p->mfcr2_ani_index = '\0';
04028 p->mfcr2_dnis_index = '\0';
04029 p->mfcr2_dnis_matched = 0;
04030 p->mfcr2_answer_pending = 0;
04031 p->mfcr2_call_accepted = 0;
04032 ast_mutex_unlock(&p->lock);
04033 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
04034 }
04035
04036 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
04037 {
04038 int res;
04039 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04040 ast_mutex_lock(&p->lock);
04041 p->inalarm = alarm ? 1 : 0;
04042 if (p->inalarm) {
04043 res = get_alarms(p);
04044 handle_alarms(p, res);
04045 } else {
04046 handle_clear_alarms(p);
04047 }
04048 ast_mutex_unlock(&p->lock);
04049 }
04050
04051 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
04052 {
04053 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
04054 }
04055
04056 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
04057 {
04058 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04059 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
04060 if (p->owner) {
04061 ast_channel_hangupcause_set(p->owner, AST_CAUSE_PROTOCOL_ERROR);
04062 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04063 }
04064 ast_mutex_lock(&p->lock);
04065 p->mfcr2call = 0;
04066 ast_mutex_unlock(&p->lock);
04067 }
04068
04069 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
04070 {
04071 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04072 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04073 p->channel, openr2_proto_get_disconnect_string(cause));
04074
04075 openr2_chan_set_idle(p->r2chan);
04076 ast_mutex_lock(&p->lock);
04077 p->mfcr2call = 0;
04078 ast_mutex_unlock(&p->lock);
04079 }
04080 }
04081
04082 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04083 {
04084 struct dahdi_pvt *p;
04085 struct ast_channel *c;
04086 struct ast_callid *callid = NULL;
04087 int callid_created = ast_callid_threadstorage_auto(&callid);
04088 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04089 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04090 openr2_proto_get_category_string(category));
04091 p = openr2_chan_get_client_data(r2chan);
04092
04093 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04094 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04095 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04096 goto dahdi_r2_on_call_offered_cleanup;
04097 }
04098 ast_mutex_lock(&p->lock);
04099 p->mfcr2_recvd_category = category;
04100
04101 if (!p->use_callerid) {
04102 ast_debug(1, "No CID allowed in configuration, CID is being cleared!\n");
04103 p->cid_num[0] = 0;
04104 p->cid_name[0] = 0;
04105 }
04106
04107 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04108 ast_debug(1, "Setting exten => s because of immediate or 0 DNIS configured\n");
04109 p->exten[0] = 's';
04110 p->exten[1] = 0;
04111 }
04112 ast_mutex_unlock(&p->lock);
04113 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04114 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04115 p->channel, p->exten, p->context);
04116 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04117 goto dahdi_r2_on_call_offered_cleanup;
04118 }
04119 if (!p->mfcr2_accept_on_offer) {
04120
04121 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04122 if (c) {
04123
04124
04125
04126 goto dahdi_r2_on_call_offered_cleanup;
04127 }
04128 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04129 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04130 } else if (p->mfcr2_charge_calls) {
04131 ast_debug(1, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04132 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04133 } else {
04134 ast_debug(1, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04135 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04136 }
04137
04138 dahdi_r2_on_call_offered_cleanup:
04139 ast_callid_threadstorage_auto_clean(callid, callid_created);
04140 }
04141
04142 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04143 {
04144 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04145 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04146 ast_mutex_lock(&p->lock);
04147 p->mfcr2call = 0;
04148 ast_mutex_unlock(&p->lock);
04149 }
04150
04151 static void dahdi_enable_ec(struct dahdi_pvt *p);
04152 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04153 {
04154 struct dahdi_pvt *p = NULL;
04155 struct ast_channel *c = NULL;
04156 struct ast_callid *callid = NULL;
04157 int callid_created = ast_callid_threadstorage_auto(&callid);
04158 p = openr2_chan_get_client_data(r2chan);
04159 dahdi_enable_ec(p);
04160 p->mfcr2_call_accepted = 1;
04161
04162 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04163 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04164
04165
04166
04167
04168 if (!p->mfcr2_accept_on_offer) {
04169 openr2_chan_disable_read(r2chan);
04170 if (p->mfcr2_answer_pending) {
04171 ast_debug(1, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04172 dahdi_r2_answer(p);
04173 }
04174 goto dahdi_r2_on_call_accepted_cleanup;
04175 }
04176 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL, callid);
04177 if (c) {
04178
04179
04180 openr2_chan_disable_read(r2chan);
04181 goto dahdi_r2_on_call_accepted_cleanup;
04182 }
04183 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04184
04185 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04186 goto dahdi_r2_on_call_accepted_cleanup;
04187 }
04188
04189 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04190 p->subs[SUB_REAL].needringing = 1;
04191 p->dialing = 0;
04192
04193 openr2_chan_disable_read(r2chan);
04194
04195 dahdi_r2_on_call_accepted_cleanup:
04196 ast_callid_threadstorage_auto_clean(callid, callid_created);
04197 }
04198
04199 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04200 {
04201 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04202 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04203 p->subs[SUB_REAL].needanswer = 1;
04204 }
04205
04206 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04207 {
04208
04209 }
04210
04211 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04212 {
04213 switch (cause) {
04214 case OR2_CAUSE_BUSY_NUMBER:
04215 return AST_CAUSE_BUSY;
04216 case OR2_CAUSE_NETWORK_CONGESTION:
04217 return AST_CAUSE_CONGESTION;
04218 case OR2_CAUSE_OUT_OF_ORDER:
04219 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04220 case OR2_CAUSE_UNALLOCATED_NUMBER:
04221 return AST_CAUSE_UNREGISTERED;
04222 case OR2_CAUSE_NO_ANSWER:
04223 return AST_CAUSE_NO_ANSWER;
04224 case OR2_CAUSE_NORMAL_CLEARING:
04225 return AST_CAUSE_NORMAL_CLEARING;
04226 case OR2_CAUSE_UNSPECIFIED:
04227 default:
04228 return AST_CAUSE_NOTDEFINED;
04229 }
04230 }
04231
04232 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04233 {
04234 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04235 char cause_str[50];
04236 struct ast_control_pvt_cause_code *cause_code;
04237 int datalen = sizeof(*cause_code);
04238
04239 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04240 ast_mutex_lock(&p->lock);
04241 if (!p->owner) {
04242 ast_mutex_unlock(&p->lock);
04243
04244 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04245 return;
04246 }
04247
04248 snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
04249 datalen += strlen(cause_str);
04250 cause_code = ast_alloca(datalen);
04251 memset(cause_code, 0, datalen);
04252 cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
04253 ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
04254 ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
04255 ast_queue_control_data(p->owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
04256 ast_channel_hangupcause_hash_set(p->owner, cause_code, datalen);
04257
04258
04259
04260 if (ast_channel_state(p->owner) == AST_STATE_UP) {
04261 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04262 ast_mutex_unlock(&p->lock);
04263 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04264
04265 switch (cause) {
04266 case OR2_CAUSE_BUSY_NUMBER:
04267 p->subs[SUB_REAL].needbusy = 1;
04268 break;
04269 case OR2_CAUSE_NETWORK_CONGESTION:
04270 case OR2_CAUSE_OUT_OF_ORDER:
04271 case OR2_CAUSE_UNALLOCATED_NUMBER:
04272 case OR2_CAUSE_NO_ANSWER:
04273 case OR2_CAUSE_UNSPECIFIED:
04274 case OR2_CAUSE_NORMAL_CLEARING:
04275 p->subs[SUB_REAL].needcongestion = 1;
04276 break;
04277 default:
04278 ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
04279 }
04280 ast_mutex_unlock(&p->lock);
04281 } else {
04282 ast_mutex_unlock(&p->lock);
04283
04284
04285 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04286 }
04287 }
04288
04289 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04290 {
04291 switch (level) {
04292 case OR2_LOG_NOTICE:
04293 ast_verbose("%s", logmessage);
04294 break;
04295 case OR2_LOG_WARNING:
04296 ast_log(LOG_WARNING, "%s", logmessage);
04297 break;
04298 case OR2_LOG_ERROR:
04299 ast_log(LOG_ERROR, "%s", logmessage);
04300 break;
04301 case OR2_LOG_STACK_TRACE:
04302 case OR2_LOG_MF_TRACE:
04303 case OR2_LOG_CAS_TRACE:
04304 case OR2_LOG_DEBUG:
04305 case OR2_LOG_EX_DEBUG:
04306 ast_debug(1, "%s", logmessage);
04307 break;
04308 default:
04309 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04310 ast_debug(1, "%s", logmessage);
04311 break;
04312 }
04313 }
04314
04315 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04316 {
04317 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04318 ast_mutex_lock(&p->lock);
04319 p->remotelyblocked = 1;
04320 ast_mutex_unlock(&p->lock);
04321 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04322 }
04323
04324 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04325 {
04326 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04327 ast_mutex_lock(&p->lock);
04328 p->remotelyblocked = 0;
04329 ast_mutex_unlock(&p->lock);
04330 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04331 }
04332
04333 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04334 __attribute__((format (printf, 3, 0)));
04335 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04336 {
04337 #define CONTEXT_TAG "Context - "
04338 char logmsg[256];
04339 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04340 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04341 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04342 dahdi_r2_write_log(level, completemsg);
04343 #undef CONTEXT_TAG
04344 }
04345
04346 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04347 __attribute__((format (printf, 3, 0)));
04348 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04349 {
04350 #define CHAN_TAG "Chan "
04351 char logmsg[256];
04352 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04353 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04354 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04355 dahdi_r2_write_log(level, completemsg);
04356 }
04357
04358 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04359 {
04360 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04361
04362 if (p->immediate) {
04363 return 0;
04364 }
04365 p->exten[p->mfcr2_dnis_index] = digit;
04366 p->rdnis[p->mfcr2_dnis_index] = digit;
04367 p->mfcr2_dnis_index++;
04368 p->exten[p->mfcr2_dnis_index] = 0;
04369 p->rdnis[p->mfcr2_dnis_index] = 0;
04370
04371 if ((p->mfcr2_dnis_matched ||
04372 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04373 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04374 return 0;
04375 }
04376
04377 return 1;
04378 }
04379
04380 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04381 {
04382 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04383 p->cid_num[p->mfcr2_ani_index] = digit;
04384 p->cid_name[p->mfcr2_ani_index] = digit;
04385 p->mfcr2_ani_index++;
04386 p->cid_num[p->mfcr2_ani_index] = 0;
04387 p->cid_name[p->mfcr2_ani_index] = 0;
04388 }
04389
04390 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04391 {
04392 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04393 }
04394
04395 static openr2_event_interface_t dahdi_r2_event_iface = {
04396 .on_call_init = dahdi_r2_on_call_init,
04397 .on_call_offered = dahdi_r2_on_call_offered,
04398 .on_call_accepted = dahdi_r2_on_call_accepted,
04399 .on_call_answered = dahdi_r2_on_call_answered,
04400 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04401 .on_call_end = dahdi_r2_on_call_end,
04402 .on_call_read = dahdi_r2_on_call_read,
04403 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04404 .on_os_error = dahdi_r2_on_os_error,
04405 .on_protocol_error = dahdi_r2_on_protocol_error,
04406 .on_line_blocked = dahdi_r2_on_line_blocked,
04407 .on_line_idle = dahdi_r2_on_line_idle,
04408
04409 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04410 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04411 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04412
04413 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04414 };
04415
04416 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04417 {
04418 return AST_ALAW(sample);
04419 }
04420
04421 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04422 {
04423 return AST_LIN2A(sample);
04424 }
04425
04426 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04427 dahdi_r2_alaw_to_linear,
04428 dahdi_r2_linear_to_alaw
04429 };
04430
04431 #endif
04432
04433 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04434 {
04435 int tchan;
04436 int tinthreeway;
04437 struct ast_channel *towner;
04438
04439 ast_debug(1, "Swapping %d and %d\n", a, b);
04440
04441 tchan = p->subs[a].chan;
04442 towner = p->subs[a].owner;
04443 tinthreeway = p->subs[a].inthreeway;
04444
04445 p->subs[a].chan = p->subs[b].chan;
04446 p->subs[a].owner = p->subs[b].owner;
04447 p->subs[a].inthreeway = p->subs[b].inthreeway;
04448
04449 p->subs[b].chan = tchan;
04450 p->subs[b].owner = towner;
04451 p->subs[b].inthreeway = tinthreeway;
04452
04453 if (p->subs[a].owner)
04454 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04455 if (p->subs[b].owner)
04456 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04457 wakeup_sub(p, a);
04458 wakeup_sub(p, b);
04459 }
04460
04461 static int dahdi_open(char *fn)
04462 {
04463 int fd;
04464 int isnum;
04465 int chan = 0;
04466 int bs;
04467 int x;
04468 isnum = 1;
04469 for (x = 0; x < strlen(fn); x++) {
04470 if (!isdigit(fn[x])) {
04471 isnum = 0;
04472 break;
04473 }
04474 }
04475 if (isnum) {
04476 chan = atoi(fn);
04477 if (chan < 1) {
04478 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04479 return -1;
04480 }
04481 fn = "/dev/dahdi/channel";
04482 }
04483 fd = open(fn, O_RDWR | O_NONBLOCK);
04484 if (fd < 0) {
04485 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04486 return -1;
04487 }
04488 if (chan) {
04489 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04490 x = errno;
04491 close(fd);
04492 errno = x;
04493 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04494 return -1;
04495 }
04496 }
04497 bs = READ_SIZE;
04498 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04499 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04500 x = errno;
04501 close(fd);
04502 errno = x;
04503 return -1;
04504 }
04505 return fd;
04506 }
04507
04508 static void dahdi_close(int fd)
04509 {
04510 if (fd > 0)
04511 close(fd);
04512 }
04513
04514 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04515 {
04516 dahdi_close(chan_pvt->subs[sub_num].dfd);
04517 chan_pvt->subs[sub_num].dfd = -1;
04518 }
04519
04520 #if defined(HAVE_PRI)
04521 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04522 {
04523 dahdi_close(pri->pri.fds[fd_num]);
04524 pri->pri.fds[fd_num] = -1;
04525 }
04526 #endif
04527
04528 #if defined(HAVE_SS7)
04529 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04530 {
04531 dahdi_close(ss7->ss7.fds[fd_num]);
04532 ss7->ss7.fds[fd_num] = -1;
04533 }
04534 #endif
04535
04536 static int dahdi_setlinear(int dfd, int linear)
04537 {
04538 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04539 }
04540
04541
04542 static int alloc_sub(struct dahdi_pvt *p, int x)
04543 {
04544 struct dahdi_bufferinfo bi;
04545 int res;
04546 if (p->subs[x].dfd >= 0) {
04547 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04548 return -1;
04549 }
04550
04551 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04552 if (p->subs[x].dfd <= -1) {
04553 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04554 return -1;
04555 }
04556
04557 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04558 if (!res) {
04559 bi.txbufpolicy = p->buf_policy;
04560 bi.rxbufpolicy = p->buf_policy;
04561 bi.numbufs = p->buf_no;
04562 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04563 if (res < 0) {
04564 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04565 }
04566 } else
04567 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04568
04569 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04570 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04571 dahdi_close_sub(p, x);
04572 p->subs[x].dfd = -1;
04573 return -1;
04574 }
04575 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04576 return 0;
04577 }
04578
04579 static int unalloc_sub(struct dahdi_pvt *p, int x)
04580 {
04581 if (!x) {
04582 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04583 return -1;
04584 }
04585 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04586 dahdi_close_sub(p, x);
04587 p->subs[x].linear = 0;
04588 p->subs[x].chan = 0;
04589 p->subs[x].owner = NULL;
04590 p->subs[x].inthreeway = 0;
04591 p->polarity = POLARITY_IDLE;
04592 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04593 return 0;
04594 }
04595
04596 static int digit_to_dtmfindex(char digit)
04597 {
04598 if (isdigit(digit))
04599 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04600 else if (digit >= 'A' && digit <= 'D')
04601 return DAHDI_TONE_DTMF_A + (digit - 'A');
04602 else if (digit >= 'a' && digit <= 'd')
04603 return DAHDI_TONE_DTMF_A + (digit - 'a');
04604 else if (digit == '*')
04605 return DAHDI_TONE_DTMF_s;
04606 else if (digit == '#')
04607 return DAHDI_TONE_DTMF_p;
04608 else
04609 return -1;
04610 }
04611
04612 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04613 {
04614 struct dahdi_pvt *pvt;
04615 int idx;
04616 int dtmf = -1;
04617 int res;
04618
04619 pvt = ast_channel_tech_pvt(chan);
04620
04621 ast_mutex_lock(&pvt->lock);
04622
04623 idx = dahdi_get_index(chan, pvt, 0);
04624
04625 if ((idx != SUB_REAL) || !pvt->owner)
04626 goto out;
04627
04628 #ifdef HAVE_PRI
04629 switch (pvt->sig) {
04630 case SIG_PRI_LIB_HANDLE_CASES:
04631 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04632 if (!res)
04633 goto out;
04634 break;
04635 default:
04636 break;
04637 }
04638 #endif
04639 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04640 goto out;
04641
04642 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04643 struct dahdi_dialoperation zo = {
04644 .op = DAHDI_DIAL_OP_APPEND,
04645 };
04646
04647 zo.dialstr[0] = 'T';
04648 zo.dialstr[1] = digit;
04649 zo.dialstr[2] = '\0';
04650 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04651 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04652 ast_channel_name(chan), digit, strerror(errno));
04653 else
04654 pvt->dialing = 1;
04655 } else {
04656 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04657 ast_channel_name(chan), digit);
04658 pvt->dialing = 1;
04659 pvt->begindigit = digit;
04660 }
04661
04662 out:
04663 ast_mutex_unlock(&pvt->lock);
04664
04665 return 0;
04666 }
04667
04668 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04669 {
04670 struct dahdi_pvt *pvt;
04671 int res = 0;
04672 int idx;
04673 int x;
04674
04675 pvt = ast_channel_tech_pvt(chan);
04676
04677 ast_mutex_lock(&pvt->lock);
04678
04679 idx = dahdi_get_index(chan, pvt, 0);
04680
04681 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04682 goto out;
04683
04684 #ifdef HAVE_PRI
04685
04686 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04687 goto out;
04688 }
04689 #endif
04690
04691 if (pvt->begindigit) {
04692 x = -1;
04693 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04694 ast_channel_name(chan), digit);
04695 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04696 pvt->dialing = 0;
04697 pvt->begindigit = 0;
04698 }
04699
04700 out:
04701 ast_mutex_unlock(&pvt->lock);
04702
04703 return res;
04704 }
04705
04706 static const char * const events[] = {
04707 "No event",
04708 "On hook",
04709 "Ring/Answered",
04710 "Wink/Flash",
04711 "Alarm",
04712 "No more alarm",
04713 "HDLC Abort",
04714 "HDLC Overrun",
04715 "HDLC Bad FCS",
04716 "Dial Complete",
04717 "Ringer On",
04718 "Ringer Off",
04719 "Hook Transition Complete",
04720 "Bits Changed",
04721 "Pulse Start",
04722 "Timer Expired",
04723 "Timer Ping",
04724 "Polarity Reversal",
04725 "Ring Begin",
04726 };
04727
04728 static struct {
04729 int alarm;
04730 char *name;
04731 } alarms[] = {
04732 { DAHDI_ALARM_RED, "Red Alarm" },
04733 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04734 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04735 { DAHDI_ALARM_RECOVER, "Recovering" },
04736 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04737 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04738 { DAHDI_ALARM_NONE, "None" },
04739 };
04740
04741 static char *alarm2str(int alm)
04742 {
04743 int x;
04744 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04745 if (alarms[x].alarm & alm)
04746 return alarms[x].name;
04747 }
04748 return alm ? "Unknown Alarm" : "No Alarm";
04749 }
04750
04751 static const char *event2str(int event)
04752 {
04753 static char buf[256];
04754 if ((event < (ARRAY_LEN(events))) && (event > -1))
04755 return events[event];
04756 sprintf(buf, "Event %d", event);
04757 return buf;
04758 }
04759
04760 static char *dahdi_sig2str(int sig)
04761 {
04762 static char buf[256];
04763 switch (sig) {
04764 case SIG_EM:
04765 return "E & M Immediate";
04766 case SIG_EMWINK:
04767 return "E & M Wink";
04768 case SIG_EM_E1:
04769 return "E & M E1";
04770 case SIG_FEATD:
04771 return "Feature Group D (DTMF)";
04772 case SIG_FEATDMF:
04773 return "Feature Group D (MF)";
04774 case SIG_FEATDMF_TA:
04775 return "Feature Groud D (MF) Tandem Access";
04776 case SIG_FEATB:
04777 return "Feature Group B (MF)";
04778 case SIG_E911:
04779 return "E911 (MF)";
04780 case SIG_FGC_CAMA:
04781 return "FGC/CAMA (Dialpulse)";
04782 case SIG_FGC_CAMAMF:
04783 return "FGC/CAMA (MF)";
04784 case SIG_FXSLS:
04785 return "FXS Loopstart";
04786 case SIG_FXSGS:
04787 return "FXS Groundstart";
04788 case SIG_FXSKS:
04789 return "FXS Kewlstart";
04790 case SIG_FXOLS:
04791 return "FXO Loopstart";
04792 case SIG_FXOGS:
04793 return "FXO Groundstart";
04794 case SIG_FXOKS:
04795 return "FXO Kewlstart";
04796 case SIG_PRI:
04797 return "ISDN PRI";
04798 case SIG_BRI:
04799 return "ISDN BRI Point to Point";
04800 case SIG_BRI_PTMP:
04801 return "ISDN BRI Point to MultiPoint";
04802 case SIG_SS7:
04803 return "SS7";
04804 case SIG_MFCR2:
04805 return "MFC/R2";
04806 case SIG_SF:
04807 return "SF (Tone) Immediate";
04808 case SIG_SFWINK:
04809 return "SF (Tone) Wink";
04810 case SIG_SF_FEATD:
04811 return "SF (Tone) with Feature Group D (DTMF)";
04812 case SIG_SF_FEATDMF:
04813 return "SF (Tone) with Feature Group D (MF)";
04814 case SIG_SF_FEATB:
04815 return "SF (Tone) with Feature Group B (MF)";
04816 case 0:
04817 return "Pseudo";
04818 default:
04819 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04820 return buf;
04821 }
04822 }
04823
04824 #define sig2str dahdi_sig2str
04825
04826 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04827 {
04828
04829
04830 struct dahdi_confinfo zi;
04831
04832 memset(&zi, 0, sizeof(zi));
04833 zi.chan = 0;
04834
04835 if (slavechannel > 0) {
04836
04837 zi.confmode = DAHDI_CONF_DIGITALMON;
04838 zi.confno = slavechannel;
04839 } else {
04840 if (!idx) {
04841
04842 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04843 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04844 } else
04845 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04846 zi.confno = p->confno;
04847 }
04848 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04849 return 0;
04850 if (c->dfd < 0)
04851 return 0;
04852 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04853 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04854 return -1;
04855 }
04856 if (slavechannel < 1) {
04857 p->confno = zi.confno;
04858 }
04859 c->curconf = zi;
04860 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04861 return 0;
04862 }
04863
04864 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04865 {
04866
04867 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04868 return 1;
04869
04870 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04871 return 1;
04872 return 0;
04873 }
04874
04875 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04876 {
04877 struct dahdi_confinfo zi;
04878 if (
04879 (c->dfd < 0) ||
04880
04881 !isourconf(p, c)
04882
04883 ) return 0;
04884 memset(&zi, 0, sizeof(zi));
04885 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04886 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04887 return -1;
04888 }
04889 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04890 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04891 return 0;
04892 }
04893
04894 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04895 {
04896 int x;
04897 int useslavenative;
04898 struct dahdi_pvt *slave = NULL;
04899
04900 useslavenative = 1;
04901
04902 for (x = 0; x < 3; x++) {
04903
04904
04905 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04906 useslavenative = 0;
04907 }
04908
04909
04910 if (useslavenative) {
04911 for (x = 0; x < MAX_SLAVES; x++) {
04912 if (p->slaves[x]) {
04913 if (slave) {
04914
04915
04916 slave = NULL;
04917 useslavenative = 0;
04918 break;
04919 } else {
04920
04921 slave = p->slaves[x];
04922 }
04923 }
04924 }
04925 }
04926
04927 if (!slave)
04928 useslavenative = 0;
04929 else if (slave->law != p->law) {
04930 useslavenative = 0;
04931 slave = NULL;
04932 }
04933 if (out)
04934 *out = slave;
04935 return useslavenative;
04936 }
04937
04938 static int reset_conf(struct dahdi_pvt *p)
04939 {
04940 p->confno = -1;
04941 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04942 if (p->subs[SUB_REAL].dfd > -1) {
04943 struct dahdi_confinfo zi;
04944
04945 memset(&zi, 0, sizeof(zi));
04946 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04947 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04948 }
04949 return 0;
04950 }
04951
04952 static int update_conf(struct dahdi_pvt *p)
04953 {
04954 int needconf = 0;
04955 int x;
04956 int useslavenative;
04957 struct dahdi_pvt *slave = NULL;
04958
04959 useslavenative = isslavenative(p, &slave);
04960
04961 for (x = 0; x < 3; x++) {
04962
04963 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04964 conf_add(p, &p->subs[x], x, 0);
04965 needconf++;
04966 } else {
04967 conf_del(p, &p->subs[x], x);
04968 }
04969 }
04970
04971
04972 for (x = 0; x < MAX_SLAVES; x++) {
04973 if (p->slaves[x]) {
04974 if (useslavenative)
04975 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04976 else {
04977 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04978 needconf++;
04979 }
04980 }
04981 }
04982
04983 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04984 if (useslavenative)
04985 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04986 else {
04987 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04988 needconf++;
04989 }
04990 }
04991
04992 if (p->master) {
04993 if (isslavenative(p->master, NULL)) {
04994 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04995 } else {
04996 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04997 }
04998 }
04999 if (!needconf) {
05000
05001
05002 p->confno = -1;
05003 }
05004 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
05005 return 0;
05006 }
05007
05008 static void dahdi_enable_ec(struct dahdi_pvt *p)
05009 {
05010 int res;
05011 if (!p)
05012 return;
05013 if (p->echocanon) {
05014 ast_debug(1, "Echo cancellation already on\n");
05015 return;
05016 }
05017 if (p->digital) {
05018 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
05019 return;
05020 }
05021 if (p->echocancel.head.tap_length) {
05022 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05023 switch (p->sig) {
05024 #if defined(HAVE_PRI)
05025 case SIG_PRI_LIB_HANDLE_CASES:
05026 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05027
05028
05029
05030
05031 return;
05032 }
05033
05034 #endif
05035 #if defined(HAVE_SS7)
05036 case SIG_SS7:
05037 #endif
05038 {
05039 int x = 1;
05040
05041 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
05042 if (res)
05043 ast_log(LOG_WARNING,
05044 "Unable to enable audio mode on channel %d (%s)\n",
05045 p->channel, strerror(errno));
05046 }
05047 break;
05048 default:
05049 break;
05050 }
05051 #endif
05052 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
05053 if (res) {
05054 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
05055 } else {
05056 p->echocanon = 1;
05057 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
05058 }
05059 } else
05060 ast_debug(1, "No echo cancellation requested\n");
05061 }
05062
05063 static void dahdi_train_ec(struct dahdi_pvt *p)
05064 {
05065 int x;
05066 int res;
05067
05068 if (p && p->echocanon && p->echotraining) {
05069 x = p->echotraining;
05070 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
05071 if (res)
05072 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
05073 else
05074 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
05075 } else {
05076 ast_debug(1, "No echo training requested\n");
05077 }
05078 }
05079
05080 static void dahdi_disable_ec(struct dahdi_pvt *p)
05081 {
05082 int res;
05083
05084 if (p->echocanon) {
05085 struct dahdi_echocanparams ecp = { .tap_length = 0 };
05086
05087 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
05088
05089 if (res)
05090 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
05091 else
05092 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
05093 }
05094
05095 p->echocanon = 0;
05096 }
05097
05098
05099 static int drc_sample(int sample, float drc)
05100 {
05101 float neg;
05102 float shallow, steep;
05103 float max = SHRT_MAX;
05104
05105 neg = (sample < 0 ? -1 : 1);
05106 steep = drc*sample;
05107 shallow = neg*(max-max/drc)+(float)sample/drc;
05108 if (abs(steep) < abs(shallow)) {
05109 sample = steep;
05110 }
05111 else {
05112 sample = shallow;
05113 }
05114
05115 return sample;
05116 }
05117
05118
05119 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05120 {
05121 int j;
05122 int k;
05123
05124 float linear_gain = pow(10.0, gain / 20.0);
05125
05126 switch (law) {
05127 case DAHDI_LAW_ALAW:
05128 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05129 if (gain || drc) {
05130 k = AST_ALAW(j);
05131 if (drc) {
05132 k = drc_sample(k, drc);
05133 }
05134 k = (float)k * linear_gain;
05135 if (k > 32767) {
05136 k = 32767;
05137 } else if (k < -32768) {
05138 k = -32768;
05139 }
05140 g->txgain[j] = AST_LIN2A(k);
05141 } else {
05142 g->txgain[j] = j;
05143 }
05144 }
05145 break;
05146 case DAHDI_LAW_MULAW:
05147 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05148 if (gain || drc) {
05149 k = AST_MULAW(j);
05150 if (drc) {
05151 k = drc_sample(k, drc);
05152 }
05153 k = (float)k * linear_gain;
05154 if (k > 32767) {
05155 k = 32767;
05156 } else if (k < -32768) {
05157 k = -32768;
05158 }
05159 g->txgain[j] = AST_LIN2MU(k);
05160
05161 } else {
05162 g->txgain[j] = j;
05163 }
05164 }
05165 break;
05166 }
05167 }
05168
05169 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05170 {
05171 int j;
05172 int k;
05173 float linear_gain = pow(10.0, gain / 20.0);
05174
05175 switch (law) {
05176 case DAHDI_LAW_ALAW:
05177 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05178 if (gain || drc) {
05179 k = AST_ALAW(j);
05180 if (drc) {
05181 k = drc_sample(k, drc);
05182 }
05183 k = (float)k * linear_gain;
05184 if (k > 32767) {
05185 k = 32767;
05186 } else if (k < -32768) {
05187 k = -32768;
05188 }
05189 g->rxgain[j] = AST_LIN2A(k);
05190 } else {
05191 g->rxgain[j] = j;
05192 }
05193 }
05194 break;
05195 case DAHDI_LAW_MULAW:
05196 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05197 if (gain || drc) {
05198 k = AST_MULAW(j);
05199 if (drc) {
05200 k = drc_sample(k, drc);
05201 }
05202 k = (float)k * linear_gain;
05203 if (k > 32767) {
05204 k = 32767;
05205 } else if (k < -32768) {
05206 k = -32768;
05207 }
05208 g->rxgain[j] = AST_LIN2MU(k);
05209 } else {
05210 g->rxgain[j] = j;
05211 }
05212 }
05213 break;
05214 }
05215 }
05216
05217 static int set_actual_txgain(int fd, float gain, float drc, int law)
05218 {
05219 struct dahdi_gains g;
05220 int res;
05221
05222 memset(&g, 0, sizeof(g));
05223 res = ioctl(fd, DAHDI_GETGAINS, &g);
05224 if (res) {
05225 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05226 return res;
05227 }
05228
05229 fill_txgain(&g, gain, drc, law);
05230
05231 return ioctl(fd, DAHDI_SETGAINS, &g);
05232 }
05233
05234 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05235 {
05236 struct dahdi_gains g;
05237 int res;
05238
05239 memset(&g, 0, sizeof(g));
05240 res = ioctl(fd, DAHDI_GETGAINS, &g);
05241 if (res) {
05242 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05243 return res;
05244 }
05245
05246 fill_rxgain(&g, gain, drc, law);
05247
05248 return ioctl(fd, DAHDI_SETGAINS, &g);
05249 }
05250
05251 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05252 {
05253 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05254 }
05255
05256 static int bump_gains(struct dahdi_pvt *p)
05257 {
05258 int res;
05259
05260
05261 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05262 if (res) {
05263 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05264 return -1;
05265 }
05266
05267 return 0;
05268 }
05269
05270 static int restore_gains(struct dahdi_pvt *p)
05271 {
05272 int res;
05273
05274 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05275 if (res) {
05276 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05277 return -1;
05278 }
05279
05280 return 0;
05281 }
05282
05283 static inline int dahdi_set_hook(int fd, int hs)
05284 {
05285 int x, res;
05286
05287 x = hs;
05288 res = ioctl(fd, DAHDI_HOOK, &x);
05289
05290 if (res < 0) {
05291 if (errno == EINPROGRESS)
05292 return 0;
05293 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05294
05295 }
05296
05297 return res;
05298 }
05299
05300 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05301 {
05302 int x, res;
05303
05304 x = muted;
05305 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05306 switch (p->sig) {
05307 #if defined(HAVE_PRI)
05308 case SIG_PRI_LIB_HANDLE_CASES:
05309 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05310
05311 break;
05312 }
05313
05314 #endif
05315 #if defined(HAVE_SS7)
05316 case SIG_SS7:
05317 #endif
05318 {
05319 int y = 1;
05320
05321 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05322 if (res)
05323 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05324 p->channel, strerror(errno));
05325 }
05326 break;
05327 default:
05328 break;
05329 }
05330 #endif
05331 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05332 if (res < 0)
05333 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05334 return res;
05335 }
05336
05337 static int save_conference(struct dahdi_pvt *p)
05338 {
05339 struct dahdi_confinfo c;
05340 int res;
05341 if (p->saveconf.confmode) {
05342 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05343 return -1;
05344 }
05345 p->saveconf.chan = 0;
05346 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05347 if (res) {
05348 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05349 p->saveconf.confmode = 0;
05350 return -1;
05351 }
05352 memset(&c, 0, sizeof(c));
05353 c.confmode = DAHDI_CONF_NORMAL;
05354 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05355 if (res) {
05356 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05357 return -1;
05358 }
05359 ast_debug(1, "Disabled conferencing\n");
05360 return 0;
05361 }
05362
05363 static int restore_conference(struct dahdi_pvt *p)
05364 {
05365 int res;
05366 if (p->saveconf.confmode) {
05367 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05368 p->saveconf.confmode = 0;
05369 if (res) {
05370 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05371 return -1;
05372 }
05373 ast_debug(1, "Restored conferencing\n");
05374 }
05375 return 0;
05376 }
05377
05378 static int send_cwcidspill(struct dahdi_pvt *p)
05379 {
05380 struct ast_format tmpfmt;
05381
05382 p->callwaitcas = 0;
05383 p->cidcwexpire = 0;
05384 p->cid_suppress_expire = 0;
05385 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05386 return -1;
05387 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05388
05389 p->cidlen += READ_SIZE * 4;
05390 p->cidpos = 0;
05391 send_callerid(p);
05392 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05393 return 0;
05394 }
05395
05396 static int has_voicemail(struct dahdi_pvt *p)
05397 {
05398 int new_msgs;
05399 struct ast_event *event;
05400 char *mailbox, *context;
05401
05402 mailbox = context = ast_strdupa(p->mailbox);
05403 strsep(&context, "@");
05404 if (ast_strlen_zero(context))
05405 context = "default";
05406
05407 event = ast_event_get_cached(AST_EVENT_MWI,
05408 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05409 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05410 AST_EVENT_IE_END);
05411
05412 if (event) {
05413 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05414 ast_event_destroy(event);
05415 } else
05416 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05417
05418 return new_msgs;
05419 }
05420
05421
05422
05423 static int send_callerid(struct dahdi_pvt *p)
05424 {
05425
05426 int res;
05427
05428 if (p->subs[SUB_REAL].linear) {
05429 p->subs[SUB_REAL].linear = 0;
05430 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05431 }
05432 while (p->cidpos < p->cidlen) {
05433 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05434 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05435 if (res < 0) {
05436 if (errno == EAGAIN)
05437 return 0;
05438 else {
05439 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05440 return -1;
05441 }
05442 }
05443 if (!res)
05444 return 0;
05445 p->cidpos += res;
05446 }
05447 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05448 ast_free(p->cidspill);
05449 p->cidspill = NULL;
05450 if (p->callwaitcas) {
05451
05452 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05453 p->cid_suppress_expire = p->cidcwexpire;
05454 } else
05455 restore_conference(p);
05456 return 0;
05457 }
05458
05459 static int dahdi_callwait(struct ast_channel *ast)
05460 {
05461 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05462 struct ast_format tmpfmt;
05463 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05464 if (p->cidspill) {
05465 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05466 ast_free(p->cidspill);
05467 }
05468
05469
05470
05471
05472
05473 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05474 return -1;
05475 save_conference(p);
05476
05477 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05478 if (!p->callwaitrings && p->callwaitingcallerid) {
05479 ast_gen_cas(p->cidspill, 1, 2400 + 680, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05480 p->callwaitcas = 1;
05481 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05482 } else {
05483 ast_gen_cas(p->cidspill, 1, 2400, ast_format_set(&tmpfmt, AST_LAW(p), 0));
05484 p->callwaitcas = 0;
05485 p->cidlen = 2400 + READ_SIZE * 4;
05486 }
05487 p->cidpos = 0;
05488 send_callerid(p);
05489
05490 return 0;
05491 }
05492
05493 static int dahdi_call(struct ast_channel *ast, const char *rdest, int timeout)
05494 {
05495 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
05496 int x, res, mysig;
05497 char *dest;
05498 AST_DECLARE_APP_ARGS(args,
05499 AST_APP_ARG(group);
05500 AST_APP_ARG(ext);
05501
05502 AST_APP_ARG(other);
05503 );
05504
05505 ast_mutex_lock(&p->lock);
05506 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05507
05508
05509 dest = ast_strdupa(rdest);
05510 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
05511 if (!args.ext) {
05512 args.ext = "";
05513 }
05514
05515 #if defined(HAVE_PRI)
05516 if (dahdi_sig_pri_lib_handles(p->sig)) {
05517 char *subaddr;
05518
05519 sig_pri_extract_called_num_subaddr(p->sig_pvt, rdest, p->exten, sizeof(p->exten));
05520
05521
05522 subaddr = strchr(p->exten, ':');
05523 if (subaddr) {
05524 *subaddr = '\0';
05525 }
05526 } else
05527 #endif
05528 {
05529 ast_copy_string(p->exten, args.ext, sizeof(p->exten));
05530 }
05531
05532 if ((ast_channel_state(ast) == AST_STATE_BUSY)) {
05533 p->subs[SUB_REAL].needbusy = 1;
05534 ast_mutex_unlock(&p->lock);
05535 return 0;
05536 }
05537 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
05538 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
05539 ast_mutex_unlock(&p->lock);
05540 return -1;
05541 }
05542 p->waitingfordt.tv_sec = 0;
05543 p->dialednone = 0;
05544 if ((p->radio || (p->oprmode < 0)))
05545 {
05546
05547 ast_setstate(ast, AST_STATE_UP);
05548 ast_mutex_unlock(&p->lock);
05549 return 0;
05550 }
05551 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05552 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05553 if (res)
05554 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05555 p->outgoing = 1;
05556
05557 if (IS_DIGITAL(ast_channel_transfercapability(ast))){
05558 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05559 } else {
05560 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05561 }
05562
05563 #ifdef HAVE_PRI
05564 if (dahdi_sig_pri_lib_handles(p->sig)) {
05565 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05566 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05567 ast_mutex_unlock(&p->lock);
05568 return res;
05569 }
05570 #endif
05571
05572 #if defined(HAVE_SS7)
05573 if (p->sig == SIG_SS7) {
05574 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05575 ast_mutex_unlock(&p->lock);
05576 return res;
05577 }
05578 #endif
05579
05580
05581 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05582 p->callwaitrings = 0;
05583 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05584 ast_mutex_unlock(&p->lock);
05585 return res;
05586 }
05587
05588 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05589 switch (mysig) {
05590 case 0:
05591
05592 ast_setstate(ast, AST_STATE_UP);
05593 break;
05594 case SIG_MFCR2:
05595 break;
05596 default:
05597 ast_debug(1, "not yet implemented\n");
05598 ast_mutex_unlock(&p->lock);
05599 return -1;
05600 }
05601
05602 #ifdef HAVE_OPENR2
05603 if (p->mfcr2) {
05604 openr2_calling_party_category_t chancat;
05605 int callres = 0;
05606 char *c, *l;
05607
05608
05609 p->dialdest[0] = '\0';
05610
05611 c = args.ext;
05612 if (!p->hidecallerid) {
05613 l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
05614 } else {
05615 l = NULL;
05616 }
05617 if (strlen(c) < p->stripmsd) {
05618 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05619 ast_mutex_unlock(&p->lock);
05620 return -1;
05621 }
05622 p->dialing = 1;
05623 chancat = dahdi_r2_get_channel_category(ast);
05624 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05625 if (-1 == callres) {
05626 ast_mutex_unlock(&p->lock);
05627 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05628 return -1;
05629 }
05630 p->mfcr2_call_accepted = 0;
05631 p->mfcr2_progress_sent = 0;
05632 ast_setstate(ast, AST_STATE_DIALING);
05633 }
05634 #endif
05635 ast_mutex_unlock(&p->lock);
05636 return 0;
05637 }
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05655 {
05656 struct dahdi_pvt *cur;
05657
05658 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05659
05660
05661 for (cur = iflist; cur; cur = cur->next) {
05662 if (pvt->channel < cur->channel) {
05663
05664 pvt->prev = cur->prev;
05665 pvt->next = cur;
05666 if (cur->prev) {
05667
05668 cur->prev->next = pvt;
05669 } else {
05670
05671 iflist = pvt;
05672 }
05673 cur->prev = pvt;
05674 return;
05675 }
05676 }
05677
05678
05679 pvt->prev = ifend;
05680 pvt->next = NULL;
05681 if (ifend) {
05682 ifend->next = pvt;
05683 }
05684 ifend = pvt;
05685 if (!iflist) {
05686
05687 iflist = pvt;
05688 }
05689 }
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05705 {
05706
05707 if (pvt->prev) {
05708 pvt->prev->next = pvt->next;
05709 } else if (iflist == pvt) {
05710
05711 iflist = pvt->next;
05712 }
05713
05714
05715 if (pvt->next) {
05716 pvt->next->prev = pvt->prev;
05717 } else if (ifend == pvt) {
05718
05719 ifend = pvt->prev;
05720 }
05721
05722
05723 pvt->which_iflist = DAHDI_IFLIST_NONE;
05724 pvt->prev = NULL;
05725 pvt->next = NULL;
05726 }
05727
05728 #if defined(HAVE_PRI)
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741
05742
05743
05744
05745 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05746 {
05747 struct dahdi_pvt *cur;
05748
05749 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05750
05751
05752 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05753 if (pvt->channel < cur->channel) {
05754
05755 pvt->prev = cur->prev;
05756 pvt->next = cur;
05757 if (cur->prev) {
05758
05759 cur->prev->next = pvt;
05760 } else {
05761
05762 pri->no_b_chan_iflist = pvt;
05763 }
05764 cur->prev = pvt;
05765 return;
05766 }
05767 }
05768
05769
05770 pvt->prev = pri->no_b_chan_end;
05771 pvt->next = NULL;
05772 if (pri->no_b_chan_end) {
05773 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05774 }
05775 pri->no_b_chan_end = pvt;
05776 if (!pri->no_b_chan_iflist) {
05777
05778 pri->no_b_chan_iflist = pvt;
05779 }
05780 }
05781 #endif
05782
05783 #if defined(HAVE_PRI)
05784
05785
05786
05787
05788
05789
05790
05791
05792
05793
05794
05795
05796
05797
05798 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05799 {
05800
05801 if (pvt->prev) {
05802 pvt->prev->next = pvt->next;
05803 } else if (pri->no_b_chan_iflist == pvt) {
05804
05805 pri->no_b_chan_iflist = pvt->next;
05806 }
05807
05808
05809 if (pvt->next) {
05810 pvt->next->prev = pvt->prev;
05811 } else if (pri->no_b_chan_end == pvt) {
05812
05813 pri->no_b_chan_end = pvt->prev;
05814 }
05815
05816
05817 pvt->which_iflist = DAHDI_IFLIST_NONE;
05818 pvt->prev = NULL;
05819 pvt->next = NULL;
05820 }
05821 #endif
05822
05823 #if defined(HAVE_PRI)
05824
05825
05826
05827
05828
05829
05830
05831
05832
05833 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05834 {
05835 unsigned idx;
05836 struct sig_pri_span *pri;
05837
05838 pri = pvt->pri;
05839 if (!pri) {
05840
05841 return;
05842 }
05843 ast_mutex_lock(&pri->lock);
05844 for (idx = 0; idx < pri->numchans; ++idx) {
05845 if (pri->pvts[idx] == pvt->sig_pvt) {
05846 pri->pvts[idx] = NULL;
05847 ast_mutex_unlock(&pri->lock);
05848 return;
05849 }
05850 }
05851 ast_mutex_unlock(&pri->lock);
05852 }
05853 #endif
05854
05855 #if defined(HAVE_SS7)
05856
05857
05858
05859
05860
05861
05862
05863
05864
05865 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05866 {
05867 unsigned idx;
05868 struct sig_ss7_linkset *ss7;
05869
05870 ss7 = pvt->ss7;
05871 if (!ss7) {
05872
05873 return;
05874 }
05875 ast_mutex_lock(&ss7->lock);
05876 for (idx = 0; idx < ss7->numchans; ++idx) {
05877 if (ss7->pvts[idx] == pvt->sig_pvt) {
05878 ss7->pvts[idx] = NULL;
05879 ast_mutex_unlock(&ss7->lock);
05880 return;
05881 }
05882 }
05883 ast_mutex_unlock(&ss7->lock);
05884 }
05885 #endif
05886
05887 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05888 {
05889 if (cur->next && cur->next->span == cur->span) {
05890 return cur->next;
05891 } else if (cur->prev && cur->prev->span == cur->span) {
05892 return cur->prev;
05893 }
05894
05895 return NULL;
05896 }
05897
05898 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05899 {
05900 struct dahdi_pvt *p = pvt;
05901
05902 if (p->manages_span_alarms) {
05903 struct dahdi_pvt *next = find_next_iface_in_span(p);
05904 if (next) {
05905 next->manages_span_alarms = 1;
05906 }
05907 }
05908
05909
05910 #if defined(HAVE_PRI)
05911 dahdi_unlink_pri_pvt(p);
05912 #endif
05913 #if defined(HAVE_SS7)
05914 dahdi_unlink_ss7_pvt(p);
05915 #endif
05916 switch (pvt->which_iflist) {
05917 case DAHDI_IFLIST_NONE:
05918 break;
05919 case DAHDI_IFLIST_MAIN:
05920 dahdi_iflist_extract(p);
05921 break;
05922 #if defined(HAVE_PRI)
05923 case DAHDI_IFLIST_NO_B_CHAN:
05924 if (p->pri) {
05925 dahdi_nobch_extract(p->pri, p);
05926 }
05927 break;
05928 #endif
05929 }
05930
05931 if (p->sig_pvt) {
05932 if (analog_lib_handles(p->sig, 0, 0)) {
05933 analog_delete(p->sig_pvt);
05934 }
05935 switch (p->sig) {
05936 #if defined(HAVE_PRI)
05937 case SIG_PRI_LIB_HANDLE_CASES:
05938 sig_pri_chan_delete(p->sig_pvt);
05939 break;
05940 #endif
05941 #if defined(HAVE_SS7)
05942 case SIG_SS7:
05943 sig_ss7_chan_delete(p->sig_pvt);
05944 break;
05945 #endif
05946 default:
05947 break;
05948 }
05949 }
05950 ast_free(p->cidspill);
05951 if (p->use_smdi)
05952 ast_smdi_interface_unref(p->smdi_iface);
05953 if (p->mwi_event_sub)
05954 ast_event_unsubscribe(p->mwi_event_sub);
05955 if (p->vars) {
05956 ast_variables_destroy(p->vars);
05957 }
05958 if (p->cc_params) {
05959 ast_cc_config_params_destroy(p->cc_params);
05960 }
05961
05962 p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
05963 p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
05964
05965 ast_mutex_destroy(&p->lock);
05966 dahdi_close_sub(p, SUB_REAL);
05967 if (p->owner)
05968 ast_channel_tech_pvt_set(p->owner, NULL);
05969 ast_free(p);
05970 }
05971
05972 static void destroy_channel(struct dahdi_pvt *cur, int now)
05973 {
05974 int i;
05975
05976 if (!now) {
05977
05978 if (cur->owner) {
05979 return;
05980 }
05981 for (i = 0; i < 3; i++) {
05982 if (cur->subs[i].owner) {
05983 return;
05984 }
05985 }
05986 }
05987 destroy_dahdi_pvt(cur);
05988 }
05989
05990 static void destroy_all_channels(void)
05991 {
05992 int chan;
05993 #if defined(HAVE_PRI)
05994 unsigned span;
05995 struct sig_pri_span *pri;
05996 #endif
05997 struct dahdi_pvt *p;
05998
05999 while (num_restart_pending) {
06000 usleep(1);
06001 }
06002
06003 ast_mutex_lock(&iflock);
06004
06005 while (iflist) {
06006 p = iflist;
06007
06008 chan = p->channel;
06009 #if defined(HAVE_PRI_SERVICE_MESSAGES)
06010 {
06011 char db_chan_name[20];
06012 char db_answer[5];
06013 char state;
06014 int why = -1;
06015
06016 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
06017 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
06018 sscanf(db_answer, "%1c:%30d", &state, &why);
06019 }
06020 if (!why) {
06021
06022 ast_db_del(db_chan_name, SRVST_DBKEY);
06023 }
06024 }
06025 #endif
06026
06027 destroy_dahdi_pvt(p);
06028 ast_verb(3, "Unregistered channel %d\n", chan);
06029 }
06030 ifcount = 0;
06031 ast_mutex_unlock(&iflock);
06032
06033 #if defined(HAVE_PRI)
06034
06035 for (span = 0; span < NUM_SPANS; ++span) {
06036 if (!pris[span].dchannels[0]) {
06037 break;
06038 }
06039 pri = &pris[span].pri;
06040 ast_mutex_lock(&pri->lock);
06041 while (pri->no_b_chan_iflist) {
06042 p = pri->no_b_chan_iflist;
06043
06044
06045 destroy_dahdi_pvt(p);
06046 }
06047 ast_mutex_unlock(&pri->lock);
06048 }
06049 #endif
06050 }
06051
06052 #if defined(HAVE_PRI)
06053 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
06054
06055 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
06056 {
06057
06058 struct dahdi_pvt *p;
06059
06060 if (ast_strlen_zero(digits)) {
06061 ast_debug(1, "No digit string sent to application!\n");
06062 return -1;
06063 }
06064
06065 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06066
06067 if (!p) {
06068 ast_debug(1, "Unable to find technology private\n");
06069 return -1;
06070 }
06071
06072 pri_send_keypad_facility_exec(p->sig_pvt, digits);
06073
06074 return 0;
06075 }
06076 #endif
06077
06078 #if defined(HAVE_PRI)
06079 #if defined(HAVE_PRI_PROG_W_CAUSE)
06080 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
06081
06082 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
06083 {
06084
06085 struct dahdi_pvt *pvt;
06086 char *parse;
06087 int res;
06088 AST_DECLARE_APP_ARGS(args,
06089 AST_APP_ARG(destination);
06090 AST_APP_ARG(original);
06091 AST_APP_ARG(reason);
06092 );
06093
06094 if (ast_strlen_zero(data)) {
06095 ast_debug(1, "No data sent to application!\n");
06096 return -1;
06097 }
06098 if (ast_channel_tech(chan) != &dahdi_tech) {
06099 ast_debug(1, "Only DAHDI technology accepted!\n");
06100 return -1;
06101 }
06102 pvt = (struct dahdi_pvt *) ast_channel_tech_pvt(chan);
06103 if (!pvt) {
06104 ast_debug(1, "Unable to find technology private\n");
06105 return -1;
06106 }
06107 switch (pvt->sig) {
06108 case SIG_PRI_LIB_HANDLE_CASES:
06109 break;
06110 default:
06111 ast_debug(1, "callrerouting attempted on non-ISDN channel %s\n",
06112 ast_channel_name(chan));
06113 return -1;
06114 }
06115
06116 parse = ast_strdupa(data);
06117 AST_STANDARD_APP_ARGS(args, parse);
06118
06119 if (ast_strlen_zero(args.destination)) {
06120 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
06121 return -1;
06122 }
06123
06124 if (ast_strlen_zero(args.original)) {
06125 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
06126 args.original = NULL;
06127 }
06128
06129 if (ast_strlen_zero(args.reason)) {
06130 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
06131 args.reason = NULL;
06132 }
06133
06134 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, ast_channel_state(chan),
06135 args.destination, args.original, args.reason);
06136 if (!res) {
06137
06138
06139
06140
06141 ast_safe_sleep(chan, 5000);
06142 }
06143
06144 return -1;
06145 }
06146 #endif
06147 #endif
06148
06149 #if defined(HAVE_OPENR2)
06150 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06151
06152 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06153 {
06154
06155 openr2_call_mode_t accept_mode;
06156 int res, timeout, maxloops;
06157 struct ast_frame *f;
06158 struct dahdi_pvt *p;
06159 char *parse;
06160 AST_DECLARE_APP_ARGS(args,
06161 AST_APP_ARG(charge);
06162 );
06163
06164 if (ast_strlen_zero(data)) {
06165 ast_debug(1, "No data sent to application!\n");
06166 return -1;
06167 }
06168
06169 if (ast_channel_tech(chan) != &dahdi_tech) {
06170 ast_debug(1, "Only DAHDI technology accepted!\n");
06171 return -1;
06172 }
06173
06174 p = (struct dahdi_pvt *)ast_channel_tech_pvt(chan);
06175 if (!p) {
06176 ast_debug(1, "Unable to find technology private!\n");
06177 return -1;
06178 }
06179
06180 parse = ast_strdupa(data);
06181 AST_STANDARD_APP_ARGS(args, parse);
06182
06183 if (ast_strlen_zero(args.charge)) {
06184 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06185 return -1;
06186 }
06187
06188 ast_mutex_lock(&p->lock);
06189 if (!p->mfcr2 || !p->mfcr2call) {
06190 ast_mutex_unlock(&p->lock);
06191 ast_debug(1, "Channel %s does not seems to be an R2 active channel!\n", ast_channel_name(chan));
06192 return -1;
06193 }
06194
06195 if (p->mfcr2_call_accepted) {
06196 ast_mutex_unlock(&p->lock);
06197 ast_debug(1, "MFC/R2 call already accepted on channel %s!\n", ast_channel_name(chan));
06198 return 0;
06199 }
06200 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06201 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06202 ast_mutex_unlock(&p->lock);
06203 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06204 return -1;
06205 }
06206 ast_mutex_unlock(&p->lock);
06207
06208 res = 0;
06209 timeout = 100;
06210 maxloops = 50;
06211
06212 while (maxloops > 0) {
06213 maxloops--;
06214 if (ast_check_hangup(chan)) {
06215 break;
06216 }
06217 res = ast_waitfor(chan, timeout);
06218 if (res < 0) {
06219 ast_debug(1, "ast_waitfor failed on channel %s, going out ...\n", ast_channel_name(chan));
06220 res = -1;
06221 break;
06222 }
06223 if (res == 0) {
06224 continue;
06225 }
06226 res = 0;
06227 f = ast_read(chan);
06228 if (!f) {
06229 ast_debug(1, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
06230 res = -1;
06231 break;
06232 }
06233 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06234 ast_debug(1, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
06235 ast_frfree(f);
06236 res = -1;
06237 break;
06238 }
06239 ast_frfree(f);
06240 ast_mutex_lock(&p->lock);
06241 if (p->mfcr2_call_accepted) {
06242 ast_mutex_unlock(&p->lock);
06243 ast_debug(1, "Accepted MFC/R2 call!\n");
06244 break;
06245 }
06246 ast_mutex_unlock(&p->lock);
06247 }
06248 if (res == -1) {
06249 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06250 }
06251 return res;
06252 }
06253
06254 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06255 {
06256 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06257 switch (cause) {
06258 case AST_CAUSE_USER_BUSY:
06259 case AST_CAUSE_CALL_REJECTED:
06260 case AST_CAUSE_INTERWORKING:
06261 r2cause = OR2_CAUSE_BUSY_NUMBER;
06262 break;
06263
06264 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06265 case AST_CAUSE_SWITCH_CONGESTION:
06266 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06267 break;
06268
06269 case AST_CAUSE_UNALLOCATED:
06270 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06271 break;
06272
06273 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06274 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06275 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06276 break;
06277
06278 case AST_CAUSE_NO_ANSWER:
06279 case AST_CAUSE_NO_USER_RESPONSE:
06280 r2cause = OR2_CAUSE_NO_ANSWER;
06281 break;
06282
06283 default:
06284 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06285 break;
06286 }
06287 ast_debug(1, "ast cause %d resulted in openr2 cause %d/%s\n",
06288 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06289 return r2cause;
06290 }
06291 #endif
06292
06293 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06294 {
06295 if (p->bufferoverrideinuse) {
06296
06297 struct dahdi_bufferinfo bi = {
06298 .txbufpolicy = p->buf_policy,
06299 .rxbufpolicy = p->buf_policy,
06300 .bufsize = p->bufsize,
06301 .numbufs = p->buf_no
06302 };
06303 int bpres;
06304
06305 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06306 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast_channel_name(ast), strerror(errno));
06307 }
06308 p->bufferoverrideinuse = 0;
06309 return bpres;
06310 }
06311
06312 return -1;
06313 }
06314
06315 static int dahdi_hangup(struct ast_channel *ast)
06316 {
06317 int res = 0;
06318 int idx,x;
06319 int law;
06320
06321 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06322 struct dahdi_params par;
06323
06324 ast_debug(1, "dahdi_hangup(%s)\n", ast_channel_name(ast));
06325 if (!ast_channel_tech_pvt(ast)) {
06326 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06327 return 0;
06328 }
06329
06330 ast_mutex_lock(&p->lock);
06331 p->exten[0] = '\0';
06332 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06333 dahdi_confmute(p, 0);
06334 restore_gains(p);
06335 p->ignoredtmf = 0;
06336 p->waitingfordt.tv_sec = 0;
06337
06338 res = analog_hangup(p->sig_pvt, ast);
06339 revert_fax_buffers(p, ast);
06340
06341 goto hangup_out;
06342 } else {
06343 p->cid_num[0] = '\0';
06344 p->cid_name[0] = '\0';
06345 p->cid_subaddr[0] = '\0';
06346 }
06347
06348 #if defined(HAVE_PRI)
06349 if (dahdi_sig_pri_lib_handles(p->sig)) {
06350 x = 1;
06351 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06352
06353 dahdi_confmute(p, 0);
06354 p->muting = 0;
06355 restore_gains(p);
06356 if (p->dsp) {
06357 ast_dsp_free(p->dsp);
06358 p->dsp = NULL;
06359 }
06360 p->ignoredtmf = 0;
06361
06362
06363 p->subs[SUB_REAL].owner = NULL;
06364 p->subs[SUB_REAL].needbusy = 0;
06365 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06366
06367 p->owner = NULL;
06368 p->cid_tag[0] = '\0';
06369 p->ringt = 0;
06370 p->distinctivering = 0;
06371 p->confirmanswer = 0;
06372 p->outgoing = 0;
06373 p->digital = 0;
06374 p->faxhandled = 0;
06375 p->pulsedial = 0;
06376
06377 revert_fax_buffers(p, ast);
06378
06379 p->law = p->law_default;
06380 law = p->law_default;
06381 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06382 if (res < 0) {
06383 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06384 p->channel, strerror(errno));
06385 }
06386
06387 sig_pri_hangup(p->sig_pvt, ast);
06388
06389 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06390 dahdi_disable_ec(p);
06391
06392 x = 0;
06393 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06394 p->didtdd = 0;
06395
06396 p->rdnis[0] = '\0';
06397 update_conf(p);
06398 reset_conf(p);
06399
06400
06401 x = 0;
06402 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06403
06404 if (num_restart_pending == 0) {
06405 restart_monitor();
06406 }
06407 goto hangup_out;
06408 }
06409 #endif
06410
06411 #if defined(HAVE_SS7)
06412 if (p->sig == SIG_SS7) {
06413 x = 1;
06414 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06415
06416 dahdi_confmute(p, 0);
06417 p->muting = 0;
06418 restore_gains(p);
06419 if (p->dsp) {
06420 ast_dsp_free(p->dsp);
06421 p->dsp = NULL;
06422 }
06423 p->ignoredtmf = 0;
06424
06425
06426 p->subs[SUB_REAL].owner = NULL;
06427 p->subs[SUB_REAL].needbusy = 0;
06428 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06429
06430 p->owner = NULL;
06431 p->ringt = 0;
06432 p->distinctivering = 0;
06433 p->confirmanswer = 0;
06434 p->outgoing = 0;
06435 p->digital = 0;
06436 p->faxhandled = 0;
06437 p->pulsedial = 0;
06438
06439 revert_fax_buffers(p, ast);
06440
06441 p->law = p->law_default;
06442 law = p->law_default;
06443 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06444 if (res < 0) {
06445 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06446 p->channel, strerror(errno));
06447 }
06448
06449 sig_ss7_hangup(p->sig_pvt, ast);
06450
06451 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06452 dahdi_disable_ec(p);
06453
06454 x = 0;
06455 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06456 p->didtdd = 0;
06457
06458 update_conf(p);
06459 reset_conf(p);
06460
06461
06462 x = 0;
06463 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06464
06465 if (num_restart_pending == 0) {
06466 restart_monitor();
06467 }
06468 goto hangup_out;
06469 }
06470 #endif
06471
06472 idx = dahdi_get_index(ast, p, 1);
06473
06474 dahdi_confmute(p, 0);
06475 p->muting = 0;
06476 restore_gains(p);
06477 if (p->origcid_num) {
06478 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06479 ast_free(p->origcid_num);
06480 p->origcid_num = NULL;
06481 }
06482 if (p->origcid_name) {
06483 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06484 ast_free(p->origcid_name);
06485 p->origcid_name = NULL;
06486 }
06487 if (p->dsp)
06488 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06489
06490 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06491 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06492 p->ignoredtmf = 0;
06493
06494 if (idx > -1) {
06495
06496 p->subs[idx].owner = NULL;
06497 p->subs[idx].needanswer = 0;
06498 p->subs[idx].needflash = 0;
06499 p->subs[idx].needringing = 0;
06500 p->subs[idx].needbusy = 0;
06501 p->subs[idx].needcongestion = 0;
06502 p->subs[idx].linear = 0;
06503 p->polarity = POLARITY_IDLE;
06504 dahdi_setlinear(p->subs[idx].dfd, 0);
06505 if (idx == SUB_REAL) {
06506 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06507 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06508 if (p->subs[SUB_CALLWAIT].inthreeway) {
06509
06510 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06511
06512 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06513 unalloc_sub(p, SUB_CALLWAIT);
06514 p->owner = NULL;
06515 } else {
06516
06517 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06518 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06519 unalloc_sub(p, SUB_THREEWAY);
06520 if (p->subs[SUB_REAL].inthreeway) {
06521
06522
06523 ast_debug(1, "Call was complete, setting owner to former third call\n");
06524 p->owner = p->subs[SUB_REAL].owner;
06525 } else {
06526
06527 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06528 p->owner = NULL;
06529 }
06530 p->subs[SUB_REAL].inthreeway = 0;
06531 }
06532 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06533
06534 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06535 unalloc_sub(p, SUB_CALLWAIT);
06536 p->owner = p->subs[SUB_REAL].owner;
06537 if (ast_channel_state(p->owner) != AST_STATE_UP)
06538 p->subs[SUB_REAL].needanswer = 1;
06539 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06540 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06541 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06542 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06543 unalloc_sub(p, SUB_THREEWAY);
06544 if (p->subs[SUB_REAL].inthreeway) {
06545
06546
06547 ast_debug(1, "Call was complete, setting owner to former third call\n");
06548 p->owner = p->subs[SUB_REAL].owner;
06549 } else {
06550
06551 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06552 p->owner = NULL;
06553 }
06554 p->subs[SUB_REAL].inthreeway = 0;
06555 }
06556 } else if (idx == SUB_CALLWAIT) {
06557
06558 if (p->subs[SUB_CALLWAIT].inthreeway) {
06559
06560
06561 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06562 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06563 S_OR(p->mohsuggest, NULL),
06564 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06565 }
06566 p->subs[SUB_THREEWAY].inthreeway = 0;
06567
06568 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06569 unalloc_sub(p, SUB_THREEWAY);
06570 } else
06571 unalloc_sub(p, SUB_CALLWAIT);
06572 } else if (idx == SUB_THREEWAY) {
06573 if (p->subs[SUB_CALLWAIT].inthreeway) {
06574
06575
06576 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06577 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06578 S_OR(p->mohsuggest, NULL),
06579 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06580 }
06581 p->subs[SUB_CALLWAIT].inthreeway = 0;
06582 }
06583 p->subs[SUB_REAL].inthreeway = 0;
06584
06585
06586 unalloc_sub(p, SUB_THREEWAY);
06587 } else {
06588
06589 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06590 }
06591 }
06592
06593 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06594 p->owner = NULL;
06595 p->ringt = 0;
06596 p->distinctivering = 0;
06597 p->confirmanswer = 0;
06598 p->outgoing = 0;
06599 p->digital = 0;
06600 p->faxhandled = 0;
06601 p->pulsedial = 0;
06602 if (p->dsp) {
06603 ast_dsp_free(p->dsp);
06604 p->dsp = NULL;
06605 }
06606
06607 revert_fax_buffers(p, ast);
06608
06609 p->law = p->law_default;
06610 law = p->law_default;
06611 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06612 if (res < 0)
06613 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06614
06615 #ifdef HAVE_OPENR2
06616 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06617 ast_debug(1, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06618
06619 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06620 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06621 } else {
06622 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06623 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06624 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06625 : dahdi_ast_cause_to_r2_cause(ast_channel_hangupcause(ast));
06626 dahdi_r2_disconnect_call(p, r2cause);
06627 }
06628 } else if (p->mfcr2call) {
06629 ast_debug(1, "Clearing call request on channel %d\n", p->channel);
06630
06631
06632
06633
06634 p->mfcr2call = 0;
06635 }
06636 #endif
06637 switch (p->sig) {
06638 case SIG_SS7:
06639 case SIG_MFCR2:
06640 case SIG_PRI_LIB_HANDLE_CASES:
06641 case 0:
06642 break;
06643 default:
06644 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06645 break;
06646 }
06647 if (res < 0) {
06648 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast_channel_name(ast));
06649 }
06650 switch (p->sig) {
06651 case SIG_FXOGS:
06652 case SIG_FXOLS:
06653 case SIG_FXOKS:
06654 memset(&par, 0, sizeof(par));
06655 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06656 if (!res) {
06657 struct analog_pvt *analog_p = p->sig_pvt;
06658 #if 0
06659 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06660 #endif
06661
06662 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06663 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06664 else
06665 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06666 analog_p->fxsoffhookstate = par.rxisoffhook;
06667 }
06668 break;
06669 case SIG_FXSGS:
06670 case SIG_FXSLS:
06671 case SIG_FXSKS:
06672
06673
06674 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
06675 time(&p->guardtime);
06676 p->guardtime += 2;
06677 }
06678 break;
06679 default:
06680 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06681 break;
06682 }
06683 if (p->sig)
06684 dahdi_disable_ec(p);
06685 x = 0;
06686 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06687 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06688 p->didtdd = 0;
06689 p->callwaitcas = 0;
06690 p->callwaiting = p->permcallwaiting;
06691 p->hidecallerid = p->permhidecallerid;
06692 p->waitingfordt.tv_sec = 0;
06693 p->dialing = 0;
06694 p->rdnis[0] = '\0';
06695 update_conf(p);
06696 reset_conf(p);
06697
06698 switch (p->sig) {
06699 case SIG_PRI_LIB_HANDLE_CASES:
06700 case SIG_SS7:
06701 x = 0;
06702 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06703 break;
06704 default:
06705 break;
06706 }
06707 if (num_restart_pending == 0)
06708 restart_monitor();
06709 }
06710
06711 p->callwaitingrepeat = 0;
06712 p->cidcwexpire = 0;
06713 p->cid_suppress_expire = 0;
06714 p->oprmode = 0;
06715 hangup_out:
06716 ast_channel_tech_pvt_set(ast, NULL);
06717 ast_free(p->cidspill);
06718 p->cidspill = NULL;
06719
06720 ast_mutex_unlock(&p->lock);
06721 ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
06722
06723 ast_mutex_lock(&iflock);
06724 if (p->restartpending) {
06725 num_restart_pending--;
06726 }
06727
06728 if (p->destroy) {
06729 destroy_channel(p, 0);
06730 }
06731 ast_mutex_unlock(&iflock);
06732
06733 ast_module_unref(ast_module_info->self);
06734 return 0;
06735 }
06736
06737 static int dahdi_answer(struct ast_channel *ast)
06738 {
06739 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
06740 int res = 0;
06741 int idx;
06742 ast_setstate(ast, AST_STATE_UP);
06743 ast_mutex_lock(&p->lock);
06744 idx = dahdi_get_index(ast, p, 0);
06745 if (idx < 0)
06746 idx = SUB_REAL;
06747
06748 if ((p->radio || (p->oprmode < 0))) {
06749 ast_mutex_unlock(&p->lock);
06750 return 0;
06751 }
06752
06753 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06754 res = analog_answer(p->sig_pvt, ast);
06755 ast_mutex_unlock(&p->lock);
06756 return res;
06757 }
06758
06759 switch (p->sig) {
06760 #if defined(HAVE_PRI)
06761 case SIG_PRI_LIB_HANDLE_CASES:
06762 res = sig_pri_answer(p->sig_pvt, ast);
06763 break;
06764 #endif
06765 #if defined(HAVE_SS7)
06766 case SIG_SS7:
06767 res = sig_ss7_answer(p->sig_pvt, ast);
06768 break;
06769 #endif
06770 #ifdef HAVE_OPENR2
06771 case SIG_MFCR2:
06772 if (!p->mfcr2_call_accepted) {
06773
06774
06775 p->mfcr2_answer_pending = 1;
06776 if (p->mfcr2_charge_calls) {
06777 ast_debug(1, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06778 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06779 } else {
06780 ast_debug(1, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06781 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06782 }
06783 } else {
06784 ast_debug(1, "Answering MFC/R2 call on chan %d\n", p->channel);
06785 dahdi_r2_answer(p);
06786 }
06787 break;
06788 #endif
06789 case 0:
06790 ast_mutex_unlock(&p->lock);
06791 return 0;
06792 default:
06793 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06794 res = -1;
06795 break;
06796 }
06797 ast_mutex_unlock(&p->lock);
06798 return res;
06799 }
06800
06801 static void disable_dtmf_detect(struct dahdi_pvt *p)
06802 {
06803 int val = 0;
06804
06805 p->ignoredtmf = 1;
06806
06807 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06808
06809 if (!p->hardwaredtmf && p->dsp) {
06810 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06811 ast_dsp_set_features(p->dsp, p->dsp_features);
06812 }
06813 }
06814
06815 static void enable_dtmf_detect(struct dahdi_pvt *p)
06816 {
06817 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06818
06819 if (p->channel == CHAN_PSEUDO)
06820 return;
06821
06822 p->ignoredtmf = 0;
06823
06824 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06825
06826 if (!p->hardwaredtmf && p->dsp) {
06827 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06828 ast_dsp_set_features(p->dsp, p->dsp_features);
06829 }
06830 }
06831
06832 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06833 {
06834 char *cp;
06835 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
06836
06837
06838 if (!p || !data || (*datalen < 1)) {
06839 errno = EINVAL;
06840 return -1;
06841 }
06842
06843 switch (option) {
06844 case AST_OPTION_DIGIT_DETECT:
06845 cp = (char *) data;
06846 *cp = p->ignoredtmf ? 0 : 1;
06847 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06848 break;
06849 case AST_OPTION_FAX_DETECT:
06850 cp = (char *) data;
06851 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06852 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", ast_channel_name(chan));
06853 break;
06854 case AST_OPTION_CC_AGENT_TYPE:
06855 #if defined(HAVE_PRI)
06856 #if defined(HAVE_PRI_CCSS)
06857 if (dahdi_sig_pri_lib_handles(p->sig)) {
06858 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06859 break;
06860 }
06861 #endif
06862 #endif
06863 return -1;
06864 default:
06865 return -1;
06866 }
06867
06868 errno = 0;
06869
06870 return 0;
06871 }
06872
06873 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06874 {
06875 char *cp;
06876 signed char *scp;
06877 int x;
06878 int idx;
06879 struct dahdi_pvt *p = ast_channel_tech_pvt(chan), *pp;
06880 struct oprmode *oprmode;
06881
06882
06883
06884 if (!p || !data || (datalen < 1)) {
06885 errno = EINVAL;
06886 return -1;
06887 }
06888
06889 switch (option) {
06890 case AST_OPTION_TXGAIN:
06891 scp = (signed char *) data;
06892 idx = dahdi_get_index(chan, p, 0);
06893 if (idx < 0) {
06894 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06895 return -1;
06896 }
06897 ast_debug(1, "Setting actual tx gain on %s to %f\n", ast_channel_name(chan), p->txgain + (float) *scp);
06898 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06899 case AST_OPTION_RXGAIN:
06900 scp = (signed char *) data;
06901 idx = dahdi_get_index(chan, p, 0);
06902 if (idx < 0) {
06903 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06904 return -1;
06905 }
06906 ast_debug(1, "Setting actual rx gain on %s to %f\n", ast_channel_name(chan), p->rxgain + (float) *scp);
06907 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06908 case AST_OPTION_TONE_VERIFY:
06909 if (!p->dsp)
06910 break;
06911 cp = (char *) data;
06912 switch (*cp) {
06913 case 1:
06914 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",ast_channel_name(chan));
06915 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06916 break;
06917 case 2:
06918 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",ast_channel_name(chan));
06919 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06920 break;
06921 default:
06922 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",ast_channel_name(chan));
06923 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06924 break;
06925 }
06926 break;
06927 case AST_OPTION_TDD:
06928
06929 cp = (char *) data;
06930 p->mate = 0;
06931 if (!*cp) {
06932 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",ast_channel_name(chan));
06933 if (p->tdd)
06934 tdd_free(p->tdd);
06935 p->tdd = 0;
06936 break;
06937 }
06938 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06939 (*cp == 2) ? "MATE" : "ON", (int) *cp, ast_channel_name(chan));
06940 dahdi_disable_ec(p);
06941
06942 if (!p->didtdd) {
06943 unsigned char mybuf[41000];
06944 unsigned char *buf;
06945 int size, res, fd, len;
06946 struct pollfd fds[1];
06947
06948 buf = mybuf;
06949 memset(buf, 0x7f, sizeof(mybuf));
06950 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06951 len = 40000;
06952 idx = dahdi_get_index(chan, p, 0);
06953 if (idx < 0) {
06954 ast_log(LOG_WARNING, "No index in TDD?\n");
06955 return -1;
06956 }
06957 fd = p->subs[idx].dfd;
06958 while (len) {
06959 if (ast_check_hangup(chan))
06960 return -1;
06961 size = len;
06962 if (size > READ_SIZE)
06963 size = READ_SIZE;
06964 fds[0].fd = fd;
06965 fds[0].events = POLLPRI | POLLOUT;
06966 fds[0].revents = 0;
06967 res = poll(fds, 1, -1);
06968 if (!res) {
06969 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06970 continue;
06971 }
06972
06973 if (fds[0].revents & POLLPRI)
06974 return -1;
06975 if (!(fds[0].revents & POLLOUT)) {
06976 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06977 continue;
06978 }
06979 res = write(fd, buf, size);
06980 if (res != size) {
06981 if (res == -1) return -1;
06982 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06983 break;
06984 }
06985 len -= size;
06986 buf += size;
06987 }
06988 p->didtdd = 1;
06989 }
06990 if (*cp == 2) {
06991 if (p->tdd)
06992 tdd_free(p->tdd);
06993 p->tdd = 0;
06994 p->mate = 1;
06995 break;
06996 }
06997 if (!p->tdd) {
06998 p->tdd = tdd_new();
06999 }
07000 break;
07001 case AST_OPTION_RELAXDTMF:
07002 if (!p->dsp)
07003 break;
07004 cp = (char *) data;
07005 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
07006 *cp ? "ON" : "OFF", (int) *cp, ast_channel_name(chan));
07007 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
07008 break;
07009 case AST_OPTION_AUDIO_MODE:
07010 #if defined(HAVE_PRI)
07011 if (dahdi_sig_pri_lib_handles(p->sig)
07012 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
07013
07014 break;
07015 }
07016 #endif
07017
07018 cp = (char *) data;
07019 if (!*cp) {
07020 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", ast_channel_name(chan));
07021 x = 0;
07022 dahdi_disable_ec(p);
07023 } else {
07024 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", ast_channel_name(chan));
07025 x = 1;
07026 }
07027 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
07028 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
07029 break;
07030 case AST_OPTION_OPRMODE:
07031 oprmode = (struct oprmode *) data;
07032
07033 if (strcasecmp(ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type)) {
07034 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
07035 ast_channel_tech(chan)->type, ast_channel_tech(oprmode->peer)->type);
07036 errno = EINVAL;
07037 return -1;
07038 }
07039 pp = ast_channel_tech_pvt(oprmode->peer);
07040 p->oprmode = pp->oprmode = 0;
07041
07042 p->oprpeer = pp;
07043 pp->oprpeer = p;
07044
07045 if (oprmode->mode)
07046 {
07047 pp->oprmode = oprmode->mode;
07048 p->oprmode = -oprmode->mode;
07049 }
07050 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
07051 oprmode->mode, ast_channel_name(chan),ast_channel_name(oprmode->peer));
07052 break;
07053 case AST_OPTION_ECHOCAN:
07054 cp = (char *) data;
07055 if (*cp) {
07056 ast_debug(1, "Enabling echo cancellation on %s\n", ast_channel_name(chan));
07057 dahdi_enable_ec(p);
07058 } else {
07059 ast_debug(1, "Disabling echo cancellation on %s\n", ast_channel_name(chan));
07060 dahdi_disable_ec(p);
07061 }
07062 break;
07063 case AST_OPTION_DIGIT_DETECT:
07064 cp = (char *) data;
07065 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07066 if (*cp) {
07067 enable_dtmf_detect(p);
07068 } else {
07069 disable_dtmf_detect(p);
07070 }
07071 break;
07072 case AST_OPTION_FAX_DETECT:
07073 cp = (char *) data;
07074 if (p->dsp) {
07075 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", ast_channel_name(chan));
07076 if (*cp) {
07077 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
07078 } else {
07079 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07080 }
07081 ast_dsp_set_features(p->dsp, p->dsp_features);
07082 }
07083 break;
07084 default:
07085 return -1;
07086 }
07087 errno = 0;
07088
07089 return 0;
07090 }
07091
07092 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
07093 {
07094 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07095 int res = 0;
07096
07097 if (!p) {
07098
07099 *buf = '\0';
07100 return -1;
07101 }
07102
07103 if (!strcasecmp(data, "rxgain")) {
07104 ast_mutex_lock(&p->lock);
07105 snprintf(buf, len, "%f", p->rxgain);
07106 ast_mutex_unlock(&p->lock);
07107 } else if (!strcasecmp(data, "txgain")) {
07108 ast_mutex_lock(&p->lock);
07109 snprintf(buf, len, "%f", p->txgain);
07110 ast_mutex_unlock(&p->lock);
07111 } else if (!strcasecmp(data, "dahdi_channel")) {
07112 ast_mutex_lock(&p->lock);
07113 snprintf(buf, len, "%d", p->channel);
07114 ast_mutex_unlock(&p->lock);
07115 } else if (!strcasecmp(data, "dahdi_span")) {
07116 ast_mutex_lock(&p->lock);
07117 snprintf(buf, len, "%d", p->span);
07118 ast_mutex_unlock(&p->lock);
07119 } else if (!strcasecmp(data, "dahdi_type")) {
07120 ast_mutex_lock(&p->lock);
07121 switch (p->sig) {
07122 #if defined(HAVE_OPENR2)
07123 case SIG_MFCR2:
07124 ast_copy_string(buf, "mfc/r2", len);
07125 break;
07126 #endif
07127 #if defined(HAVE_PRI)
07128 case SIG_PRI_LIB_HANDLE_CASES:
07129 ast_copy_string(buf, "pri", len);
07130 break;
07131 #endif
07132 case 0:
07133 ast_copy_string(buf, "pseudo", len);
07134 break;
07135 #if defined(HAVE_SS7)
07136 case SIG_SS7:
07137 ast_copy_string(buf, "ss7", len);
07138 break;
07139 #endif
07140 default:
07141
07142 ast_copy_string(buf, "analog", len);
07143 break;
07144 }
07145 ast_mutex_unlock(&p->lock);
07146 #if defined(HAVE_PRI)
07147 #if defined(HAVE_PRI_REVERSE_CHARGE)
07148 } else if (!strcasecmp(data, "reversecharge")) {
07149 ast_mutex_lock(&p->lock);
07150 switch (p->sig) {
07151 case SIG_PRI_LIB_HANDLE_CASES:
07152 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07153 break;
07154 default:
07155 *buf = '\0';
07156 res = -1;
07157 break;
07158 }
07159 ast_mutex_unlock(&p->lock);
07160 #endif
07161 #if defined(HAVE_PRI_SETUP_KEYPAD)
07162 } else if (!strcasecmp(data, "keypad_digits")) {
07163 ast_mutex_lock(&p->lock);
07164 switch (p->sig) {
07165 case SIG_PRI_LIB_HANDLE_CASES:
07166 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07167 len);
07168 break;
07169 default:
07170 *buf = '\0';
07171 res = -1;
07172 break;
07173 }
07174 ast_mutex_unlock(&p->lock);
07175 #endif
07176 } else if (!strcasecmp(data, "no_media_path")) {
07177 ast_mutex_lock(&p->lock);
07178 switch (p->sig) {
07179 case SIG_PRI_LIB_HANDLE_CASES:
07180
07181
07182
07183
07184 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07185 break;
07186 default:
07187 *buf = '\0';
07188 res = -1;
07189 break;
07190 }
07191 ast_mutex_unlock(&p->lock);
07192 #endif
07193 } else {
07194 *buf = '\0';
07195 res = -1;
07196 }
07197
07198 return res;
07199 }
07200
07201
07202 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07203 {
07204 int res;
07205 char policy_str[21] = "";
07206
07207 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07208 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07209 return 1;
07210 }
07211 if (*num_buffers < 0) {
07212 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07213 return -1;
07214 }
07215 if (!strcasecmp(policy_str, "full")) {
07216 *policy = DAHDI_POLICY_WHEN_FULL;
07217 } else if (!strcasecmp(policy_str, "immediate")) {
07218 *policy = DAHDI_POLICY_IMMEDIATE;
07219 #if defined(HAVE_DAHDI_HALF_FULL)
07220 } else if (!strcasecmp(policy_str, "half")) {
07221 *policy = DAHDI_POLICY_HALF_FULL;
07222 #endif
07223 } else {
07224 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07225 return -1;
07226 }
07227
07228 return 0;
07229 }
07230
07231 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07232 {
07233 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
07234 int res = 0;
07235
07236 if (!p) {
07237
07238 return -1;
07239 }
07240
07241 if (!strcasecmp(data, "buffers")) {
07242 int num_bufs, policy;
07243
07244 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07245 struct dahdi_bufferinfo bi = {
07246 .txbufpolicy = policy,
07247 .rxbufpolicy = policy,
07248 .bufsize = p->bufsize,
07249 .numbufs = num_bufs,
07250 };
07251 int bpres;
07252
07253 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07254 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07255 } else {
07256 p->bufferoverrideinuse = 1;
07257 }
07258 } else {
07259 res = -1;
07260 }
07261 } else if (!strcasecmp(data, "echocan_mode")) {
07262 if (!strcasecmp(value, "on")) {
07263 ast_mutex_lock(&p->lock);
07264 dahdi_enable_ec(p);
07265 ast_mutex_unlock(&p->lock);
07266 } else if (!strcasecmp(value, "off")) {
07267 ast_mutex_lock(&p->lock);
07268 dahdi_disable_ec(p);
07269 ast_mutex_unlock(&p->lock);
07270 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07271 } else if (!strcasecmp(value, "fax")) {
07272 int blah = 1;
07273
07274 ast_mutex_lock(&p->lock);
07275 if (!p->echocanon) {
07276 dahdi_enable_ec(p);
07277 }
07278 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07279 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07280 }
07281 ast_mutex_unlock(&p->lock);
07282 } else if (!strcasecmp(value, "voice")) {
07283 int blah = 0;
07284
07285 ast_mutex_lock(&p->lock);
07286 if (!p->echocanon) {
07287 dahdi_enable_ec(p);
07288 }
07289 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07290 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07291 }
07292 ast_mutex_unlock(&p->lock);
07293 #endif
07294 } else {
07295 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07296 res = -1;
07297 }
07298 } else {
07299 res = -1;
07300 }
07301
07302 return res;
07303 }
07304
07305 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07306 {
07307
07308 int x;
07309 int hasslaves;
07310 if (!master)
07311 return;
07312 if (needlock) {
07313 ast_mutex_lock(&master->lock);
07314 if (slave) {
07315 while (ast_mutex_trylock(&slave->lock)) {
07316 DEADLOCK_AVOIDANCE(&master->lock);
07317 }
07318 }
07319 }
07320 hasslaves = 0;
07321 for (x = 0; x < MAX_SLAVES; x++) {
07322 if (master->slaves[x]) {
07323 if (!slave || (master->slaves[x] == slave)) {
07324
07325 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07326 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07327 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07328 master->slaves[x]->master = NULL;
07329 master->slaves[x] = NULL;
07330 } else
07331 hasslaves = 1;
07332 }
07333 if (!hasslaves)
07334 master->inconference = 0;
07335 }
07336 if (!slave) {
07337 if (master->master) {
07338
07339 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07340 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07341 hasslaves = 0;
07342 for (x = 0; x < MAX_SLAVES; x++) {
07343 if (master->master->slaves[x] == master)
07344 master->master->slaves[x] = NULL;
07345 else if (master->master->slaves[x])
07346 hasslaves = 1;
07347 }
07348 if (!hasslaves)
07349 master->master->inconference = 0;
07350 }
07351 master->master = NULL;
07352 }
07353 update_conf(master);
07354 if (needlock) {
07355 if (slave)
07356 ast_mutex_unlock(&slave->lock);
07357 ast_mutex_unlock(&master->lock);
07358 }
07359 }
07360
07361 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07362 int x;
07363 if (!slave || !master) {
07364 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07365 return;
07366 }
07367 for (x = 0; x < MAX_SLAVES; x++) {
07368 if (!master->slaves[x]) {
07369 master->slaves[x] = slave;
07370 break;
07371 }
07372 }
07373 if (x >= MAX_SLAVES) {
07374 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07375 master->slaves[MAX_SLAVES - 1] = slave;
07376 }
07377 if (slave->master)
07378 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07379 slave->master = master;
07380
07381 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07382 }
07383
07384 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)
07385 {
07386 struct ast_channel *who;
07387 struct dahdi_pvt *p0, *p1, *op0, *op1;
07388 struct dahdi_pvt *master = NULL, *slave = NULL;
07389 struct ast_frame *f;
07390 int inconf = 0;
07391 int nothingok = 1;
07392 int ofd0, ofd1;
07393 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07394 int os0 = -1, os1 = -1;
07395 int priority = 0;
07396 struct ast_channel *oc0, *oc1;
07397 enum ast_bridge_result res;
07398 struct timeval start = ast_tvnow();
07399 #ifdef PRI_2BCT
07400 int triedtopribridge = 0;
07401 q931_call *q931c0;
07402 q931_call *q931c1;
07403 #endif
07404
07405
07406
07407
07408
07409
07410 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07411 return AST_BRIDGE_FAILED_NOWARN;
07412
07413 ast_channel_lock_both(c0, c1);
07414
07415 p0 = ast_channel_tech_pvt(c0);
07416 p1 = ast_channel_tech_pvt(c1);
07417
07418 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07419 ast_channel_unlock(c0);
07420 ast_channel_unlock(c1);
07421 return AST_BRIDGE_FAILED_NOWARN;
07422 }
07423
07424 oi0 = dahdi_get_index(c0, p0, 0);
07425 oi1 = dahdi_get_index(c1, p1, 0);
07426 if ((oi0 < 0) || (oi1 < 0)) {
07427 ast_channel_unlock(c0);
07428 ast_channel_unlock(c1);
07429 return AST_BRIDGE_FAILED;
07430 }
07431
07432 op0 = p0 = ast_channel_tech_pvt(c0);
07433 op1 = p1 = ast_channel_tech_pvt(c1);
07434 ofd0 = ast_channel_fd(c0, 0);
07435 ofd1 = ast_channel_fd(c1, 0);
07436 oc0 = p0->owner;
07437 oc1 = p1->owner;
07438
07439 if (ast_mutex_trylock(&p0->lock)) {
07440
07441 ast_channel_unlock(c0);
07442 ast_channel_unlock(c1);
07443 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07444 return AST_BRIDGE_RETRY;
07445 }
07446 if (ast_mutex_trylock(&p1->lock)) {
07447
07448 ast_mutex_unlock(&p0->lock);
07449 ast_channel_unlock(c0);
07450 ast_channel_unlock(c1);
07451 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07452 return AST_BRIDGE_RETRY;
07453 }
07454
07455 if ((p0->callwaiting && p0->callwaitingcallerid)
07456 || (p1->callwaiting && p1->callwaitingcallerid)) {
07457
07458
07459
07460
07461
07462
07463
07464
07465
07466 ast_mutex_unlock(&p0->lock);
07467 ast_mutex_unlock(&p1->lock);
07468 ast_channel_unlock(c0);
07469 ast_channel_unlock(c1);
07470 return AST_BRIDGE_FAILED_NOWARN;
07471 }
07472
07473 #if defined(HAVE_PRI)
07474 if ((dahdi_sig_pri_lib_handles(p0->sig)
07475 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07476 || (dahdi_sig_pri_lib_handles(p1->sig)
07477 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07478
07479
07480
07481
07482 ast_mutex_unlock(&p0->lock);
07483 ast_mutex_unlock(&p1->lock);
07484 ast_channel_unlock(c0);
07485 ast_channel_unlock(c1);
07486 return AST_BRIDGE_FAILED_NOWARN;
07487 }
07488 #endif
07489
07490 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07491 if (p0->owner && p1->owner) {
07492
07493 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07494 master = p0;
07495 slave = p1;
07496 inconf = 1;
07497 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07498 master = p1;
07499 slave = p0;
07500 inconf = 1;
07501 } else {
07502 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07503 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07504 p0->channel,
07505 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07506 p0->subs[SUB_REAL].inthreeway, p0->channel,
07507 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07508 p1->subs[SUB_REAL].inthreeway);
07509 }
07510 nothingok = 0;
07511 }
07512 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07513 if (p1->subs[SUB_THREEWAY].inthreeway) {
07514 master = p1;
07515 slave = p0;
07516 nothingok = 0;
07517 }
07518 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07519 if (p0->subs[SUB_THREEWAY].inthreeway) {
07520 master = p0;
07521 slave = p1;
07522 nothingok = 0;
07523 }
07524 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07525
07526
07527 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07528 master = p1;
07529 slave = p0;
07530 nothingok = 0;
07531 }
07532 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07533
07534 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07535 master = p0;
07536 slave = p1;
07537 nothingok = 0;
07538 }
07539 }
07540 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07541 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07542 if (master && slave) {
07543
07544
07545
07546 if ((oi1 == SUB_THREEWAY) &&
07547 p1->subs[SUB_THREEWAY].inthreeway &&
07548 p1->subs[SUB_REAL].owner &&
07549 p1->subs[SUB_REAL].inthreeway &&
07550 (ast_channel_state(p1->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07551 ast_debug(1,
07552 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07553 p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07554 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07555 os1 = ast_channel_state(p1->subs[SUB_REAL].owner);
07556 } else {
07557 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07558 p0->channel, oi0, ast_channel_name(c0), p1->channel, oi1, ast_channel_name(c1));
07559 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07560 }
07561 if ((oi0 == SUB_THREEWAY) &&
07562 p0->subs[SUB_THREEWAY].inthreeway &&
07563 p0->subs[SUB_REAL].owner &&
07564 p0->subs[SUB_REAL].inthreeway &&
07565 (ast_channel_state(p0->subs[SUB_REAL].owner) == AST_STATE_RINGING)) {
07566 ast_debug(1,
07567 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07568 p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07569 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07570 os0 = ast_channel_state(p0->subs[SUB_REAL].owner);
07571 } else {
07572 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07573 p1->channel, oi1, ast_channel_name(c1), p0->channel, oi0, ast_channel_name(c0));
07574 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07575 }
07576 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07577 if (!p0->echocanbridged || !p1->echocanbridged) {
07578
07579 dahdi_disable_ec(p0);
07580 dahdi_disable_ec(p1);
07581 }
07582 }
07583 dahdi_link(slave, master);
07584 master->inconference = inconf;
07585 } else if (!nothingok)
07586 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07587
07588 update_conf(p0);
07589 update_conf(p1);
07590 t0 = p0->subs[SUB_REAL].inthreeway;
07591 t1 = p1->subs[SUB_REAL].inthreeway;
07592
07593 ast_mutex_unlock(&p0->lock);
07594 ast_mutex_unlock(&p1->lock);
07595
07596 ast_channel_unlock(c0);
07597 ast_channel_unlock(c1);
07598
07599
07600 if ((!master || !slave) && !nothingok) {
07601 dahdi_enable_ec(p0);
07602 dahdi_enable_ec(p1);
07603 return AST_BRIDGE_FAILED;
07604 }
07605
07606 ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07607
07608 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07609 disable_dtmf_detect(op0);
07610
07611 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07612 disable_dtmf_detect(op1);
07613
07614 for (;;) {
07615 struct ast_channel *c0_priority[2] = {c0, c1};
07616 struct ast_channel *c1_priority[2] = {c1, c0};
07617 int ms;
07618
07619
07620
07621
07622 ast_channel_lock_both(c0, c1);
07623
07624 p0 = ast_channel_tech_pvt(c0);
07625 p1 = ast_channel_tech_pvt(c1);
07626
07627 if (op0 == p0)
07628 i0 = dahdi_get_index(c0, p0, 1);
07629 if (op1 == p1)
07630 i1 = dahdi_get_index(c1, p1, 1);
07631
07632 ast_channel_unlock(c0);
07633 ast_channel_unlock(c1);
07634 ms = ast_remaining_ms(start, timeoutms);
07635 if (!ms ||
07636 (op0 != p0) ||
07637 (op1 != p1) ||
07638 (ofd0 != ast_channel_fd(c0, 0)) ||
07639 (ofd1 != ast_channel_fd(c1, 0)) ||
07640 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != ast_channel_state(p0->subs[SUB_REAL].owner))) ||
07641 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != ast_channel_state(p1->subs[SUB_REAL].owner))) ||
07642 (oc0 != p0->owner) ||
07643 (oc1 != p1->owner) ||
07644 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07645 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07646 (oi0 != i0) ||
07647 (oi1 != i1)) {
07648 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07649 op0->channel, oi0, op1->channel, oi1);
07650 res = AST_BRIDGE_RETRY;
07651 goto return_from_bridge;
07652 }
07653
07654 #ifdef PRI_2BCT
07655 if (!triedtopribridge) {
07656 triedtopribridge = 1;
07657 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07658 ast_mutex_lock(&p0->pri->lock);
07659 switch (p0->sig) {
07660 case SIG_PRI_LIB_HANDLE_CASES:
07661 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07662 break;
07663 default:
07664 q931c0 = NULL;
07665 break;
07666 }
07667 switch (p1->sig) {
07668 case SIG_PRI_LIB_HANDLE_CASES:
07669 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07670 break;
07671 default:
07672 q931c1 = NULL;
07673 break;
07674 }
07675 if (q931c0 && q931c1) {
07676 pri_channel_bridge(q931c0, q931c1);
07677 }
07678 ast_mutex_unlock(&p0->pri->lock);
07679 }
07680 }
07681 #endif
07682
07683 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07684 if (!who) {
07685 ast_debug(1, "Ooh, empty read...\n");
07686 continue;
07687 }
07688 f = ast_read(who);
07689 switch (f ? f->frametype : AST_FRAME_CONTROL) {
07690 case AST_FRAME_CONTROL:
07691 if (f && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
07692 ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
07693 break;
07694 }
07695 *fo = f;
07696 *rc = who;
07697 res = AST_BRIDGE_COMPLETE;
07698 goto return_from_bridge;
07699 case AST_FRAME_DTMF_END:
07700 if ((who == c0) && p0->pulsedial) {
07701 ast_write(c1, f);
07702 } else if ((who == c1) && p1->pulsedial) {
07703 ast_write(c0, f);
07704 } else {
07705 *fo = f;
07706 *rc = who;
07707 res = AST_BRIDGE_COMPLETE;
07708 goto return_from_bridge;
07709 }
07710 break;
07711 case AST_FRAME_TEXT:
07712 if (who == c0) {
07713 ast_write(c1, f);
07714 } else {
07715 ast_write(c0, f);
07716 }
07717 break;
07718 case AST_FRAME_VOICE:
07719
07720 case AST_FRAME_NULL:
07721 break;
07722 default:
07723 ast_debug(1, "Chan '%s' is discarding frame of frametype:%d\n",
07724 ast_channel_name(who), f->frametype);
07725 break;
07726 }
07727 ast_frfree(f);
07728
07729
07730 priority = !priority;
07731 }
07732
07733 return_from_bridge:
07734 if (op0 == p0)
07735 dahdi_enable_ec(p0);
07736
07737 if (op1 == p1)
07738 dahdi_enable_ec(p1);
07739
07740 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07741 enable_dtmf_detect(op0);
07742
07743 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07744 enable_dtmf_detect(op1);
07745
07746 dahdi_unlink(slave, master, 1);
07747
07748 return res;
07749 }
07750
07751 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07752 {
07753 struct dahdi_pvt *p = ast_channel_tech_pvt(newchan);
07754 int x;
07755
07756 ast_mutex_lock(&p->lock);
07757
07758 ast_debug(1, "New owner for channel %d is %s\n", p->channel, ast_channel_name(newchan));
07759 if (p->owner == oldchan) {
07760 p->owner = newchan;
07761 }
07762 for (x = 0; x < 3; x++) {
07763 if (p->subs[x].owner == oldchan) {
07764 if (!x) {
07765 dahdi_unlink(NULL, p, 0);
07766 }
07767 p->subs[x].owner = newchan;
07768 }
07769 }
07770 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07771 analog_fixup(oldchan, newchan, p->sig_pvt);
07772 #if defined(HAVE_PRI)
07773 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07774 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07775 #endif
07776 #if defined(HAVE_SS7)
07777 } else if (p->sig == SIG_SS7) {
07778 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07779 #endif
07780 }
07781 update_conf(p);
07782
07783 ast_mutex_unlock(&p->lock);
07784
07785 if (ast_channel_state(newchan) == AST_STATE_RINGING) {
07786 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07787 }
07788 return 0;
07789 }
07790
07791 static int dahdi_ring_phone(struct dahdi_pvt *p)
07792 {
07793 int x;
07794 int res;
07795
07796 x = 0;
07797 x = DAHDI_ONHOOK;
07798 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07799 do {
07800 x = DAHDI_RING;
07801 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07802 if (res) {
07803 switch (errno) {
07804 case EBUSY:
07805 case EINTR:
07806
07807 usleep(10000);
07808 continue;
07809 case EINPROGRESS:
07810 res = 0;
07811 break;
07812 default:
07813 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07814 res = 0;
07815 }
07816 }
07817 } while (res);
07818 return res;
07819 }
07820
07821 static void *analog_ss_thread(void *data);
07822
07823 static int attempt_transfer(struct dahdi_pvt *p)
07824 {
07825
07826
07827
07828 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07829
07830
07831 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07832 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07833 if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RINGING) {
07834 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07835 }
07836 if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RING) {
07837 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07838 }
07839 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07840 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07841 ast_channel_name(ast_bridged_channel(p->subs[SUB_REAL].owner)), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07842 return -1;
07843 }
07844
07845 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07846 unalloc_sub(p, SUB_THREEWAY);
07847 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07848 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07849 if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RINGING) {
07850 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07851 }
07852 if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RING) {
07853 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07854 }
07855 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07856 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07857 ast_channel_name(ast_bridged_channel(p->subs[SUB_THREEWAY].owner)), ast_channel_name(p->subs[SUB_REAL].owner));
07858 return -1;
07859 }
07860
07861 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07862 ast_channel_unlock(p->subs[SUB_REAL].owner);
07863 unalloc_sub(p, SUB_THREEWAY);
07864
07865 return 1;
07866 } else {
07867 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07868 ast_channel_name(p->subs[SUB_REAL].owner), ast_channel_name(p->subs[SUB_THREEWAY].owner));
07869 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
07870 return -1;
07871 }
07872 return 0;
07873 }
07874
07875 static int check_for_conference(struct dahdi_pvt *p)
07876 {
07877 struct dahdi_confinfo ci;
07878
07879 if (p->master || (p->confno > -1))
07880 return 0;
07881 memset(&ci, 0, sizeof(ci));
07882 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07883 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07884 return 0;
07885 }
07886
07887
07888
07889 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07890 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07891 return 1;
07892 }
07893 return 0;
07894 }
07895
07896
07897
07898
07899
07900
07901 static int get_alarms(struct dahdi_pvt *p)
07902 {
07903 int res;
07904 struct dahdi_spaninfo zi;
07905 struct dahdi_params params;
07906
07907 memset(&zi, 0, sizeof(zi));
07908 zi.spanno = p->span;
07909
07910 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07911 if (zi.alarms != DAHDI_ALARM_NONE)
07912 return zi.alarms;
07913 } else {
07914 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07915 return 0;
07916 }
07917
07918
07919 memset(¶ms, 0, sizeof(params));
07920 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07921 return params.chan_alarms;
07922
07923 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07924
07925 return DAHDI_ALARM_NONE;
07926 }
07927
07928 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07929 {
07930 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
07931 struct ast_frame *f = *dest;
07932
07933 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07934 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07935 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
07936
07937 if (p->confirmanswer) {
07938 if (f->frametype == AST_FRAME_DTMF_END) {
07939 ast_debug(1, "Confirm answer on %s!\n", ast_channel_name(ast));
07940
07941
07942 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07943 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07944
07945 p->confirmanswer = 0;
07946 } else {
07947 p->subs[idx].f.frametype = AST_FRAME_NULL;
07948 p->subs[idx].f.subclass.integer = 0;
07949 }
07950 *dest = &p->subs[idx].f;
07951 } else if (p->callwaitcas) {
07952 if (f->frametype == AST_FRAME_DTMF_END) {
07953 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07954 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07955 ast_free(p->cidspill);
07956 p->cidspill = NULL;
07957 send_cwcidspill(p);
07958 }
07959 p->callwaitcas = 0;
07960 }
07961 p->subs[idx].f.frametype = AST_FRAME_NULL;
07962 p->subs[idx].f.subclass.integer = 0;
07963 *dest = &p->subs[idx].f;
07964 } else if (f->subclass.integer == 'f') {
07965 if (f->frametype == AST_FRAME_DTMF_END) {
07966
07967 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07968
07969 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07970 struct dahdi_bufferinfo bi = {
07971 .txbufpolicy = p->faxbuf_policy,
07972 .bufsize = p->bufsize,
07973 .numbufs = p->faxbuf_no
07974 };
07975 int res;
07976
07977 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07978 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast_channel_name(ast), strerror(errno));
07979 } else {
07980 p->bufferoverrideinuse = 1;
07981 }
07982 }
07983 p->faxhandled = 1;
07984 if (p->dsp) {
07985 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07986 ast_dsp_set_features(p->dsp, p->dsp_features);
07987 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast_channel_name(ast));
07988 }
07989 if (strcmp(ast_channel_exten(ast), "fax")) {
07990 const char *target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
07991
07992
07993
07994
07995
07996 ast_mutex_unlock(&p->lock);
07997 ast_channel_unlock(ast);
07998 if (ast_exists_extension(ast, target_context, "fax", 1,
07999 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
08000 ast_channel_lock(ast);
08001 ast_mutex_lock(&p->lock);
08002 ast_verb(3, "Redirecting %s to fax extension\n", ast_channel_name(ast));
08003
08004 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
08005 if (ast_async_goto(ast, target_context, "fax", 1))
08006 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), target_context);
08007 } else {
08008 ast_channel_lock(ast);
08009 ast_mutex_lock(&p->lock);
08010 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
08011 }
08012 } else {
08013 ast_debug(1, "Already in a fax extension, not redirecting\n");
08014 }
08015 } else {
08016 ast_debug(1, "Fax already handled\n");
08017 }
08018 dahdi_confmute(p, 0);
08019 }
08020 p->subs[idx].f.frametype = AST_FRAME_NULL;
08021 p->subs[idx].f.subclass.integer = 0;
08022 *dest = &p->subs[idx].f;
08023 }
08024 }
08025
08026 static void handle_alarms(struct dahdi_pvt *p, int alms)
08027 {
08028 const char *alarm_str;
08029
08030 #if defined(HAVE_PRI)
08031 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
08032 return;
08033 }
08034 #endif
08035
08036 alarm_str = alarm2str(alms);
08037 if (report_alarms & REPORT_CHANNEL_ALARMS) {
08038 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
08039
08040
08041
08042
08043
08044 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
08045 "Alarm: %s\r\n"
08046 "Channel: %d\r\n",
08047 alarm_str, p->channel);
08048 }
08049
08050 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
08051 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
08052
08053
08054
08055
08056
08057 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
08058 "Alarm: %s\r\n"
08059 "Span: %d\r\n",
08060 alarm_str, p->span);
08061 }
08062 }
08063
08064 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
08065 {
08066 int res, x;
08067 int idx, mysig;
08068 char *c;
08069 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08070 pthread_t threadid;
08071 struct ast_channel *chan;
08072 struct ast_frame *f;
08073
08074 idx = dahdi_get_index(ast, p, 0);
08075 if (idx < 0) {
08076 return &ast_null_frame;
08077 }
08078 mysig = p->sig;
08079 if (p->outsigmod > -1)
08080 mysig = p->outsigmod;
08081 p->subs[idx].f.frametype = AST_FRAME_NULL;
08082 p->subs[idx].f.subclass.integer = 0;
08083 p->subs[idx].f.datalen = 0;
08084 p->subs[idx].f.samples = 0;
08085 p->subs[idx].f.mallocd = 0;
08086 p->subs[idx].f.offset = 0;
08087 p->subs[idx].f.src = "dahdi_handle_event";
08088 p->subs[idx].f.data.ptr = NULL;
08089 f = &p->subs[idx].f;
08090
08091 if (p->fake_event) {
08092 res = p->fake_event;
08093 p->fake_event = 0;
08094 } else
08095 res = dahdi_get_event(p->subs[idx].dfd);
08096
08097 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
08098
08099 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
08100 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
08101 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
08102 #if defined(HAVE_PRI)
08103 if (dahdi_sig_pri_lib_handles(p->sig)
08104 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08105 && p->pri
08106 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08107
08108 } else
08109 #endif
08110 {
08111
08112 dahdi_confmute(p, 0);
08113 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
08114 p->subs[idx].f.subclass.integer = res & 0xff;
08115 dahdi_handle_dtmf(ast, idx, &f);
08116 }
08117 return f;
08118 }
08119
08120 if (res & DAHDI_EVENT_DTMFDOWN) {
08121 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
08122 #if defined(HAVE_PRI)
08123 if (dahdi_sig_pri_lib_handles(p->sig)
08124 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
08125 && p->pri
08126 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
08127
08128 } else
08129 #endif
08130 {
08131
08132 dahdi_confmute(p, 1);
08133 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
08134 p->subs[idx].f.subclass.integer = res & 0xff;
08135 dahdi_handle_dtmf(ast, idx, &f);
08136 }
08137 return &p->subs[idx].f;
08138 }
08139
08140 switch (res) {
08141 case DAHDI_EVENT_EC_DISABLED:
08142 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
08143 p->echocanon = 0;
08144 break;
08145 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
08146 case DAHDI_EVENT_TX_CED_DETECTED:
08147 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
08148 break;
08149 case DAHDI_EVENT_RX_CED_DETECTED:
08150 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
08151 break;
08152 case DAHDI_EVENT_EC_NLP_DISABLED:
08153 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
08154 break;
08155 case DAHDI_EVENT_EC_NLP_ENABLED:
08156 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
08157 break;
08158 #endif
08159 case DAHDI_EVENT_BITSCHANGED:
08160 #ifdef HAVE_OPENR2
08161 if (p->sig != SIG_MFCR2) {
08162 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08163 } else {
08164 ast_debug(1, "bits changed in chan %d\n", p->channel);
08165 openr2_chan_handle_cas(p->r2chan);
08166 }
08167 #else
08168 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08169 #endif
08170 break;
08171 case DAHDI_EVENT_PULSE_START:
08172
08173 if (!ast_channel_pbx(ast))
08174 tone_zone_play_tone(p->subs[idx].dfd, -1);
08175 break;
08176 case DAHDI_EVENT_DIALCOMPLETE:
08177
08178 #if defined(HAVE_PRI)
08179 if (dahdi_sig_pri_lib_handles(p->sig)) {
08180 if (p->inalarm) {
08181 break;
08182 }
08183 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08184 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",
08185 ast_channel_name(ast), strerror(errno));
08186 return NULL;
08187 }
08188 if (x) {
08189
08190 break;
08191 }
08192
08193
08194
08195
08196 sig_pri_dial_complete(p->sig_pvt, ast);
08197 break;
08198 }
08199 #endif
08200 #ifdef HAVE_OPENR2
08201 if ((p->sig & SIG_MFCR2) && p->r2chan && ast_channel_state(ast) != AST_STATE_UP) {
08202
08203
08204 break;
08205 }
08206 #endif
08207 if (p->inalarm) break;
08208 if ((p->radio || (p->oprmode < 0))) break;
08209 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08210 ast_debug(1, "DAHDI_DIALING ioctl failed on %s: %s\n",ast_channel_name(ast), strerror(errno));
08211 return NULL;
08212 }
08213 if (!x) {
08214 dahdi_enable_ec(p);
08215 if (p->echobreak) {
08216 dahdi_train_ec(p);
08217 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08218 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08219 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08220 p->echobreak = 0;
08221 } else {
08222 p->dialing = 0;
08223 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08224
08225 if (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK) {
08226 ast_setstate(ast, AST_STATE_UP);
08227 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08228 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08229 break;
08230 } else {
08231
08232 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08233 }
08234 }
08235 if (ast_channel_state(ast) == AST_STATE_DIALING) {
08236 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08237 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08238 } else if (p->confirmanswer || (!p->dialednone
08239 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08240 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08241 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08242 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08243 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08244 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08245 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08246 || (mysig == SIG_SF_FEATB)))) {
08247 ast_setstate(ast, AST_STATE_RINGING);
08248 } else if (!p->answeronpolarityswitch) {
08249 ast_setstate(ast, AST_STATE_UP);
08250 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08251 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08252
08253 p->polarity = POLARITY_REV;
08254 } else {
08255
08256 p->polarity = POLARITY_IDLE;
08257 }
08258 }
08259 }
08260 }
08261 break;
08262 case DAHDI_EVENT_ALARM:
08263 switch (p->sig) {
08264 #if defined(HAVE_PRI)
08265 case SIG_PRI_LIB_HANDLE_CASES:
08266 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08267 break;
08268 #endif
08269 #if defined(HAVE_SS7)
08270 case SIG_SS7:
08271 sig_ss7_set_alarm(p->sig_pvt, 1);
08272 break;
08273 #endif
08274 default:
08275 p->inalarm = 1;
08276 break;
08277 }
08278 res = get_alarms(p);
08279 handle_alarms(p, res);
08280 #ifdef HAVE_PRI
08281 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08282
08283 } else {
08284 break;
08285 }
08286 #endif
08287 #if defined(HAVE_SS7)
08288 if (p->sig == SIG_SS7)
08289 break;
08290 #endif
08291 #ifdef HAVE_OPENR2
08292 if (p->sig == SIG_MFCR2)
08293 break;
08294 #endif
08295 case DAHDI_EVENT_ONHOOK:
08296 if (p->radio) {
08297 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08298 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08299 break;
08300 }
08301 if (p->oprmode < 0)
08302 {
08303 if (p->oprmode != -1) break;
08304 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08305 {
08306
08307 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08308 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08309 save_conference(p->oprpeer);
08310 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08311 }
08312 break;
08313 }
08314 switch (p->sig) {
08315 case SIG_FXOLS:
08316 case SIG_FXOGS:
08317 case SIG_FXOKS:
08318
08319 if (idx == SUB_REAL) {
08320
08321 if (p->subs[SUB_CALLWAIT].owner) {
08322
08323 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08324 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08325 unalloc_sub(p, SUB_CALLWAIT);
08326 #if 0
08327 p->subs[idx].needanswer = 0;
08328 p->subs[idx].needringing = 0;
08329 #endif
08330 p->callwaitingrepeat = 0;
08331 p->cidcwexpire = 0;
08332 p->cid_suppress_expire = 0;
08333 p->owner = NULL;
08334
08335 if (ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP)
08336 p->dialing = 1;
08337 dahdi_ring_phone(p);
08338 } else if (p->subs[SUB_THREEWAY].owner) {
08339 unsigned int mssinceflash;
08340
08341
08342 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08343
08344 DLA_UNLOCK(&p->lock);
08345 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08346
08347
08348
08349 DLA_LOCK(&p->lock);
08350 if (p->owner != ast) {
08351 ast_log(LOG_WARNING, "This isn't good...\n");
08352 return NULL;
08353 }
08354 }
08355 if (!p->subs[SUB_THREEWAY].owner) {
08356 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08357 return NULL;
08358 }
08359 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08360 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08361 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08362
08363
08364 if (p->subs[SUB_THREEWAY].owner)
08365 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08366 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08367 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08368 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08369 } else if ((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) {
08370 if (p->transfer) {
08371
08372 p->subs[SUB_REAL].inthreeway = 0;
08373 p->subs[SUB_THREEWAY].inthreeway = 0;
08374
08375 if (!p->transfertobusy && ast_channel_state(ast) == AST_STATE_BUSY) {
08376 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08377
08378 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08379 p->owner = NULL;
08380
08381 dahdi_ring_phone(p);
08382 } else {
08383 if ((res = attempt_transfer(p)) < 0) {
08384 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08385 if (p->subs[SUB_THREEWAY].owner)
08386 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08387 } else if (res) {
08388
08389 if (p->subs[SUB_THREEWAY].owner)
08390 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08391 break;
08392 }
08393 }
08394 } else {
08395 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08396 if (p->subs[SUB_THREEWAY].owner)
08397 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08398 }
08399 } else {
08400 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08401
08402 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08403 p->owner = NULL;
08404
08405 dahdi_ring_phone(p);
08406 }
08407 }
08408 } else {
08409 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08410 }
08411
08412 default:
08413 dahdi_disable_ec(p);
08414 return NULL;
08415 }
08416 break;
08417 case DAHDI_EVENT_RINGOFFHOOK:
08418 if (p->inalarm) break;
08419 if (p->oprmode < 0)
08420 {
08421 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08422 {
08423
08424 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08425 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08426 restore_conference(p->oprpeer);
08427 }
08428 break;
08429 }
08430 if (p->radio)
08431 {
08432 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08433 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08434 break;
08435 }
08436
08437
08438 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast_channel_state(ast) == AST_STATE_DIALING_OFFHOOK)) {
08439 c = strchr(p->dialdest, '/');
08440 if (c)
08441 c++;
08442 else
08443 c = p->dialdest;
08444 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08445 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08446 if (strlen(p->dop.dialstr) > 4) {
08447 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08448 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08449 p->echorest[sizeof(p->echorest) - 1] = '\0';
08450 p->echobreak = 1;
08451 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08452 } else
08453 p->echobreak = 0;
08454 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08455 int saveerr = errno;
08456
08457 x = DAHDI_ONHOOK;
08458 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08459 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08460 return NULL;
08461 }
08462 p->dialing = 1;
08463 return &p->subs[idx].f;
08464 }
08465 switch (p->sig) {
08466 case SIG_FXOLS:
08467 case SIG_FXOGS:
08468 case SIG_FXOKS:
08469 switch (ast_channel_state(ast)) {
08470 case AST_STATE_RINGING:
08471 dahdi_enable_ec(p);
08472 dahdi_train_ec(p);
08473 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08474 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08475
08476 p->subs[SUB_REAL].needringing = 0;
08477 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08478 ast_debug(1, "channel %d answered\n", p->channel);
08479
08480
08481 ast_free(p->cidspill);
08482 p->cidspill = NULL;
08483 restore_conference(p);
08484
08485 p->dialing = 0;
08486 p->callwaitcas = 0;
08487 if (p->confirmanswer) {
08488
08489 p->subs[idx].f.frametype = AST_FRAME_NULL;
08490 p->subs[idx].f.subclass.integer = 0;
08491 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08492
08493 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08494 if (res < 0) {
08495 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08496 p->dop.dialstr[0] = '\0';
08497 return NULL;
08498 } else {
08499 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08500 p->subs[idx].f.frametype = AST_FRAME_NULL;
08501 p->subs[idx].f.subclass.integer = 0;
08502 p->dialing = 1;
08503 }
08504 p->dop.dialstr[0] = '\0';
08505 ast_setstate(ast, AST_STATE_DIALING);
08506 } else
08507 ast_setstate(ast, AST_STATE_UP);
08508 return &p->subs[idx].f;
08509 case AST_STATE_DOWN:
08510 ast_setstate(ast, AST_STATE_RING);
08511 ast_channel_rings_set(ast, 1);
08512 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08513 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08514 ast_debug(1, "channel %d picked up\n", p->channel);
08515 return &p->subs[idx].f;
08516 case AST_STATE_UP:
08517
08518 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08519
08520 if (ast_bridged_channel(p->owner))
08521 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08522 p->subs[idx].needunhold = 1;
08523 break;
08524 case AST_STATE_RESERVED:
08525
08526 if (has_voicemail(p))
08527 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08528 else
08529 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08530 break;
08531 default:
08532 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast_channel_state(ast));
08533 }
08534 break;
08535 case SIG_FXSLS:
08536 case SIG_FXSGS:
08537 case SIG_FXSKS:
08538 if (ast_channel_state(ast) == AST_STATE_RING) {
08539 p->ringt = p->ringt_base;
08540 }
08541
08542
08543
08544 ast_debug(1, "Setting IDLE polarity due "
08545 "to ring. Old polarity was %d\n",
08546 p->polarity);
08547 p->polarity = POLARITY_IDLE;
08548
08549
08550 case SIG_EM:
08551 case SIG_EM_E1:
08552 case SIG_EMWINK:
08553 case SIG_FEATD:
08554 case SIG_FEATDMF:
08555 case SIG_FEATDMF_TA:
08556 case SIG_E911:
08557 case SIG_FGC_CAMA:
08558 case SIG_FGC_CAMAMF:
08559 case SIG_FEATB:
08560 case SIG_SF:
08561 case SIG_SFWINK:
08562 case SIG_SF_FEATD:
08563 case SIG_SF_FEATDMF:
08564 case SIG_SF_FEATB:
08565 if (ast_channel_state(ast) == AST_STATE_PRERING)
08566 ast_setstate(ast, AST_STATE_RING);
08567 if ((ast_channel_state(ast) == AST_STATE_DOWN) || (ast_channel_state(ast) == AST_STATE_RING)) {
08568 ast_debug(1, "Ring detected\n");
08569 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08570 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08571 } else if (p->outgoing && ((ast_channel_state(ast) == AST_STATE_RINGING) || (ast_channel_state(ast) == AST_STATE_DIALING))) {
08572 ast_debug(1, "Line answered\n");
08573 if (p->confirmanswer) {
08574 p->subs[idx].f.frametype = AST_FRAME_NULL;
08575 p->subs[idx].f.subclass.integer = 0;
08576 } else {
08577 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08578 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08579 ast_setstate(ast, AST_STATE_UP);
08580 }
08581 } else if (ast_channel_state(ast) != AST_STATE_RING)
08582 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast_channel_state(ast), p->channel);
08583 break;
08584 default:
08585 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08586 }
08587 break;
08588 case DAHDI_EVENT_RINGBEGIN:
08589 switch (p->sig) {
08590 case SIG_FXSLS:
08591 case SIG_FXSGS:
08592 case SIG_FXSKS:
08593 if (ast_channel_state(ast) == AST_STATE_RING) {
08594 p->ringt = p->ringt_base;
08595 }
08596 break;
08597 }
08598 break;
08599 case DAHDI_EVENT_RINGERON:
08600 break;
08601 case DAHDI_EVENT_NOALARM:
08602 switch (p->sig) {
08603 #if defined(HAVE_PRI)
08604 case SIG_PRI_LIB_HANDLE_CASES:
08605 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08606 break;
08607 #endif
08608 #if defined(HAVE_SS7)
08609 case SIG_SS7:
08610 sig_ss7_set_alarm(p->sig_pvt, 0);
08611 break;
08612 #endif
08613 default:
08614 p->inalarm = 0;
08615 break;
08616 }
08617 handle_clear_alarms(p);
08618 break;
08619 case DAHDI_EVENT_WINKFLASH:
08620 if (p->inalarm) break;
08621 if (p->radio) break;
08622 if (p->oprmode < 0) break;
08623 if (p->oprmode > 1)
08624 {
08625 struct dahdi_params par;
08626
08627 memset(&par, 0, sizeof(par));
08628 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08629 {
08630 if (!par.rxisoffhook)
08631 {
08632
08633 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08634 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08635 save_conference(p);
08636 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08637 }
08638 }
08639 break;
08640 }
08641
08642 p->flashtime = ast_tvnow();
08643 switch (mysig) {
08644 case SIG_FXOLS:
08645 case SIG_FXOGS:
08646 case SIG_FXOKS:
08647 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08648 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08649
08650
08651 ast_free(p->cidspill);
08652 p->cidspill = NULL;
08653 restore_conference(p);
08654 p->callwaitcas = 0;
08655
08656 if (idx != SUB_REAL) {
08657 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08658 goto winkflashdone;
08659 }
08660
08661 if (p->subs[SUB_CALLWAIT].owner) {
08662
08663 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08664 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08665 p->owner = p->subs[SUB_REAL].owner;
08666 ast_debug(1, "Making %s the new owner\n", ast_channel_name(p->owner));
08667 if (ast_channel_state(p->owner) == AST_STATE_RINGING) {
08668 ast_setstate(p->owner, AST_STATE_UP);
08669 p->subs[SUB_REAL].needanswer = 1;
08670 }
08671 p->callwaitingrepeat = 0;
08672 p->cidcwexpire = 0;
08673 p->cid_suppress_expire = 0;
08674
08675 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08676 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08677 S_OR(p->mohsuggest, NULL),
08678 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08679 }
08680 p->subs[SUB_CALLWAIT].needhold = 1;
08681 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08682 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08683 S_OR(p->mohsuggest, NULL),
08684 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08685 }
08686 p->subs[SUB_REAL].needunhold = 1;
08687 } else if (!p->subs[SUB_THREEWAY].owner) {
08688 if (!p->threewaycalling) {
08689
08690 p->subs[SUB_REAL].needflash = 1;
08691 goto winkflashdone;
08692 } else if (!check_for_conference(p)) {
08693 struct ast_callid *callid = NULL;
08694 int callid_created;
08695 char cid_num[256];
08696 char cid_name[256];
08697
08698 cid_num[0] = 0;
08699 cid_name[0] = 0;
08700 if (p->dahditrcallerid && p->owner) {
08701 if (ast_channel_caller(p->owner)->id.number.valid
08702 && ast_channel_caller(p->owner)->id.number.str) {
08703 ast_copy_string(cid_num, ast_channel_caller(p->owner)->id.number.str,
08704 sizeof(cid_num));
08705 }
08706 if (ast_channel_caller(p->owner)->id.name.valid
08707 && ast_channel_caller(p->owner)->id.name.str) {
08708 ast_copy_string(cid_name, ast_channel_caller(p->owner)->id.name.str,
08709 sizeof(cid_name));
08710 }
08711 }
08712
08713
08714 if (!((ast_channel_pbx(ast)) ||
08715 (ast_channel_state(ast) == AST_STATE_UP) ||
08716 (ast_channel_state(ast) == AST_STATE_RING))) {
08717 ast_debug(1, "Flash when call not up or ringing\n");
08718 goto winkflashdone;
08719 }
08720 if (alloc_sub(p, SUB_THREEWAY)) {
08721 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08722 goto winkflashdone;
08723 }
08724 callid_created = ast_callid_threadstorage_auto(&callid);
08725
08726
08727
08728
08729
08730
08731 ast_mutex_unlock(&p->lock);
08732 ast_channel_unlock(ast);
08733 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL, callid);
08734 ast_channel_lock(ast);
08735 ast_mutex_lock(&p->lock);
08736 if (p->dahditrcallerid) {
08737 if (!p->origcid_num)
08738 p->origcid_num = ast_strdup(p->cid_num);
08739 if (!p->origcid_name)
08740 p->origcid_name = ast_strdup(p->cid_name);
08741 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08742 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08743 }
08744
08745 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08746
08747 dahdi_disable_ec(p);
08748 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08749 if (res)
08750 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08751 p->owner = chan;
08752 if (!chan) {
08753 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08754 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08755 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08756 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08757 dahdi_enable_ec(p);
08758 ast_hangup(chan);
08759 } else {
08760 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08761
08762
08763 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08764 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08765 S_OR(p->mohsuggest, NULL),
08766 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08767 }
08768 p->subs[SUB_THREEWAY].needhold = 1;
08769 }
08770 ast_callid_threadstorage_auto_clean(callid, callid_created);
08771 }
08772 } else {
08773
08774 if (p->subs[SUB_THREEWAY].inthreeway) {
08775
08776 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08777
08778 if ((ast_channel_state(p->subs[SUB_REAL].owner) != AST_STATE_UP) && (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_UP)) {
08779
08780 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08781 p->owner = p->subs[SUB_REAL].owner;
08782 }
08783
08784 ast_verb(3, "Dropping three-way call on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08785 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08786 p->subs[SUB_REAL].inthreeway = 0;
08787 p->subs[SUB_THREEWAY].inthreeway = 0;
08788 } else {
08789
08790 if (((ast_channel_pbx(ast)) || (ast_channel_state(ast) == AST_STATE_UP)) &&
08791 (p->transfertobusy || (ast_channel_state(ast) != AST_STATE_BUSY))) {
08792 int otherindex = SUB_THREEWAY;
08793
08794 ast_verb(3, "Building conference call with %s and %s\n",
08795 ast_channel_name(p->subs[SUB_THREEWAY].owner),
08796 ast_channel_name(p->subs[SUB_REAL].owner));
08797
08798 p->subs[SUB_THREEWAY].inthreeway = 1;
08799 p->subs[SUB_REAL].inthreeway = 1;
08800 if (ast_channel_state(ast) == AST_STATE_UP) {
08801 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08802 otherindex = SUB_REAL;
08803 }
08804 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08805 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08806 p->subs[otherindex].needunhold = 1;
08807 p->owner = p->subs[SUB_REAL].owner;
08808 } else {
08809 ast_verb(3, "Dumping incomplete call on on %s\n", ast_channel_name(p->subs[SUB_THREEWAY].owner));
08810 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08811 ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
08812 p->owner = p->subs[SUB_REAL].owner;
08813 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08814 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08815 p->subs[SUB_REAL].needunhold = 1;
08816 dahdi_enable_ec(p);
08817 }
08818 }
08819 }
08820 winkflashdone:
08821 update_conf(p);
08822 break;
08823 case SIG_EM:
08824 case SIG_EM_E1:
08825 case SIG_FEATD:
08826 case SIG_SF:
08827 case SIG_SFWINK:
08828 case SIG_SF_FEATD:
08829 case SIG_FXSLS:
08830 case SIG_FXSGS:
08831 if (p->dialing)
08832 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08833 else
08834 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast_channel_state(ast), p->channel);
08835 break;
08836 case SIG_FEATDMF_TA:
08837 switch (p->whichwink) {
08838 case 0:
08839 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", ast_channel_caller(p->owner)->ani2,
08840 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08841 ast_channel_caller(p->owner)->ani.number.str, ""));
08842 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08843 ast_channel_caller(p->owner)->ani2,
08844 S_COR(ast_channel_caller(p->owner)->ani.number.valid,
08845 ast_channel_caller(p->owner)->ani.number.str, ""));
08846 break;
08847 case 1:
08848 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08849 break;
08850 case 2:
08851 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08852 return NULL;
08853 }
08854 p->whichwink++;
08855
08856 case SIG_FEATDMF:
08857 case SIG_E911:
08858 case SIG_FGC_CAMAMF:
08859 case SIG_FGC_CAMA:
08860 case SIG_FEATB:
08861 case SIG_SF_FEATDMF:
08862 case SIG_SF_FEATB:
08863 case SIG_EMWINK:
08864
08865 if (!ast_strlen_zero(p->dop.dialstr)) {
08866 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08867 if (res < 0) {
08868 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08869 p->dop.dialstr[0] = '\0';
08870 return NULL;
08871 } else
08872 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08873 }
08874 p->dop.dialstr[0] = '\0';
08875 break;
08876 default:
08877 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08878 }
08879 break;
08880 case DAHDI_EVENT_HOOKCOMPLETE:
08881 if (p->inalarm) break;
08882 if ((p->radio || (p->oprmode < 0))) break;
08883 if (p->waitingfordt.tv_sec) break;
08884 switch (mysig) {
08885 case SIG_FXSLS:
08886 case SIG_FXSGS:
08887 case SIG_FXSKS:
08888 case SIG_EM:
08889 case SIG_EM_E1:
08890 case SIG_EMWINK:
08891 case SIG_FEATD:
08892 case SIG_SF:
08893 case SIG_SFWINK:
08894 case SIG_SF_FEATD:
08895 if (!ast_strlen_zero(p->dop.dialstr)) {
08896 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08897 if (res < 0) {
08898 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08899 p->dop.dialstr[0] = '\0';
08900 return NULL;
08901 } else
08902 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08903 }
08904 p->dop.dialstr[0] = '\0';
08905 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08906 break;
08907 case SIG_FEATDMF:
08908 case SIG_FEATDMF_TA:
08909 case SIG_E911:
08910 case SIG_FGC_CAMA:
08911 case SIG_FGC_CAMAMF:
08912 case SIG_FEATB:
08913 case SIG_SF_FEATDMF:
08914 case SIG_SF_FEATB:
08915 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08916 break;
08917 default:
08918 break;
08919 }
08920 break;
08921 case DAHDI_EVENT_POLARITY:
08922
08923
08924
08925
08926
08927
08928 if (p->polarity == POLARITY_IDLE) {
08929 p->polarity = POLARITY_REV;
08930 if (p->answeronpolarityswitch &&
08931 ((ast_channel_state(ast) == AST_STATE_DIALING) ||
08932 (ast_channel_state(ast) == AST_STATE_RINGING))) {
08933 ast_debug(1, "Answering on polarity switch!\n");
08934 ast_setstate(p->owner, AST_STATE_UP);
08935 if (p->hanguponpolarityswitch) {
08936 p->polaritydelaytv = ast_tvnow();
08937 }
08938 } else
08939 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast_channel_state(ast));
08940 }
08941
08942
08943 if (p->hanguponpolarityswitch &&
08944 (p->polarityonanswerdelay > 0) &&
08945 (p->polarity == POLARITY_REV) &&
08946 ((ast_channel_state(ast) == AST_STATE_UP) || (ast_channel_state(ast) == AST_STATE_RING)) ) {
08947
08948 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08949
08950 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08951 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08952 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08953 p->polarity = POLARITY_IDLE;
08954 } else
08955 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast_channel_state(ast));
08956
08957 } else {
08958 p->polarity = POLARITY_IDLE;
08959 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast_channel_state(ast));
08960 }
08961
08962 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast_channel_state(ast), p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08963 break;
08964 default:
08965 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08966 }
08967 return &p->subs[idx].f;
08968 }
08969
08970 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08971 {
08972 int res;
08973 int idx;
08974 struct ast_frame *f;
08975 int usedindex = -1;
08976 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
08977
08978 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08979 idx = SUB_REAL;
08980 }
08981
08982 p->subs[idx].f.frametype = AST_FRAME_NULL;
08983 p->subs[idx].f.datalen = 0;
08984 p->subs[idx].f.samples = 0;
08985 p->subs[idx].f.mallocd = 0;
08986 p->subs[idx].f.offset = 0;
08987 p->subs[idx].f.subclass.integer = 0;
08988 p->subs[idx].f.delivery = ast_tv(0,0);
08989 p->subs[idx].f.src = "dahdi_exception";
08990 p->subs[idx].f.data.ptr = NULL;
08991
08992
08993 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08994
08995
08996
08997
08998
08999 if (p->fake_event) {
09000 res = p->fake_event;
09001 p->fake_event = 0;
09002 } else
09003 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
09004
09005 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
09006 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
09007 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
09008 p->owner = p->subs[SUB_REAL].owner;
09009 if (p->owner && ast_bridged_channel(p->owner))
09010 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09011 p->subs[SUB_REAL].needunhold = 1;
09012 }
09013 switch (res) {
09014 case DAHDI_EVENT_ONHOOK:
09015 dahdi_disable_ec(p);
09016 if (p->owner) {
09017 ast_verb(3, "Channel %s still has call, ringing phone\n", ast_channel_name(p->owner));
09018 dahdi_ring_phone(p);
09019 p->callwaitingrepeat = 0;
09020 p->cidcwexpire = 0;
09021 p->cid_suppress_expire = 0;
09022 } else
09023 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09024 update_conf(p);
09025 break;
09026 case DAHDI_EVENT_RINGOFFHOOK:
09027 dahdi_enable_ec(p);
09028 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09029 if (p->owner && (ast_channel_state(p->owner) == AST_STATE_RINGING)) {
09030 p->subs[SUB_REAL].needanswer = 1;
09031 p->dialing = 0;
09032 }
09033 break;
09034 case DAHDI_EVENT_HOOKCOMPLETE:
09035 case DAHDI_EVENT_RINGERON:
09036 case DAHDI_EVENT_RINGEROFF:
09037
09038 break;
09039 case DAHDI_EVENT_WINKFLASH:
09040 p->flashtime = ast_tvnow();
09041 if (p->owner) {
09042 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, ast_channel_name(p->owner));
09043 if (ast_channel_state(p->owner) != AST_STATE_UP) {
09044
09045 usedindex = dahdi_get_index(p->owner, p, 0);
09046 if (usedindex > -1) {
09047 p->subs[usedindex].needanswer = 1;
09048 }
09049 ast_setstate(p->owner, AST_STATE_UP);
09050 }
09051 p->callwaitingrepeat = 0;
09052 p->cidcwexpire = 0;
09053 p->cid_suppress_expire = 0;
09054 if (ast_bridged_channel(p->owner))
09055 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
09056 p->subs[SUB_REAL].needunhold = 1;
09057 } else
09058 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
09059 update_conf(p);
09060 break;
09061 default:
09062 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
09063 }
09064 f = &p->subs[idx].f;
09065 return f;
09066 }
09067 if (!(p->radio || (p->oprmode < 0)))
09068 ast_debug(1, "Exception on %d, channel %d\n", ast_channel_fd(ast, 0), p->channel);
09069
09070 if (ast != p->owner) {
09071 if (p->owner) {
09072 ast_log(LOG_WARNING, "We're %s, not %s\n", ast_channel_name(ast), ast_channel_name(p->owner));
09073 }
09074 f = &p->subs[idx].f;
09075 return f;
09076 }
09077
09078 f = dahdi_handle_event(ast);
09079 if (!f) {
09080 const char *name = ast_strdupa(ast_channel_name(ast));
09081
09082
09083 ast_mutex_unlock(&p->lock);
09084 ast_channel_unlock(ast);
09085 ast_set_hangupsource(ast, name, 0);
09086 ast_channel_lock(ast);
09087 ast_mutex_lock(&p->lock);
09088 }
09089 return f;
09090 }
09091
09092 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
09093 {
09094 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09095 struct ast_frame *f;
09096 ast_mutex_lock(&p->lock);
09097 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09098 struct analog_pvt *analog_p = p->sig_pvt;
09099 f = analog_exception(analog_p, ast);
09100 } else {
09101 f = __dahdi_exception(ast);
09102 }
09103 ast_mutex_unlock(&p->lock);
09104 return f;
09105 }
09106
09107 static struct ast_frame *dahdi_read(struct ast_channel *ast)
09108 {
09109 struct dahdi_pvt *p;
09110 int res;
09111 int idx;
09112 void *readbuf;
09113 struct ast_frame *f;
09114
09115
09116
09117
09118
09119
09120 p = ast_channel_tech_pvt(ast);
09121 while (ast_mutex_trylock(&p->lock)) {
09122 CHANNEL_DEADLOCK_AVOIDANCE(ast);
09123
09124
09125
09126
09127
09128
09129
09130
09131
09132
09133
09134
09135 if (ast_channel_tech_pvt(ast) != p) {
09136
09137 return &ast_null_frame;
09138 }
09139 }
09140
09141 idx = dahdi_get_index(ast, p, 0);
09142
09143
09144 if (idx < 0) {
09145 ast_log(LOG_WARNING, "We don't exist?\n");
09146 ast_mutex_unlock(&p->lock);
09147 return NULL;
09148 }
09149
09150 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
09151 ast_mutex_unlock(&p->lock);
09152 return NULL;
09153 }
09154
09155 p->subs[idx].f.frametype = AST_FRAME_NULL;
09156 p->subs[idx].f.datalen = 0;
09157 p->subs[idx].f.samples = 0;
09158 p->subs[idx].f.mallocd = 0;
09159 p->subs[idx].f.offset = 0;
09160 p->subs[idx].f.subclass.integer = 0;
09161 p->subs[idx].f.delivery = ast_tv(0,0);
09162 p->subs[idx].f.src = "dahdi_read";
09163 p->subs[idx].f.data.ptr = NULL;
09164
09165
09166 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
09167 {
09168 struct dahdi_params ps;
09169
09170 memset(&ps, 0, sizeof(ps));
09171 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09172 ast_mutex_unlock(&p->lock);
09173 return NULL;
09174 }
09175 p->firstradio = 1;
09176 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09177 if (ps.rxisoffhook)
09178 {
09179 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09180 }
09181 else
09182 {
09183 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09184 }
09185 ast_mutex_unlock(&p->lock);
09186 return &p->subs[idx].f;
09187 }
09188 if (p->ringt > 0) {
09189 if (!(--p->ringt)) {
09190 ast_mutex_unlock(&p->lock);
09191 return NULL;
09192 }
09193 }
09194
09195 #ifdef HAVE_OPENR2
09196 if (p->mfcr2) {
09197 openr2_chan_process_event(p->r2chan);
09198 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09199 struct ast_frame fr = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS } };
09200
09201
09202 if (p->mfcr2_call_accepted &&
09203 !p->mfcr2_progress_sent &&
09204 ast_channel_state(ast) == AST_STATE_RINGING) {
09205 ast_debug(1, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09206 ast_queue_frame(p->owner, &fr);
09207 p->mfcr2_progress_sent = 1;
09208 }
09209 }
09210 }
09211 #endif
09212
09213 if (p->subs[idx].needringing) {
09214
09215 p->subs[idx].needringing = 0;
09216 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09217 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09218 ast_setstate(ast, AST_STATE_RINGING);
09219 ast_mutex_unlock(&p->lock);
09220 return &p->subs[idx].f;
09221 }
09222
09223 if (p->subs[idx].needbusy) {
09224
09225 p->subs[idx].needbusy = 0;
09226 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09227 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09228 ast_mutex_unlock(&p->lock);
09229 return &p->subs[idx].f;
09230 }
09231
09232 if (p->subs[idx].needcongestion) {
09233
09234 p->subs[idx].needcongestion = 0;
09235 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09236 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09237 ast_mutex_unlock(&p->lock);
09238 return &p->subs[idx].f;
09239 }
09240
09241 if (p->subs[idx].needanswer) {
09242
09243 p->subs[idx].needanswer = 0;
09244 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09245 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09246 ast_mutex_unlock(&p->lock);
09247 return &p->subs[idx].f;
09248 }
09249 #ifdef HAVE_OPENR2
09250 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09251
09252
09253
09254
09255 ast_mutex_unlock(&p->lock);
09256 return &ast_null_frame;
09257 }
09258 #endif
09259
09260 if (p->subs[idx].needflash) {
09261
09262 p->subs[idx].needflash = 0;
09263 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09264 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09265 ast_mutex_unlock(&p->lock);
09266 return &p->subs[idx].f;
09267 }
09268
09269 if (p->subs[idx].needhold) {
09270
09271 p->subs[idx].needhold = 0;
09272 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09273 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09274 ast_mutex_unlock(&p->lock);
09275 ast_debug(1, "Sending hold on '%s'\n", ast_channel_name(ast));
09276 return &p->subs[idx].f;
09277 }
09278
09279 if (p->subs[idx].needunhold) {
09280
09281 p->subs[idx].needunhold = 0;
09282 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09283 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09284 ast_mutex_unlock(&p->lock);
09285 ast_debug(1, "Sending unhold on '%s'\n", ast_channel_name(ast));
09286 return &p->subs[idx].f;
09287 }
09288
09289
09290
09291
09292
09293 if (p->fake_event && p->owner == ast) {
09294 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09295 struct analog_pvt *analog_p = p->sig_pvt;
09296
09297 f = analog_exception(analog_p, ast);
09298 } else {
09299 f = __dahdi_exception(ast);
09300 }
09301 ast_mutex_unlock(&p->lock);
09302 return f;
09303 }
09304
09305 if (ast_channel_rawreadformat(ast)->id == AST_FORMAT_SLINEAR) {
09306 if (!p->subs[idx].linear) {
09307 p->subs[idx].linear = 1;
09308 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09309 if (res)
09310 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09311 }
09312 } else if ((ast_channel_rawreadformat(ast)->id == AST_FORMAT_ULAW) ||
09313 (ast_channel_rawreadformat(ast)->id == AST_FORMAT_ALAW)) {
09314 if (p->subs[idx].linear) {
09315 p->subs[idx].linear = 0;
09316 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09317 if (res)
09318 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09319 }
09320 } else {
09321 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast_channel_rawreadformat(ast)));
09322 ast_mutex_unlock(&p->lock);
09323 return NULL;
09324 }
09325 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09326 CHECK_BLOCKING(ast);
09327 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09328 ast_clear_flag(ast_channel_flags(ast), AST_FLAG_BLOCKING);
09329
09330 if (res < 0) {
09331 f = NULL;
09332 if (res == -1) {
09333 if (errno == EAGAIN) {
09334
09335 ast_mutex_unlock(&p->lock);
09336 return &p->subs[idx].f;
09337 } else if (errno == ELAST) {
09338 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09339 struct analog_pvt *analog_p = p->sig_pvt;
09340 f = analog_exception(analog_p, ast);
09341 } else {
09342 f = __dahdi_exception(ast);
09343 }
09344 } else
09345 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09346 }
09347 ast_mutex_unlock(&p->lock);
09348 return f;
09349 }
09350 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09351 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09352 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09353 struct analog_pvt *analog_p = p->sig_pvt;
09354 f = analog_exception(analog_p, ast);
09355 } else {
09356 f = __dahdi_exception(ast);
09357 }
09358 ast_mutex_unlock(&p->lock);
09359 return f;
09360 }
09361 if (p->tdd) {
09362 int c;
09363
09364 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09365 if (c < 0) {
09366 ast_debug(1,"tdd_feed failed\n");
09367 ast_mutex_unlock(&p->lock);
09368 return NULL;
09369 }
09370 if (c) {
09371 p->subs[idx].f.subclass.integer = 0;
09372 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09373 p->subs[idx].f.mallocd = 0;
09374 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09375 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09376 p->subs[idx].f.datalen = 1;
09377 *((char *) p->subs[idx].f.data.ptr) = c;
09378 ast_mutex_unlock(&p->lock);
09379 return &p->subs[idx].f;
09380 }
09381 }
09382 if (idx == SUB_REAL) {
09383
09384 if (p->cidcwexpire) {
09385 if (!--p->cidcwexpire) {
09386
09387 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09388 restore_conference(p);
09389 }
09390 }
09391 if (p->cid_suppress_expire) {
09392 --p->cid_suppress_expire;
09393 }
09394 if (p->callwaitingrepeat) {
09395 if (!--p->callwaitingrepeat) {
09396
09397 ++p->callwaitrings;
09398 dahdi_callwait(ast);
09399 }
09400 }
09401 }
09402 if (p->subs[idx].linear) {
09403 p->subs[idx].f.datalen = READ_SIZE * 2;
09404 } else
09405 p->subs[idx].f.datalen = READ_SIZE;
09406
09407
09408 if ((p->owner == ast) && p->cidspill) {
09409 send_callerid(p);
09410 }
09411
09412 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09413 ast_format_copy(&p->subs[idx].f.subclass.format, ast_channel_rawreadformat(ast));
09414 p->subs[idx].f.samples = READ_SIZE;
09415 p->subs[idx].f.mallocd = 0;
09416 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09417 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09418 #if 0
09419 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09420 #endif
09421 if (p->dialing || p->radio ||
09422 (idx && (ast_channel_state(ast) != AST_STATE_UP)) ||
09423 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09424 ) {
09425
09426
09427 p->subs[idx].f.frametype = AST_FRAME_NULL;
09428 p->subs[idx].f.subclass.integer = 0;
09429 p->subs[idx].f.samples = 0;
09430 p->subs[idx].f.mallocd = 0;
09431 p->subs[idx].f.offset = 0;
09432 p->subs[idx].f.data.ptr = NULL;
09433 p->subs[idx].f.datalen= 0;
09434 }
09435 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
09436
09437 int mute;
09438
09439 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09440
09441
09442 mute = ast_dsp_was_muted(p->dsp);
09443 if (p->muting != mute) {
09444 p->muting = mute;
09445 dahdi_confmute(p, mute);
09446 }
09447
09448 if (f) {
09449 if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
09450 && !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
09451 if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
09452 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09453 ast_dsp_set_features(p->dsp, p->dsp_features);
09454 }
09455 }
09456 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09457 if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
09458
09459
09460
09461
09462 ast_frfree(f);
09463 f = NULL;
09464 }
09465 } else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
09466 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
09467
09468 ast_frfree(f);
09469 f = NULL;
09470 }
09471 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09472 || f->frametype == AST_FRAME_DTMF_END) {
09473 #ifdef HAVE_PRI
09474 if (dahdi_sig_pri_lib_handles(p->sig)
09475 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09476 && p->pri
09477 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09478 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09479
09480 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09481 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09482 f->subclass.integer, f->subclass.integer, ast_channel_name(ast));
09483
09484 f->frametype = AST_FRAME_NULL;
09485 f->subclass.integer = 0;
09486 }
09487 #endif
09488
09489 p->pulsedial = 0;
09490 } else if (p->waitingfordt.tv_sec) {
09491 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09492 p->waitingfordt.tv_sec = 0;
09493 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09494 ast_frfree(f);
09495 f = NULL;
09496 } else if (f->frametype == AST_FRAME_VOICE) {
09497 f->frametype = AST_FRAME_NULL;
09498 f->subclass.integer = 0;
09499 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) {
09500 p->waitingfordt.tv_sec = 0;
09501 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09502 ast_dsp_set_features(p->dsp, p->dsp_features);
09503 ast_debug(1, "Got 10 samples of dialtone!\n");
09504 if (!ast_strlen_zero(p->dop.dialstr)) {
09505 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09506 if (res < 0) {
09507 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09508 p->dop.dialstr[0] = '\0';
09509 ast_mutex_unlock(&p->lock);
09510 ast_frfree(f);
09511 return NULL;
09512 } else {
09513 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
09514 p->dialing = 1;
09515 p->dop.dialstr[0] = '\0';
09516 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09517 ast_setstate(ast, AST_STATE_DIALING);
09518 }
09519 }
09520 }
09521 }
09522 }
09523 }
09524 } else
09525 f = &p->subs[idx].f;
09526
09527 if (f) {
09528 switch (f->frametype) {
09529 case AST_FRAME_DTMF_BEGIN:
09530 case AST_FRAME_DTMF_END:
09531 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09532 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09533 } else {
09534 dahdi_handle_dtmf(ast, idx, &f);
09535 }
09536 break;
09537 case AST_FRAME_VOICE:
09538 if (p->cidspill || p->cid_suppress_expire) {
09539
09540 p->subs[idx].f.frametype = AST_FRAME_NULL;
09541 p->subs[idx].f.subclass.integer = 0;
09542 p->subs[idx].f.samples = 0;
09543 p->subs[idx].f.mallocd = 0;
09544 p->subs[idx].f.offset = 0;
09545 p->subs[idx].f.data.ptr = NULL;
09546 p->subs[idx].f.datalen= 0;
09547 }
09548 break;
09549 default:
09550 break;
09551 }
09552 }
09553
09554 ast_mutex_unlock(&p->lock);
09555 return f;
09556 }
09557
09558 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09559 {
09560 int sent=0;
09561 int size;
09562 int res;
09563 int fd;
09564 fd = p->subs[idx].dfd;
09565 while (len) {
09566 size = len;
09567 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09568 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09569 res = write(fd, buf, size);
09570 if (res != size) {
09571 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09572 return sent;
09573 }
09574 len -= size;
09575 buf += size;
09576 }
09577 return sent;
09578 }
09579
09580 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09581 {
09582 struct dahdi_pvt *p = ast_channel_tech_pvt(ast);
09583 int res;
09584 int idx;
09585 idx = dahdi_get_index(ast, p, 0);
09586 if (idx < 0) {
09587 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast_channel_name(ast));
09588 return -1;
09589 }
09590
09591
09592 if (frame->frametype != AST_FRAME_VOICE) {
09593 if (frame->frametype != AST_FRAME_IMAGE)
09594 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09595 return 0;
09596 }
09597 if ((frame->subclass.format.id != AST_FORMAT_SLINEAR) &&
09598 (frame->subclass.format.id != AST_FORMAT_ULAW) &&
09599 (frame->subclass.format.id != AST_FORMAT_ALAW)) {
09600 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
09601 return -1;
09602 }
09603 if (p->dialing) {
09604 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast_channel_name(ast));
09605 return 0;
09606 }
09607 if (!p->owner) {
09608 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast_channel_name(ast));
09609 return 0;
09610 }
09611 if (p->cidspill) {
09612 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09613 ast_channel_name(ast));
09614 return 0;
09615 }
09616
09617 if (!frame->data.ptr || !frame->datalen)
09618 return 0;
09619
09620 if (frame->subclass.format.id == AST_FORMAT_SLINEAR) {
09621 if (!p->subs[idx].linear) {
09622 p->subs[idx].linear = 1;
09623 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09624 if (res)
09625 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09626 }
09627 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09628 } else {
09629
09630 if (p->subs[idx].linear) {
09631 p->subs[idx].linear = 0;
09632 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09633 if (res)
09634 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09635 }
09636 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09637 }
09638 if (res < 0) {
09639 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09640 return -1;
09641 }
09642 return 0;
09643 }
09644
09645 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09646 {
09647 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
09648 int res=-1;
09649 int idx;
09650 int func = DAHDI_FLASH;
09651
09652 ast_mutex_lock(&p->lock);
09653 ast_debug(1, "Requested indication %d on channel %s\n", condition, ast_channel_name(chan));
09654 switch (p->sig) {
09655 #if defined(HAVE_PRI)
09656 case SIG_PRI_LIB_HANDLE_CASES:
09657 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09658 ast_mutex_unlock(&p->lock);
09659 return res;
09660 #endif
09661 #if defined(HAVE_SS7)
09662 case SIG_SS7:
09663 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09664 ast_mutex_unlock(&p->lock);
09665 return res;
09666 #endif
09667 default:
09668 break;
09669 }
09670 #ifdef HAVE_OPENR2
09671 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09672 ast_mutex_unlock(&p->lock);
09673
09674
09675 return 0;
09676 }
09677 #endif
09678 idx = dahdi_get_index(chan, p, 0);
09679 if (idx == SUB_REAL) {
09680 switch (condition) {
09681 case AST_CONTROL_BUSY:
09682 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09683 break;
09684 case AST_CONTROL_RINGING:
09685 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09686
09687 if (ast_channel_state(chan) != AST_STATE_UP) {
09688 if ((ast_channel_state(chan) != AST_STATE_RING) ||
09689 ((p->sig != SIG_FXSKS) &&
09690 (p->sig != SIG_FXSLS) &&
09691 (p->sig != SIG_FXSGS)))
09692 ast_setstate(chan, AST_STATE_RINGING);
09693 }
09694 break;
09695 case AST_CONTROL_INCOMPLETE:
09696 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", ast_channel_name(chan));
09697
09698 res = 0;
09699 break;
09700 case AST_CONTROL_PROCEEDING:
09701 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", ast_channel_name(chan));
09702
09703 res = 0;
09704 break;
09705 case AST_CONTROL_PROGRESS:
09706 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", ast_channel_name(chan));
09707
09708 res = 0;
09709 break;
09710 case AST_CONTROL_CONGESTION:
09711
09712 switch (ast_channel_hangupcause(chan)) {
09713 case AST_CAUSE_USER_BUSY:
09714 case AST_CAUSE_NORMAL_CLEARING:
09715 case 0:
09716
09717 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
09718 break;
09719 default:
09720 break;
09721 }
09722 break;
09723 case AST_CONTROL_HOLD:
09724 ast_moh_start(chan, data, p->mohinterpret);
09725 break;
09726 case AST_CONTROL_UNHOLD:
09727 ast_moh_stop(chan);
09728 break;
09729 case AST_CONTROL_RADIO_KEY:
09730 if (p->radio)
09731 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09732 res = 0;
09733 break;
09734 case AST_CONTROL_RADIO_UNKEY:
09735 if (p->radio)
09736 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09737 res = 0;
09738 break;
09739 case AST_CONTROL_FLASH:
09740
09741 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09742
09743 p->dop.dialstr[0] = '\0';
09744 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09745 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09746 ast_channel_name(chan), strerror(errno));
09747 } else
09748 res = 0;
09749 } else
09750 res = 0;
09751 break;
09752 case AST_CONTROL_SRCUPDATE:
09753 res = 0;
09754 break;
09755 case -1:
09756 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09757 break;
09758 }
09759 } else {
09760 res = 0;
09761 }
09762 ast_mutex_unlock(&p->lock);
09763 return res;
09764 }
09765
09766 #if defined(HAVE_PRI)
09767 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09768 #else
09769 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09770 #endif
09771 {
09772 struct ast_str *chan_name;
09773 int x, y;
09774
09775
09776 if (!(chan_name = ast_str_create(32))) {
09777 return NULL;
09778 }
09779 if (i->channel == CHAN_PSEUDO) {
09780 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09781 #if defined(HAVE_PRI)
09782 } else if (i->pri) {
09783 ast_mutex_lock(&i->pri->lock);
09784 y = ++i->pri->new_chan_seq;
09785 if (is_outgoing) {
09786 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09787 address[0] = '\0';
09788 } else if (ast_strlen_zero(i->cid_subaddr)) {
09789
09790 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09791 } else {
09792
09793 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09794 i->cid_subaddr, y);
09795 }
09796 ast_mutex_unlock(&i->pri->lock);
09797 #endif
09798 } else {
09799 y = 1;
09800 do {
09801 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09802 for (x = 0; x < 3; ++x) {
09803 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09804 ast_channel_name(i->subs[x].owner) + 6)) {
09805 break;
09806 }
09807 }
09808 ++y;
09809 } while (x < 3);
09810 }
09811 return chan_name;
09812 }
09813
09814 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)
09815 {
09816 struct ast_channel *new_channel = dahdi_new(i, state, startpbx, idx, law, linkedid, callid);
09817
09818 ast_callid_threadstorage_auto_clean(callid, callid_created);
09819
09820 return new_channel;
09821 }
09822
09823 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)
09824 {
09825 struct ast_channel *tmp;
09826 struct ast_format deflaw;
09827 int x;
09828 int features;
09829 struct ast_str *chan_name;
09830 struct ast_variable *v;
09831 char *dashptr;
09832 char device_name[AST_CHANNEL_NAME];
09833
09834 if (i->subs[idx].owner) {
09835 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09836 return NULL;
09837 }
09838
09839 ast_format_clear(&deflaw);
09840 #if defined(HAVE_PRI)
09841
09842
09843
09844
09845 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09846 #else
09847 chan_name = create_channel_name(i);
09848 #endif
09849 if (!chan_name) {
09850 return NULL;
09851 }
09852
09853 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));
09854 ast_free(chan_name);
09855 if (!tmp) {
09856 return NULL;
09857 }
09858
09859 if (callid) {
09860 ast_channel_callid_set(tmp, callid);
09861 }
09862
09863 ast_channel_tech_set(tmp, &dahdi_tech);
09864 #if defined(HAVE_PRI)
09865 if (i->pri) {
09866 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09867 }
09868 #endif
09869 ast_channel_cc_params_init(tmp, i->cc_params);
09870 if (law) {
09871 i->law = law;
09872 if (law == DAHDI_LAW_ALAW) {
09873 ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09874 } else {
09875 ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09876 }
09877 } else {
09878 switch (i->sig) {
09879 case SIG_PRI_LIB_HANDLE_CASES:
09880
09881 i->law = (i->law_default == DAHDI_LAW_ALAW)
09882 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09883 break;
09884 default:
09885 i->law = i->law_default;
09886 break;
09887 }
09888 if (i->law_default == DAHDI_LAW_ALAW) {
09889 ast_format_set(&deflaw, AST_FORMAT_ALAW, 0);
09890 } else {
09891 ast_format_set(&deflaw, AST_FORMAT_ULAW, 0);
09892 }
09893 }
09894 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09895 ast_format_cap_add(ast_channel_nativeformats(tmp), &deflaw);
09896
09897 ast_format_copy(ast_channel_rawreadformat(tmp), &deflaw);
09898 ast_format_copy(ast_channel_readformat(tmp), &deflaw);
09899 ast_format_copy(ast_channel_rawwriteformat(tmp), &deflaw);
09900 ast_format_copy(ast_channel_writeformat(tmp), &deflaw);
09901 i->subs[idx].linear = 0;
09902 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09903 features = 0;
09904 if (idx == SUB_REAL) {
09905 if (i->busydetect && CANBUSYDETECT(i))
09906 features |= DSP_FEATURE_BUSY_DETECT;
09907 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09908 features |= DSP_FEATURE_CALL_PROGRESS;
09909 if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
09910 features |= DSP_FEATURE_WAITDIALTONE;
09911 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09912 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09913 features |= DSP_FEATURE_FAX_DETECT;
09914 }
09915 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09916 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09917 i->hardwaredtmf = 0;
09918 features |= DSP_FEATURE_DIGIT_DETECT;
09919 } else if (NEED_MFDETECT(i)) {
09920 i->hardwaredtmf = 1;
09921 features |= DSP_FEATURE_DIGIT_DETECT;
09922 }
09923 }
09924 if (features) {
09925 if (i->dsp) {
09926 ast_debug(1, "Already have a dsp on %s?\n", ast_channel_name(tmp));
09927 } else {
09928 if (i->channel != CHAN_PSEUDO)
09929 i->dsp = ast_dsp_new();
09930 else
09931 i->dsp = NULL;
09932 if (i->dsp) {
09933 i->dsp_features = features;
09934 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09935
09936 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09937
09938
09939 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09940 features = 0;
09941 }
09942 #endif
09943 ast_dsp_set_features(i->dsp, features);
09944 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09945 if (!ast_strlen_zero(progzone))
09946 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09947 if (i->busydetect && CANBUSYDETECT(i)) {
09948 ast_dsp_set_busy_count(i->dsp, i->busycount);
09949 ast_dsp_set_busy_pattern(i->dsp, &i->busy_cadence);
09950 }
09951 }
09952 }
09953 }
09954
09955 i->dialtone_scanning_time_elapsed = 0;
09956
09957 if (state == AST_STATE_RING)
09958 ast_channel_rings_set(tmp, 1);
09959 ast_channel_tech_pvt_set(tmp, i);
09960 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09961
09962 ast_channel_callgroup_set(tmp, i->callgroup);
09963 ast_channel_pickupgroup_set(tmp, i->pickupgroup);
09964 ast_channel_named_callgroups_set(tmp, i->named_callgroups);
09965 ast_channel_named_pickupgroups_set(tmp, i->named_pickupgroups);
09966 }
09967 if (!ast_strlen_zero(i->parkinglot))
09968 ast_channel_parkinglot_set(tmp, i->parkinglot);
09969 if (!ast_strlen_zero(i->language))
09970 ast_channel_language_set(tmp, i->language);
09971 if (!i->owner)
09972 i->owner = tmp;
09973 if (!ast_strlen_zero(i->accountcode))
09974 ast_channel_accountcode_set(tmp, i->accountcode);
09975 if (i->amaflags)
09976 ast_channel_amaflags_set(tmp, i->amaflags);
09977 i->subs[idx].owner = tmp;
09978 ast_channel_context_set(tmp, i->context);
09979 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09980 ast_channel_call_forward_set(tmp, i->call_forward);
09981 }
09982
09983 if (!i->adsi)
09984 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
09985 if (!ast_strlen_zero(i->exten))
09986 ast_channel_exten_set(tmp, i->exten);
09987 if (!ast_strlen_zero(i->rdnis)) {
09988 ast_channel_redirecting(tmp)->from.number.valid = 1;
09989 ast_channel_redirecting(tmp)->from.number.str = ast_strdup(i->rdnis);
09990 }
09991 if (!ast_strlen_zero(i->dnid)) {
09992 ast_channel_dialed(tmp)->number.str = ast_strdup(i->dnid);
09993 }
09994
09995
09996
09997 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09998 if (!ast_strlen_zero(i->cid_ani)) {
09999 ast_channel_caller(tmp)->ani.number.valid = 1;
10000 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_ani);
10001 } else if (!ast_strlen_zero(i->cid_num)) {
10002 ast_channel_caller(tmp)->ani.number.valid = 1;
10003 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10004 }
10005 #else
10006 if (!ast_strlen_zero(i->cid_num)) {
10007 ast_channel_caller(tmp)->ani.number.valid = 1;
10008 ast_channel_caller(tmp)->ani.number.str = ast_strdup(i->cid_num);
10009 }
10010 #endif
10011 ast_channel_caller(tmp)->id.name.presentation = i->callingpres;
10012 ast_channel_caller(tmp)->id.number.presentation = i->callingpres;
10013 ast_channel_caller(tmp)->id.number.plan = i->cid_ton;
10014 ast_channel_caller(tmp)->ani2 = i->cid_ani2;
10015 ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);
10016
10017 i->fake_event = 0;
10018
10019 dahdi_confmute(i, 0);
10020 i->muting = 0;
10021
10022 ast_jb_configure(tmp, &global_jbconf);
10023
10024
10025 ast_copy_string(device_name, ast_channel_name(tmp), sizeof(device_name));
10026 dashptr = strrchr(device_name, '-');
10027 if (dashptr) {
10028 *dashptr = '\0';
10029 }
10030 ast_set_flag(ast_channel_flags(tmp), AST_FLAG_DISABLE_DEVSTATE_CACHE);
10031 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
10032
10033 for (v = i->vars ; v ; v = v->next)
10034 pbx_builtin_setvar_helper(tmp, v->name, v->value);
10035
10036 ast_module_ref(ast_module_info->self);
10037
10038 dahdi_ami_channel_event(i, tmp);
10039 if (startpbx) {
10040 #ifdef HAVE_OPENR2
10041 if (i->mfcr2call) {
10042 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
10043 }
10044 #endif
10045 if (ast_pbx_start(tmp)) {
10046 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
10047 ast_hangup(tmp);
10048 return NULL;
10049 }
10050 }
10051 return tmp;
10052 }
10053
10054
10055 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
10056 {
10057 char c;
10058
10059 *str = 0;
10060 for (;;)
10061 {
10062
10063 c = ast_waitfordigit(chan, ms);
10064
10065 if (c < 1)
10066 return c;
10067 *str++ = c;
10068 *str = 0;
10069 if (strchr(term, c))
10070 return 1;
10071 }
10072 }
10073
10074 static int dahdi_wink(struct dahdi_pvt *p, int idx)
10075 {
10076 int j;
10077 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
10078 for (;;)
10079 {
10080
10081 j = DAHDI_IOMUX_SIGEVENT;
10082
10083 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
10084
10085 if (j & DAHDI_IOMUX_SIGEVENT) break;
10086 }
10087
10088 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
10089 return 0;
10090 }
10091
10092
10093
10094
10095
10096
10097
10098
10099
10100
10101 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
10102 {
10103 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
10104 return analog_dnd(dahdichan->sig_pvt, flag);
10105 }
10106
10107 if (flag == -1) {
10108 return dahdichan->dnd;
10109 }
10110
10111
10112 dahdichan->dnd = flag;
10113 ast_verb(3, "%s DND on channel %d\n",
10114 flag? "Enabled" : "Disabled",
10115 dahdichan->channel);
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
10130 "Channel: DAHDI/%d\r\n"
10131 "Status: %s\r\n", dahdichan->channel,
10132 flag? "enabled" : "disabled");
10133
10134 return 0;
10135 }
10136
10137 static int canmatch_featurecode(const char *exten)
10138 {
10139 int extlen = strlen(exten);
10140 const char *pickup_ext;
10141 if (!extlen) {
10142 return 1;
10143 }
10144 pickup_ext = ast_pickup_ext();
10145 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
10146 return 1;
10147 }
10148
10149 if (exten[0] == '*' && extlen < 3) {
10150 if (extlen == 1) {
10151 return 1;
10152 }
10153
10154 switch (exten[1]) {
10155 case '6':
10156 case '7':
10157 case '8':
10158 return 1;
10159 }
10160 }
10161 return 0;
10162 }
10163
10164 static void *analog_ss_thread(void *data)
10165 {
10166 struct ast_channel *chan = data;
10167 struct dahdi_pvt *p = ast_channel_tech_pvt(chan);
10168 char exten[AST_MAX_EXTENSION] = "";
10169 char exten2[AST_MAX_EXTENSION] = "";
10170 unsigned char buf[256];
10171 char dtmfcid[300];
10172 char dtmfbuf[300];
10173 struct callerid_state *cs = NULL;
10174 char *name = NULL, *number = NULL;
10175 int distMatches;
10176 int curRingData[3];
10177 int receivedRingT;
10178 int counter1;
10179 int counter;
10180 int samples = 0;
10181 struct ast_smdi_md_message *smdi_msg = NULL;
10182 int flags = 0;
10183 int i;
10184 int timeout;
10185 int getforward = 0;
10186 char *s1, *s2;
10187 int len = 0;
10188 int res;
10189 int idx;
10190 struct ast_format tmpfmt;
10191
10192 ast_mutex_lock(&ss_thread_lock);
10193 ss_thread_count++;
10194 ast_mutex_unlock(&ss_thread_lock);
10195
10196
10197
10198 if (!p) {
10199 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
10200 ast_hangup(chan);
10201 goto quit;
10202 }
10203 ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
10204 idx = dahdi_get_index(chan, p, 1);
10205 if (idx < 0) {
10206 ast_log(LOG_WARNING, "Huh?\n");
10207 ast_hangup(chan);
10208 goto quit;
10209 }
10210 if (p->dsp)
10211 ast_dsp_digitreset(p->dsp);
10212 switch (p->sig) {
10213 case SIG_FEATD:
10214 case SIG_FEATDMF:
10215 case SIG_FEATDMF_TA:
10216 case SIG_E911:
10217 case SIG_FGC_CAMAMF:
10218 case SIG_FEATB:
10219 case SIG_EMWINK:
10220 case SIG_SF_FEATD:
10221 case SIG_SF_FEATDMF:
10222 case SIG_SF_FEATB:
10223 case SIG_SFWINK:
10224 if (dahdi_wink(p, idx))
10225 goto quit;
10226
10227 case SIG_EM:
10228 case SIG_EM_E1:
10229 case SIG_SF:
10230 case SIG_FGC_CAMA:
10231 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10232 if (p->dsp)
10233 ast_dsp_digitreset(p->dsp);
10234
10235 if (p->dsp) {
10236 if (NEED_MFDETECT(p))
10237 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10238 else
10239 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10240 }
10241 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10242
10243 if (!p->immediate)
10244
10245 res = ast_waitfordigit(chan, 5000);
10246 else
10247 res = 0;
10248 if (res > 0) {
10249
10250 dtmfbuf[0] = res;
10251 switch (p->sig) {
10252 case SIG_FEATD:
10253 case SIG_SF_FEATD:
10254 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10255 if (res > 0)
10256 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10257 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10258 break;
10259 case SIG_FEATDMF_TA:
10260 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10261 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10262 if (dahdi_wink(p, idx)) goto quit;
10263 dtmfbuf[0] = 0;
10264
10265 res = ast_waitfordigit(chan, 5000);
10266 if (res <= 0) break;
10267 dtmfbuf[0] = res;
10268
10269 case SIG_FEATDMF:
10270 case SIG_E911:
10271 case SIG_FGC_CAMAMF:
10272 case SIG_SF_FEATDMF:
10273 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10274
10275 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10276 {
10277 if (dahdi_wink(p, idx)) goto quit;
10278 dtmfbuf[0] = 0;
10279
10280 res = ast_waitfordigit(chan, 5000);
10281 if (res <= 0) break;
10282 dtmfbuf[0] = res;
10283 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10284 }
10285 if (res > 0) {
10286
10287 if (p->sig == SIG_E911)
10288 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10289 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10290 }
10291 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10292 break;
10293 case SIG_FEATB:
10294 case SIG_SF_FEATB:
10295 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10296 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10297 break;
10298 case SIG_EMWINK:
10299
10300
10301
10302
10303 if (res == '*') {
10304 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10305 if (res > 0)
10306 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10307 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10308 break;
10309 }
10310 default:
10311
10312 len = 1;
10313 dtmfbuf[len] = '\0';
10314 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10315 if (ast_exists_extension(chan, ast_channel_context(chan), dtmfbuf, 1, p->cid_num)) {
10316 timeout = matchdigittimeout;
10317 } else {
10318 timeout = gendigittimeout;
10319 }
10320 res = ast_waitfordigit(chan, timeout);
10321 if (res < 0) {
10322 ast_debug(1, "waitfordigit returned < 0...\n");
10323 ast_hangup(chan);
10324 goto quit;
10325 } else if (res) {
10326 dtmfbuf[len++] = res;
10327 dtmfbuf[len] = '\0';
10328 } else {
10329 break;
10330 }
10331 }
10332 break;
10333 }
10334 }
10335 if (res == -1) {
10336 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10337 ast_hangup(chan);
10338 goto quit;
10339 } else if (res < 0) {
10340 ast_debug(1, "Got hung up before digits finished\n");
10341 ast_hangup(chan);
10342 goto quit;
10343 }
10344
10345 if (p->sig == SIG_FGC_CAMA) {
10346 char anibuf[100];
10347
10348 if (ast_safe_sleep(chan,1000) == -1) {
10349 ast_hangup(chan);
10350 goto quit;
10351 }
10352 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10353 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10354 res = my_getsigstr(chan, anibuf, "#", 10000);
10355 if ((res > 0) && (strlen(anibuf) > 2)) {
10356 if (anibuf[strlen(anibuf) - 1] == '#')
10357 anibuf[strlen(anibuf) - 1] = 0;
10358 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10359 }
10360 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10361 }
10362
10363 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10364 if (ast_strlen_zero(exten))
10365 ast_copy_string(exten, "s", sizeof(exten));
10366 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10367
10368 if (exten[0] == '*') {
10369 char *stringp=NULL;
10370 ast_copy_string(exten2, exten, sizeof(exten2));
10371
10372 stringp=exten2 +1;
10373 s1 = strsep(&stringp, "*");
10374 s2 = strsep(&stringp, "*");
10375 if (s2) {
10376 if (!ast_strlen_zero(p->cid_num))
10377 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10378 else
10379 ast_set_callerid(chan, s1, NULL, s1);
10380 ast_copy_string(exten, s2, sizeof(exten));
10381 } else
10382 ast_copy_string(exten, s1, sizeof(exten));
10383 } else if (p->sig == SIG_FEATD)
10384 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10385 }
10386 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10387 if (exten[0] == '*') {
10388 char *stringp=NULL;
10389 ast_copy_string(exten2, exten, sizeof(exten2));
10390
10391 stringp=exten2 +1;
10392 s1 = strsep(&stringp, "#");
10393 s2 = strsep(&stringp, "#");
10394 if (s2) {
10395 if (!ast_strlen_zero(p->cid_num))
10396 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10397 else
10398 if (*(s1 + 2))
10399 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10400 ast_copy_string(exten, s2 + 1, sizeof(exten));
10401 } else
10402 ast_copy_string(exten, s1 + 2, sizeof(exten));
10403 } else
10404 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10405 }
10406 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10407 if (exten[0] == '*') {
10408 char *stringp=NULL;
10409 ast_copy_string(exten2, exten, sizeof(exten2));
10410
10411 stringp=exten2 +1;
10412 s1 = strsep(&stringp, "#");
10413 s2 = strsep(&stringp, "#");
10414 if (s2 && (*(s2 + 1) == '0')) {
10415 if (*(s2 + 2))
10416 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10417 }
10418 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10419 else ast_copy_string(exten, "911", sizeof(exten));
10420 } else
10421 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10422 }
10423 if (p->sig == SIG_FEATB) {
10424 if (exten[0] == '*') {
10425 char *stringp=NULL;
10426 ast_copy_string(exten2, exten, sizeof(exten2));
10427
10428 stringp=exten2 +1;
10429 s1 = strsep(&stringp, "#");
10430 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10431 } else
10432 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10433 }
10434 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10435 dahdi_wink(p, idx);
10436
10437
10438
10439 if (ast_safe_sleep(chan, 100)) {
10440 ast_hangup(chan);
10441 goto quit;
10442 }
10443 }
10444 dahdi_enable_ec(p);
10445 if (NEED_MFDETECT(p)) {
10446 if (p->dsp) {
10447 if (!p->hardwaredtmf)
10448 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10449 else {
10450 ast_dsp_free(p->dsp);
10451 p->dsp = NULL;
10452 }
10453 }
10454 }
10455
10456 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1,
10457 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
10458 ast_channel_exten_set(chan, exten);
10459 if (p->dsp) ast_dsp_digitreset(p->dsp);
10460 res = ast_pbx_run(chan);
10461 if (res) {
10462 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10463 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10464 }
10465 goto quit;
10466 } else {
10467 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, ast_channel_context(chan));
10468 sleep(2);
10469 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10470 if (res < 0)
10471 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10472 else
10473 sleep(1);
10474 res = ast_streamfile(chan, "ss-noservice", ast_channel_language(chan));
10475 if (res >= 0)
10476 ast_waitstream(chan, "");
10477 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10478 ast_hangup(chan);
10479 goto quit;
10480 }
10481 break;
10482 case SIG_FXOLS:
10483 case SIG_FXOGS:
10484 case SIG_FXOKS:
10485
10486 timeout = firstdigittimeout;
10487
10488
10489 if (p->subs[SUB_THREEWAY].owner)
10490 timeout = 999999;
10491 while (len < AST_MAX_EXTENSION-1) {
10492
10493
10494 if (p->immediate)
10495 res = 's';
10496 else
10497 res = ast_waitfordigit(chan, timeout);
10498 timeout = 0;
10499 if (res < 0) {
10500 ast_debug(1, "waitfordigit returned < 0...\n");
10501 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10502 ast_hangup(chan);
10503 goto quit;
10504 } else if (res) {
10505 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10506 exten[len++]=res;
10507 exten[len] = '\0';
10508 }
10509 if (!ast_ignore_pattern(ast_channel_context(chan), exten))
10510 tone_zone_play_tone(p->subs[idx].dfd, -1);
10511 else
10512 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10513 if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, ast_channel_context(chan))) {
10514 if (!res || !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
10515 if (getforward) {
10516
10517 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10518 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10519 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10520 if (res)
10521 break;
10522 usleep(500000);
10523 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10524 sleep(1);
10525 memset(exten, 0, sizeof(exten));
10526 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10527 len = 0;
10528 getforward = 0;
10529 } else {
10530 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10531 ast_channel_exten_set(chan, exten);
10532 if (!ast_strlen_zero(p->cid_num)) {
10533 if (!p->hidecallerid)
10534 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10535 else
10536 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10537 }
10538 if (!ast_strlen_zero(p->cid_name)) {
10539 if (!p->hidecallerid)
10540 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10541 }
10542 ast_setstate(chan, AST_STATE_RING);
10543 dahdi_enable_ec(p);
10544 res = ast_pbx_run(chan);
10545 if (res) {
10546 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10547 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10548 }
10549 goto quit;
10550 }
10551 } else {
10552
10553
10554 timeout = matchdigittimeout;
10555 }
10556 } else if (res == 0) {
10557 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10558 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10559 dahdi_wait_event(p->subs[idx].dfd);
10560 ast_hangup(chan);
10561 goto quit;
10562 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10563 ast_verb(3, "Disabling call waiting on %s\n", ast_channel_name(chan));
10564
10565 p->callwaiting = 0;
10566 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10567 if (res) {
10568 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10569 ast_channel_name(chan), strerror(errno));
10570 }
10571 len = 0;
10572 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10573 memset(exten, 0, sizeof(exten));
10574 timeout = firstdigittimeout;
10575
10576 } else if (!strcmp(exten,ast_pickup_ext())) {
10577
10578
10579
10580
10581 if (idx == SUB_REAL) {
10582
10583 if (p->subs[SUB_THREEWAY].owner) {
10584
10585
10586 alloc_sub(p, SUB_CALLWAIT);
10587 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10588 unalloc_sub(p, SUB_THREEWAY);
10589 }
10590 dahdi_enable_ec(p);
10591 if (ast_pickup_call(chan)) {
10592 ast_debug(1, "No call pickup possible...\n");
10593 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10594 dahdi_wait_event(p->subs[idx].dfd);
10595 }
10596 ast_hangup(chan);
10597 goto quit;
10598 } else {
10599 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10600 ast_hangup(chan);
10601 goto quit;
10602 }
10603
10604 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10605 ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
10606
10607 p->hidecallerid = 1;
10608 ast_party_number_free(&ast_channel_caller(chan)->id.number);
10609 ast_party_number_init(&ast_channel_caller(chan)->id.number);
10610 ast_party_name_free(&ast_channel_caller(chan)->id.name);
10611 ast_party_name_init(&ast_channel_caller(chan)->id.name);
10612 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10613 if (res) {
10614 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10615 ast_channel_name(chan), strerror(errno));
10616 }
10617 len = 0;
10618 memset(exten, 0, sizeof(exten));
10619 timeout = firstdigittimeout;
10620 } else if (p->callreturn && !strcmp(exten, "*69")) {
10621 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10622 break;
10623 } else if (!strcmp(exten, "*78")) {
10624 dahdi_dnd(p, 1);
10625
10626 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10627 getforward = 0;
10628 memset(exten, 0, sizeof(exten));
10629 len = 0;
10630 } else if (!strcmp(exten, "*79")) {
10631 dahdi_dnd(p, 0);
10632
10633 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10634 getforward = 0;
10635 memset(exten, 0, sizeof(exten));
10636 len = 0;
10637 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10638 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10639 getforward = 1;
10640 memset(exten, 0, sizeof(exten));
10641 len = 0;
10642 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10643 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10644 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10645 memset(p->call_forward, 0, sizeof(p->call_forward));
10646 getforward = 0;
10647 memset(exten, 0, sizeof(exten));
10648 len = 0;
10649 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, ast_channel_context(chan)) &&
10650 p->subs[SUB_THREEWAY].owner &&
10651 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10652
10653
10654 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10655 chan, exten, ast_channel_context(chan), 0, NULL);
10656 ast_verb(3, "Parking call to '%s'\n", ast_channel_name(chan));
10657 break;
10658 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10659 ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
10660
10661 p->hidecallerid = 0;
10662 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10663 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10664 if (res) {
10665 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10666 ast_channel_name(chan), strerror(errno));
10667 }
10668 len = 0;
10669 memset(exten, 0, sizeof(exten));
10670 timeout = firstdigittimeout;
10671 } else if (!strcmp(exten, "*0")) {
10672 struct ast_channel *nbridge =
10673 p->subs[SUB_THREEWAY].owner;
10674 struct dahdi_pvt *pbridge = NULL;
10675
10676 if (nbridge && ast_bridged_channel(nbridge))
10677 pbridge = ast_channel_tech_pvt(ast_bridged_channel(nbridge));
10678 if (nbridge && pbridge &&
10679 (ast_channel_tech(nbridge) == &dahdi_tech) &&
10680 (ast_channel_tech(ast_bridged_channel(nbridge)) == &dahdi_tech) &&
10681 ISTRUNK(pbridge)) {
10682 int func = DAHDI_FLASH;
10683
10684 p->dop.dialstr[0] = '\0';
10685
10686 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10687 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10688 ast_channel_name(nbridge), strerror(errno));
10689 }
10690 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10691 unalloc_sub(p, SUB_THREEWAY);
10692 p->owner = p->subs[SUB_REAL].owner;
10693 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10694 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10695 ast_hangup(chan);
10696 goto quit;
10697 } else {
10698 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10699 dahdi_wait_event(p->subs[idx].dfd);
10700 tone_zone_play_tone(p->subs[idx].dfd, -1);
10701 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10702 unalloc_sub(p, SUB_THREEWAY);
10703 p->owner = p->subs[SUB_REAL].owner;
10704 ast_hangup(chan);
10705 goto quit;
10706 }
10707 } else if (!ast_canmatch_extension(chan, ast_channel_context(chan), exten, 1,
10708 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
10709 && !canmatch_featurecode(exten)) {
10710 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10711 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<Unknown Caller>"),
10712 ast_channel_context(chan));
10713 break;
10714 }
10715 if (!timeout)
10716 timeout = gendigittimeout;
10717 if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
10718 tone_zone_play_tone(p->subs[idx].dfd, -1);
10719 }
10720 break;
10721 case SIG_FXSLS:
10722 case SIG_FXSGS:
10723 case SIG_FXSKS:
10724
10725 if (p->use_smdi && p->smdi_iface) {
10726 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10727
10728 if (smdi_msg != NULL) {
10729 ast_channel_exten_set(chan, smdi_msg->fwd_st);
10730
10731 if (smdi_msg->type == 'B')
10732 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10733 else if (smdi_msg->type == 'N')
10734 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10735
10736 ast_debug(1, "Received SMDI message on %s\n", ast_channel_name(chan));
10737 } else {
10738 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10739 }
10740 }
10741
10742 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10743 number = smdi_msg->calling_st;
10744
10745
10746
10747
10748 } else if (p->use_callerid && (ast_channel_state(chan) == AST_STATE_PRERING &&
10749 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10750
10751 if (p->cid_signalling == CID_SIG_DTMF) {
10752 int k = 0;
10753 int off_ms;
10754 struct timeval start = ast_tvnow();
10755 int ms;
10756 cs = NULL;
10757 ast_debug(1, "Receiving DTMF cid on channel %s\n", ast_channel_name(chan));
10758 dahdi_setlinear(p->subs[idx].dfd, 0);
10759
10760
10761
10762
10763
10764
10765 ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10766 off_ms = 4000;
10767 for (;;) {
10768 struct ast_frame *f;
10769
10770 ms = ast_remaining_ms(start, off_ms);
10771 res = ast_waitfor(chan, ms);
10772 if (res <= 0) {
10773
10774
10775
10776
10777
10778 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10779 "Exiting simple switch\n");
10780 ast_hangup(chan);
10781 goto quit;
10782 }
10783 f = ast_read(chan);
10784 if (!f)
10785 break;
10786 if (f->frametype == AST_FRAME_DTMF) {
10787 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10788 dtmfbuf[k++] = f->subclass.integer;
10789 }
10790 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10791 start = ast_tvnow();
10792 }
10793 ast_frfree(f);
10794 if (ast_channel_state(chan) == AST_STATE_RING ||
10795 ast_channel_state(chan) == AST_STATE_RINGING)
10796 break;
10797 }
10798 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
10799 dtmfbuf[k] = '\0';
10800 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10801
10802 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10803 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10804 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10805
10806 if (!ast_strlen_zero(dtmfcid))
10807 number = dtmfcid;
10808 else
10809 number = NULL;
10810
10811 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10812 cs = callerid_new(p->cid_signalling);
10813 if (cs) {
10814 int off_ms;
10815 struct timeval start;
10816 int ms;
10817 samples = 0;
10818 #if 1
10819 bump_gains(p);
10820 #endif
10821
10822 dahdi_setlinear(p->subs[idx].dfd, 0);
10823
10824
10825 for (;;) {
10826 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10827 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10828 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10829 callerid_free(cs);
10830 ast_hangup(chan);
10831 goto quit;
10832 }
10833 if (i & DAHDI_IOMUX_SIGEVENT) {
10834 res = dahdi_get_event(p->subs[idx].dfd);
10835 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10836 if (res == DAHDI_EVENT_NOALARM) {
10837 p->inalarm = 0;
10838 }
10839
10840 if (p->cid_signalling == CID_SIG_V23_JP) {
10841 if (res == DAHDI_EVENT_RINGBEGIN) {
10842 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10843 usleep(1);
10844 }
10845 } else {
10846 res = 0;
10847 break;
10848 }
10849 } else if (i & DAHDI_IOMUX_READ) {
10850 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10851 if (res < 0) {
10852 if (errno != ELAST) {
10853 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10854 callerid_free(cs);
10855 ast_hangup(chan);
10856 goto quit;
10857 }
10858 break;
10859 }
10860 samples += res;
10861
10862 if (p->cid_signalling == CID_SIG_V23_JP) {
10863 res = callerid_feed_jp(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10864 } else {
10865 res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
10866 }
10867 if (res < 0) {
10868
10869
10870
10871
10872 ast_log(LOG_WARNING,
10873 "Failed to decode CallerID on channel '%s'\n",
10874 ast_channel_name(chan));
10875 break;
10876 } else if (res)
10877 break;
10878 else if (samples > (8000 * 10))
10879 break;
10880 }
10881 }
10882 if (res == 1) {
10883 callerid_get(cs, &name, &number, &flags);
10884 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10885 }
10886
10887 if (p->cid_signalling == CID_SIG_V23_JP) {
10888 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10889 usleep(1);
10890 }
10891
10892
10893 start = ast_tvnow();
10894 off_ms = 4000;
10895 for (;;) {
10896 struct ast_frame *f;
10897
10898 ms = ast_remaining_ms(start, off_ms);
10899 res = ast_waitfor(chan, ms);
10900 if (res <= 0) {
10901 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10902 "Exiting simple switch\n");
10903 ast_hangup(chan);
10904 goto quit;
10905 }
10906 if (!(f = ast_read(chan))) {
10907 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10908 ast_hangup(chan);
10909 goto quit;
10910 }
10911 ast_frfree(f);
10912 if (ast_channel_state(chan) == AST_STATE_RING ||
10913 ast_channel_state(chan) == AST_STATE_RINGING)
10914 break;
10915 }
10916
10917
10918
10919 if (p->usedistinctiveringdetection) {
10920 len = 0;
10921 distMatches = 0;
10922
10923 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10924 curRingData[receivedRingT] = 0;
10925 receivedRingT = 0;
10926 counter = 0;
10927 counter1 = 0;
10928
10929 if (strcmp(p->context,p->defcontext) != 0) {
10930 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10931 ast_channel_context_set(chan, p->defcontext);
10932 }
10933
10934 for (;;) {
10935 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10936 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10937 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10938 callerid_free(cs);
10939 ast_hangup(chan);
10940 goto quit;
10941 }
10942 if (i & DAHDI_IOMUX_SIGEVENT) {
10943 res = dahdi_get_event(p->subs[idx].dfd);
10944 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10945 if (res == DAHDI_EVENT_NOALARM) {
10946 p->inalarm = 0;
10947 }
10948 res = 0;
10949
10950
10951 curRingData[receivedRingT] = p->ringt;
10952
10953 if (p->ringt < p->ringt_base/2)
10954 break;
10955
10956
10957 if (++receivedRingT == ARRAY_LEN(curRingData))
10958 break;
10959 } else if (i & DAHDI_IOMUX_READ) {
10960 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10961 if (res < 0) {
10962 if (errno != ELAST) {
10963 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10964 callerid_free(cs);
10965 ast_hangup(chan);
10966 goto quit;
10967 }
10968 break;
10969 }
10970 if (p->ringt > 0) {
10971 if (!(--p->ringt)) {
10972 res = -1;
10973 break;
10974 }
10975 }
10976 }
10977 }
10978
10979 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10980 for (counter = 0; counter < 3; counter++) {
10981
10982
10983 distMatches = 0;
10984 for (counter1 = 0; counter1 < 3; counter1++) {
10985 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10986 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10987 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10988 curRingData[counter1]);
10989 distMatches++;
10990 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10991 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10992 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10993 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10994 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10995 distMatches++;
10996 }
10997 }
10998
10999 if (distMatches == 3) {
11000
11001 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11002 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11003 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11004 break;
11005 }
11006 }
11007 }
11008
11009 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11010 #if 1
11011 restore_gains(p);
11012 #endif
11013 } else
11014 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11015 } else {
11016 ast_log(LOG_WARNING, "Channel %s in prering "
11017 "state, but I have nothing to do. "
11018 "Terminating simple switch, should be "
11019 "restarted by the actual ring.\n",
11020 ast_channel_name(chan));
11021 ast_hangup(chan);
11022 goto quit;
11023 }
11024 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
11025 if (p->cid_signalling == CID_SIG_DTMF) {
11026 int k = 0;
11027 int off_ms;
11028 struct timeval start;
11029 int ms;
11030 cs = NULL;
11031 dahdi_setlinear(p->subs[idx].dfd, 0);
11032 off_ms = 2000;
11033 start = ast_tvnow();
11034 for (;;) {
11035 struct ast_frame *f;
11036
11037 ms = ast_remaining_ms(start, off_ms);
11038 res = ast_waitfor(chan, ms);
11039 if (res <= 0) {
11040 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
11041 "Exiting simple switch\n");
11042 ast_hangup(chan);
11043 goto quit;
11044 }
11045 f = ast_read(chan);
11046 if (!f) {
11047
11048 ast_hangup(chan);
11049 goto quit;
11050 }
11051 if (f->frametype == AST_FRAME_DTMF) {
11052 dtmfbuf[k++] = f->subclass.integer;
11053 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
11054 start = ast_tvnow();
11055 }
11056 ast_frfree(f);
11057
11058 if (p->ringt_base == p->ringt)
11059 break;
11060 }
11061 dtmfbuf[k] = '\0';
11062 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11063
11064 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
11065 ast_debug(1, "CID is '%s', flags %d\n",
11066 dtmfcid, flags);
11067
11068 if (!ast_strlen_zero(dtmfcid))
11069 number = dtmfcid;
11070 else
11071 number = NULL;
11072
11073 } else {
11074
11075 cs = callerid_new(p->cid_signalling);
11076 if (cs) {
11077 #if 1
11078 bump_gains(p);
11079 #endif
11080 samples = 0;
11081 len = 0;
11082 distMatches = 0;
11083
11084 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
11085 curRingData[receivedRingT] = 0;
11086 receivedRingT = 0;
11087 counter = 0;
11088 counter1 = 0;
11089
11090 if (strcmp(p->context,p->defcontext) != 0) {
11091 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
11092 ast_channel_context_set(chan, p->defcontext);
11093 }
11094
11095
11096 dahdi_setlinear(p->subs[idx].dfd, 0);
11097 for (;;) {
11098 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11099 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11100 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11101 callerid_free(cs);
11102 ast_hangup(chan);
11103 goto quit;
11104 }
11105 if (i & DAHDI_IOMUX_SIGEVENT) {
11106 res = dahdi_get_event(p->subs[idx].dfd);
11107 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11108 if (res == DAHDI_EVENT_NOALARM) {
11109 p->inalarm = 0;
11110 }
11111
11112 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
11113 ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
11114 p->polarity = POLARITY_IDLE;
11115 callerid_free(cs);
11116 ast_hangup(chan);
11117 goto quit;
11118 }
11119 res = 0;
11120
11121
11122 curRingData[receivedRingT] = p->ringt;
11123
11124 if (p->ringt < p->ringt_base/2)
11125 break;
11126
11127
11128 if (++receivedRingT == ARRAY_LEN(curRingData))
11129 break;
11130 } else if (i & DAHDI_IOMUX_READ) {
11131 res = read(p->subs[idx].dfd, buf, sizeof(buf));
11132 if (res < 0) {
11133 if (errno != ELAST) {
11134 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11135 callerid_free(cs);
11136 ast_hangup(chan);
11137 goto quit;
11138 }
11139 break;
11140 }
11141 if (p->ringt > 0) {
11142 if (!(--p->ringt)) {
11143 res = -1;
11144 break;
11145 }
11146 }
11147 samples += res;
11148 res = callerid_feed(cs, buf, res, ast_format_set(&tmpfmt, AST_LAW(p), 0));
11149 if (res < 0) {
11150
11151
11152
11153
11154 ast_log(LOG_WARNING,
11155 "Failed to decode CallerID on channel '%s'\n",
11156 ast_channel_name(chan));
11157 break;
11158 } else if (res)
11159 break;
11160 else if (samples > (8000 * 10))
11161 break;
11162 }
11163 }
11164 if (res == 1) {
11165 callerid_get(cs, &name, &number, &flags);
11166 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
11167 }
11168 if (distinctiveringaftercid == 1) {
11169
11170 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
11171 curRingData[receivedRingT] = 0;
11172 }
11173 receivedRingT = 0;
11174 ast_verb(3, "Detecting post-CID distinctive ring\n");
11175 for (;;) {
11176 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11177 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
11178 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11179 callerid_free(cs);
11180 ast_hangup(chan);
11181 goto quit;
11182 }
11183 if (i & DAHDI_IOMUX_SIGEVENT) {
11184 res = dahdi_get_event(p->subs[idx].dfd);
11185 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
11186 if (res == DAHDI_EVENT_NOALARM) {
11187 p->inalarm = 0;
11188 }
11189 res = 0;
11190
11191
11192 curRingData[receivedRingT] = p->ringt;
11193
11194 if (p->ringt < p->ringt_base/2)
11195 break;
11196
11197
11198 if (++receivedRingT == ARRAY_LEN(curRingData))
11199 break;
11200 } else if (i & DAHDI_IOMUX_READ) {
11201 res = read(p->subs[idx].dfd, buf, sizeof(buf));
11202 if (res < 0) {
11203 if (errno != ELAST) {
11204 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11205 callerid_free(cs);
11206 ast_hangup(chan);
11207 goto quit;
11208 }
11209 break;
11210 }
11211 if (p->ringt > 0) {
11212 if (!(--p->ringt)) {
11213 res = -1;
11214 break;
11215 }
11216 }
11217 }
11218 }
11219 }
11220 if (p->usedistinctiveringdetection) {
11221
11222 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11223
11224 for (counter = 0; counter < 3; counter++) {
11225
11226
11227
11228 ast_verb(3, "Checking %d,%d,%d\n",
11229 p->drings.ringnum[counter].ring[0],
11230 p->drings.ringnum[counter].ring[1],
11231 p->drings.ringnum[counter].ring[2]);
11232 distMatches = 0;
11233 for (counter1 = 0; counter1 < 3; counter1++) {
11234 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11235 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11236 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11237 curRingData[counter1]);
11238 distMatches++;
11239 }
11240 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11241 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11242 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11243 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11244 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11245 distMatches++;
11246 }
11247 }
11248 if (distMatches == 3) {
11249
11250 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11251 ast_channel_context_set(chan, S_OR(p->drings.ringContext[counter].contextData, p->defcontext));
11252 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11253 break;
11254 }
11255 }
11256 }
11257
11258 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11259 #if 1
11260 restore_gains(p);
11261 #endif
11262 if (res < 0) {
11263 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", ast_channel_name(chan));
11264 }
11265 } else
11266 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11267 }
11268 } else
11269 cs = NULL;
11270
11271 if (number)
11272 ast_shrink_phone_number(number);
11273 ast_set_callerid(chan, number, name, number);
11274
11275 if (smdi_msg)
11276 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11277
11278 if (cs)
11279 callerid_free(cs);
11280
11281 my_handle_notify_message(chan, p, flags, -1);
11282
11283 ast_setstate(chan, AST_STATE_RING);
11284 ast_channel_rings_set(chan, 1);
11285 p->ringt = p->ringt_base;
11286 res = ast_pbx_run(chan);
11287 if (res) {
11288 ast_hangup(chan);
11289 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11290 }
11291 goto quit;
11292 default:
11293 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11294 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11295 if (res < 0)
11296 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11297 }
11298 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11299 if (res < 0)
11300 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11301 ast_hangup(chan);
11302 quit:
11303 ast_mutex_lock(&ss_thread_lock);
11304 ss_thread_count--;
11305 ast_cond_signal(&ss_thread_complete);
11306 ast_mutex_unlock(&ss_thread_lock);
11307 return NULL;
11308 }
11309
11310 struct mwi_thread_data {
11311 struct dahdi_pvt *pvt;
11312 unsigned char buf[READ_SIZE];
11313 size_t len;
11314 };
11315
11316 static int calc_energy(const unsigned char *buf, int len, enum ast_format_id law)
11317 {
11318 int x;
11319 int sum = 0;
11320
11321 if (!len)
11322 return 0;
11323
11324 for (x = 0; x < len; x++)
11325 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11326
11327 return sum / len;
11328 }
11329
11330 static void *mwi_thread(void *data)
11331 {
11332 struct mwi_thread_data *mtd = data;
11333 struct callerid_state *cs;
11334 pthread_t threadid;
11335 int samples = 0;
11336 char *name, *number;
11337 int flags;
11338 int i, res;
11339 unsigned int spill_done = 0;
11340 int spill_result = -1;
11341 struct ast_format tmpfmt;
11342
11343 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11344 goto quit_no_clean;
11345 }
11346
11347 callerid_feed(cs, mtd->buf, mtd->len, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0));
11348
11349 bump_gains(mtd->pvt);
11350
11351 for (;;) {
11352 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11353 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11354 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11355 goto quit;
11356 }
11357
11358 if (i & DAHDI_IOMUX_SIGEVENT) {
11359 struct ast_channel *chan;
11360 struct ast_callid *callid = NULL;
11361 int callid_created;
11362
11363
11364
11365
11366 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11367
11368 switch (res) {
11369 case DAHDI_EVENT_NEONMWI_ACTIVE:
11370 case DAHDI_EVENT_NEONMWI_INACTIVE:
11371 case DAHDI_EVENT_NONE:
11372 case DAHDI_EVENT_BITSCHANGED:
11373 break;
11374 case DAHDI_EVENT_NOALARM:
11375 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11376 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11377
11378 analog_p->inalarm = 0;
11379 }
11380 mtd->pvt->inalarm = 0;
11381 handle_clear_alarms(mtd->pvt);
11382 break;
11383 case DAHDI_EVENT_ALARM:
11384 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11385 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11386
11387 analog_p->inalarm = 1;
11388 }
11389 mtd->pvt->inalarm = 1;
11390 res = get_alarms(mtd->pvt);
11391 handle_alarms(mtd->pvt, res);
11392 break;
11393 default:
11394 callid_created = ast_callid_threadstorage_auto(&callid);
11395 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11396 callerid_free(cs);
11397
11398 restore_gains(mtd->pvt);
11399 mtd->pvt->ringt = mtd->pvt->ringt_base;
11400
11401 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid))) {
11402 int result;
11403
11404 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11405 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11406 } else {
11407 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11408 }
11409 if (result) {
11410 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11411 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11412 if (res < 0)
11413 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11414 ast_hangup(chan);
11415 }
11416 } else {
11417 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11418 }
11419
11420 ast_callid_threadstorage_auto_clean(callid, callid_created);
11421 goto quit_no_clean;
11422 }
11423 } else if (i & DAHDI_IOMUX_READ) {
11424 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11425 if (errno != ELAST) {
11426 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11427 goto quit;
11428 }
11429 break;
11430 }
11431 samples += res;
11432 if (!spill_done) {
11433 if ((spill_result = callerid_feed(cs, mtd->buf, res, ast_format_set(&tmpfmt, AST_LAW(mtd->pvt), 0))) < 0) {
11434
11435
11436
11437
11438 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11439 break;
11440 } else if (spill_result) {
11441 spill_done = 1;
11442 }
11443 } else {
11444
11445
11446
11447 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11448 break;
11449 }
11450 if (samples > (8000 * 4))
11451 break;
11452 }
11453 }
11454
11455 if (spill_result == 1) {
11456 callerid_get(cs, &name, &number, &flags);
11457 if (flags & CID_MSGWAITING) {
11458 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11459 notify_message(mtd->pvt->mailbox, 1);
11460 } else if (flags & CID_NOMSGWAITING) {
11461 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11462 notify_message(mtd->pvt->mailbox, 0);
11463 } else {
11464 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11465 }
11466 }
11467
11468
11469 quit:
11470 callerid_free(cs);
11471
11472 restore_gains(mtd->pvt);
11473
11474 quit_no_clean:
11475 mtd->pvt->mwimonitoractive = 0;
11476 ast_free(mtd);
11477
11478 return NULL;
11479 }
11480
11481
11482
11483
11484
11485
11486
11487
11488 static int mwi_send_init(struct dahdi_pvt * pvt)
11489 {
11490 int x;
11491 struct ast_format tmpfmt;
11492
11493 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11494
11495 if (pvt->mwisend_rpas) {
11496 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11497 pvt->mwisendactive = 1;
11498 } else if (pvt->mwisend_fsk) {
11499 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11500 pvt->mwisendactive = 1;
11501 } else {
11502 pvt->mwisendactive = 0;
11503 return 0;
11504 }
11505 #else
11506 if (mwisend_rpas) {
11507 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11508 } else {
11509 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11510 }
11511 pvt->mwisendactive = 1;
11512 #endif
11513
11514 if (pvt->cidspill) {
11515 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11516 ast_free(pvt->cidspill);
11517 pvt->cidspill = NULL;
11518 pvt->cidpos = 0;
11519 pvt->cidlen = 0;
11520 }
11521 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11522 if (!pvt->cidspill) {
11523 pvt->mwisendactive = 0;
11524 return -1;
11525 }
11526 x = DAHDI_FLUSH_BOTH;
11527 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11528 x = 3000;
11529 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11530 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11531 if (pvt->mwisend_fsk) {
11532 #endif
11533 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11534 ast_format_set(&tmpfmt, AST_LAW(pvt), 0), pvt->cid_name, pvt->cid_num, 0);
11535 pvt->cidpos = 0;
11536 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11537 }
11538 #endif
11539 return 0;
11540 }
11541
11542 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11543 {
11544 struct timeval now;
11545 int res;
11546
11547
11548
11549
11550 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11551 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11552 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11553
11554 switch ( pvt->mwisend_data.mwisend_current) {
11555 case MWI_SEND_SA:
11556
11557 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11558 if (res) {
11559 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11560 goto quit;
11561 }
11562 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11563 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11564 break;
11565 case MWI_SEND_SA_WAIT:
11566 break;
11567 case MWI_SEND_PAUSE:
11568 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11569 if (pvt->mwisend_fsk) {
11570 #endif
11571 gettimeofday(&now, NULL);
11572 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11573 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11574 }
11575 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11576 } else {
11577 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11578 }
11579 #endif
11580 break;
11581 case MWI_SEND_SPILL:
11582
11583 if(0 < num_read) {
11584 if (num_read > pvt->cidlen - pvt->cidpos)
11585 num_read = pvt->cidlen - pvt->cidpos;
11586 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11587 if (res > 0) {
11588 pvt->cidpos += res;
11589 if (pvt->cidpos >= pvt->cidlen) {
11590 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11591 }
11592 } else {
11593 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11594 goto quit;
11595 }
11596 }
11597 break;
11598 case MWI_SEND_CLEANUP:
11599
11600 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11601 break;
11602 default:
11603
11604 goto quit;
11605 }
11606 }
11607
11608 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11609 if (pvt->cidspill) {
11610 ast_free(pvt->cidspill);
11611 pvt->cidspill = NULL;
11612 pvt->cidpos = 0;
11613 pvt->cidlen = 0;
11614 }
11615 pvt->mwisendactive = 0;
11616 }
11617 return 0;
11618 quit:
11619 if (pvt->cidspill) {
11620 ast_free(pvt->cidspill);
11621 pvt->cidspill = NULL;
11622 pvt->cidpos = 0;
11623 pvt->cidlen = 0;
11624 }
11625 pvt->mwisendactive = 0;
11626 return -1;
11627 }
11628
11629 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11630 {
11631 int handled = 0;
11632
11633 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11634 switch (event) {
11635 case DAHDI_EVENT_RINGEROFF:
11636 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11637 handled = 1;
11638
11639 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11640 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11641 ast_free(pvt->cidspill);
11642 pvt->cidspill = NULL;
11643 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11644 pvt->mwisendactive = 0;
11645 } else {
11646 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11647 gettimeofday(&pvt->mwisend_data.pause, NULL);
11648 }
11649 }
11650 break;
11651
11652 case DAHDI_EVENT_RINGOFFHOOK:
11653 if (pvt->cidspill) {
11654 ast_free(pvt->cidspill);
11655 pvt->cidspill = NULL;
11656 pvt->cidpos = 0;
11657 pvt->cidlen = 0;
11658 }
11659 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11660 pvt->mwisendactive = 0;
11661 break;
11662 case DAHDI_EVENT_RINGERON:
11663 case DAHDI_EVENT_HOOKCOMPLETE:
11664 break;
11665 default:
11666 break;
11667 }
11668 }
11669 return handled;
11670 }
11671
11672
11673 static int dahdi_destroy_channel_bynum(int channel)
11674 {
11675 struct dahdi_pvt *cur;
11676
11677 ast_mutex_lock(&iflock);
11678 for (cur = iflist; cur; cur = cur->next) {
11679 if (cur->channel == channel) {
11680 int x = DAHDI_FLASH;
11681
11682
11683 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11684
11685 destroy_channel(cur, 1);
11686 ast_mutex_unlock(&iflock);
11687 ast_module_unref(ast_module_info->self);
11688 return RESULT_SUCCESS;
11689 }
11690 }
11691 ast_mutex_unlock(&iflock);
11692 return RESULT_FAILURE;
11693 }
11694
11695 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11696 {
11697 int res;
11698 pthread_t threadid;
11699 struct ast_channel *chan;
11700 struct ast_callid *callid = NULL;
11701 int callid_created;
11702
11703
11704
11705 switch (event) {
11706 case DAHDI_EVENT_NONE:
11707 case DAHDI_EVENT_BITSCHANGED:
11708 break;
11709 case DAHDI_EVENT_WINKFLASH:
11710 case DAHDI_EVENT_RINGOFFHOOK:
11711 if (i->inalarm) break;
11712 if (i->radio) break;
11713
11714 switch (i->sig) {
11715 case SIG_FXOLS:
11716 case SIG_FXOGS:
11717 case SIG_FXOKS:
11718 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11719 if (res && (errno == EBUSY)) {
11720 break;
11721 }
11722
11723 callid_created = ast_callid_threadstorage_auto(&callid);
11724
11725
11726 ast_free(i->cidspill);
11727 i->cidspill = NULL;
11728 restore_conference(i);
11729
11730 if (i->immediate) {
11731 dahdi_enable_ec(i);
11732
11733 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11734 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL, callid);
11735 if (!chan) {
11736 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11737 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11738 if (res < 0)
11739 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11740 }
11741 } else {
11742
11743 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL, callid);
11744 if (chan) {
11745 if (has_voicemail(i))
11746 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11747 else
11748 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11749 if (res < 0)
11750 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11751 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11752 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11753 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11754 if (res < 0)
11755 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11756 ast_hangup(chan);
11757 }
11758 } else
11759 ast_log(LOG_WARNING, "Unable to create channel\n");
11760 }
11761
11762 ast_callid_threadstorage_auto_clean(callid, callid_created);
11763 break;
11764 case SIG_FXSLS:
11765 case SIG_FXSGS:
11766 case SIG_FXSKS:
11767 i->ringt = i->ringt_base;
11768
11769 case SIG_EMWINK:
11770 case SIG_FEATD:
11771 case SIG_FEATDMF:
11772 case SIG_FEATDMF_TA:
11773 case SIG_E911:
11774 case SIG_FGC_CAMA:
11775 case SIG_FGC_CAMAMF:
11776 case SIG_FEATB:
11777 case SIG_EM:
11778 case SIG_EM_E1:
11779 case SIG_SFWINK:
11780 case SIG_SF_FEATD:
11781 case SIG_SF_FEATDMF:
11782 case SIG_SF_FEATB:
11783 case SIG_SF:
11784
11785 callid_created = ast_callid_threadstorage_auto(&callid);
11786 if (i->cid_start == CID_START_POLARITY_IN) {
11787 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11788 } else {
11789 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL, callid);
11790 }
11791
11792 if (!chan) {
11793 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11794 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11795 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11796 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11797 if (res < 0) {
11798 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11799 }
11800 ast_hangup(chan);
11801 }
11802
11803 ast_callid_threadstorage_auto_clean(callid, callid_created);
11804 break;
11805 default:
11806 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11807 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11808 if (res < 0)
11809 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11810 return NULL;
11811 }
11812 break;
11813 case DAHDI_EVENT_NOALARM:
11814 switch (i->sig) {
11815 #if defined(HAVE_PRI)
11816 case SIG_PRI_LIB_HANDLE_CASES:
11817 ast_mutex_lock(&i->lock);
11818 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11819 ast_mutex_unlock(&i->lock);
11820 break;
11821 #endif
11822 #if defined(HAVE_SS7)
11823 case SIG_SS7:
11824 sig_ss7_set_alarm(i->sig_pvt, 0);
11825 break;
11826 #endif
11827 default:
11828 i->inalarm = 0;
11829 break;
11830 }
11831 handle_clear_alarms(i);
11832 break;
11833 case DAHDI_EVENT_ALARM:
11834 switch (i->sig) {
11835 #if defined(HAVE_PRI)
11836 case SIG_PRI_LIB_HANDLE_CASES:
11837 ast_mutex_lock(&i->lock);
11838 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11839 ast_mutex_unlock(&i->lock);
11840 break;
11841 #endif
11842 #if defined(HAVE_SS7)
11843 case SIG_SS7:
11844 sig_ss7_set_alarm(i->sig_pvt, 1);
11845 break;
11846 #endif
11847 default:
11848 i->inalarm = 1;
11849 break;
11850 }
11851 res = get_alarms(i);
11852 handle_alarms(i, res);
11853
11854 case DAHDI_EVENT_ONHOOK:
11855 if (i->radio)
11856 break;
11857
11858 switch (i->sig) {
11859 case SIG_FXOLS:
11860 case SIG_FXOGS:
11861 case SIG_FEATD:
11862 case SIG_FEATDMF:
11863 case SIG_FEATDMF_TA:
11864 case SIG_E911:
11865 case SIG_FGC_CAMA:
11866 case SIG_FGC_CAMAMF:
11867 case SIG_FEATB:
11868 case SIG_EM:
11869 case SIG_EM_E1:
11870 case SIG_EMWINK:
11871 case SIG_SF_FEATD:
11872 case SIG_SF_FEATDMF:
11873 case SIG_SF_FEATB:
11874 case SIG_SF:
11875 case SIG_SFWINK:
11876 case SIG_FXSLS:
11877 case SIG_FXSGS:
11878 case SIG_FXSKS:
11879 case SIG_FXOKS:
11880 dahdi_disable_ec(i);
11881
11882 #ifdef ZHONE_HACK
11883 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11884 usleep(1);
11885 #endif
11886 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11887 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11888 break;
11889 case SIG_SS7:
11890 case SIG_PRI_LIB_HANDLE_CASES:
11891 dahdi_disable_ec(i);
11892 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11893 break;
11894 default:
11895 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11896 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11897 return NULL;
11898 }
11899 break;
11900 case DAHDI_EVENT_POLARITY:
11901 switch (i->sig) {
11902 case SIG_FXSLS:
11903 case SIG_FXSKS:
11904 case SIG_FXSGS:
11905
11906
11907
11908
11909 callid_created = ast_callid_threadstorage_auto(&callid);
11910 if (i->hanguponpolarityswitch)
11911 i->polarity = POLARITY_REV;
11912 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11913 i->polarity = POLARITY_REV;
11914 ast_verb(2, "Starting post polarity "
11915 "CID detection on channel %d\n",
11916 i->channel);
11917 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
11918 if (!chan) {
11919 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11920 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11921 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11922 ast_hangup(chan);
11923 }
11924 }
11925 ast_callid_threadstorage_auto_clean(callid, callid_created);
11926 break;
11927 default:
11928 ast_log(LOG_WARNING, "handle_init_event detected "
11929 "polarity reversal on non-FXO (SIG_FXS) "
11930 "interface %d\n", i->channel);
11931 }
11932 break;
11933 case DAHDI_EVENT_REMOVED:
11934 ast_log(LOG_NOTICE,
11935 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11936 i->channel);
11937 return i;
11938 case DAHDI_EVENT_NEONMWI_ACTIVE:
11939 if (i->mwimonitor_neon) {
11940 notify_message(i->mailbox, 1);
11941 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11942 }
11943 break;
11944 case DAHDI_EVENT_NEONMWI_INACTIVE:
11945 if (i->mwimonitor_neon) {
11946 notify_message(i->mailbox, 0);
11947 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11948 }
11949 break;
11950 }
11951 return NULL;
11952 }
11953
11954 static void monitor_pfds_clean(void *arg) {
11955 struct pollfd **pfds = arg;
11956 ast_free(*pfds);
11957 }
11958
11959 static void *do_monitor(void *data)
11960 {
11961 int count, res, res2, spoint, pollres=0;
11962 struct dahdi_pvt *i;
11963 struct dahdi_pvt *last = NULL;
11964 struct dahdi_pvt *doomed;
11965 time_t thispass = 0, lastpass = 0;
11966 int found;
11967 char buf[1024];
11968 struct pollfd *pfds=NULL;
11969 int lastalloc = -1;
11970
11971
11972
11973 #if 0
11974 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11975 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11976 return NULL;
11977 }
11978 ast_debug(1, "Monitor starting...\n");
11979 #endif
11980 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11981
11982 pthread_cleanup_push(monitor_pfds_clean, &pfds);
11983 for (;;) {
11984
11985 ast_mutex_lock(&iflock);
11986 if (!pfds || (lastalloc != ifcount)) {
11987 if (pfds) {
11988 ast_free(pfds);
11989 pfds = NULL;
11990 }
11991 if (ifcount) {
11992 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11993 ast_mutex_unlock(&iflock);
11994 return NULL;
11995 }
11996 }
11997 lastalloc = ifcount;
11998 }
11999
12000
12001 count = 0;
12002 for (i = iflist; i; i = i->next) {
12003 ast_mutex_lock(&i->lock);
12004 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
12005 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12006 struct analog_pvt *p = i->sig_pvt;
12007
12008 if (!p) {
12009 ast_log(LOG_ERROR, "No sig_pvt?\n");
12010 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
12011
12012 pfds[count].fd = i->subs[SUB_REAL].dfd;
12013 pfds[count].events = POLLPRI;
12014 pfds[count].revents = 0;
12015
12016 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12017 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12018 pfds[count].events |= POLLIN;
12019 }
12020 count++;
12021 }
12022 } else {
12023 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
12024
12025 pfds[count].fd = i->subs[SUB_REAL].dfd;
12026 pfds[count].events = POLLPRI;
12027 pfds[count].revents = 0;
12028
12029
12030 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
12031 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
12032 pfds[count].events |= POLLIN;
12033 }
12034 count++;
12035 }
12036 }
12037 }
12038 ast_mutex_unlock(&i->lock);
12039 }
12040
12041 ast_mutex_unlock(&iflock);
12042
12043 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12044 pthread_testcancel();
12045
12046 res = poll(pfds, count, 1000);
12047 pthread_testcancel();
12048 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12049
12050
12051 if (res < 0) {
12052 if ((errno != EAGAIN) && (errno != EINTR))
12053 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
12054 continue;
12055 }
12056
12057
12058 ast_mutex_lock(&iflock);
12059 found = 0;
12060 spoint = 0;
12061 lastpass = thispass;
12062 thispass = time(NULL);
12063 doomed = NULL;
12064 for (i = iflist;; i = i->next) {
12065 if (doomed) {
12066 int res;
12067 res = dahdi_destroy_channel_bynum(doomed->channel);
12068 if (res != RESULT_SUCCESS) {
12069 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
12070 }
12071 doomed = NULL;
12072 }
12073 if (!i) {
12074 break;
12075 }
12076
12077 if (thispass != lastpass) {
12078 if (!found && ((i == last) || ((i == iflist) && !last))) {
12079 last = i;
12080 if (last) {
12081 struct analog_pvt *analog_p = last->sig_pvt;
12082
12083 if (analog_p
12084 && !last->mwisendactive
12085 && (last->sig & __DAHDI_SIG_FXO)
12086 && !analog_p->fxsoffhookstate
12087 && !last->owner
12088 && !ast_strlen_zero(last->mailbox)
12089 && (thispass - analog_p->onhooktime > 3)) {
12090 res = has_voicemail(last);
12091 if (analog_p->msgstate != res) {
12092
12093 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
12094 if (res2) {
12095
12096 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
12097 }
12098
12099 if (mwi_send_init(last)) {
12100 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
12101 }
12102 analog_p->msgstate = res;
12103 found ++;
12104 }
12105 }
12106 last = last->next;
12107 }
12108 }
12109 }
12110 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
12111 if (i->radio && !i->owner)
12112 {
12113 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12114 if (res)
12115 {
12116 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
12117
12118 ast_mutex_unlock(&iflock);
12119 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12120 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12121 else
12122 doomed = handle_init_event(i, res);
12123 ast_mutex_lock(&iflock);
12124 }
12125 continue;
12126 }
12127 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
12128 if (pollres & POLLIN) {
12129 if (i->owner || i->subs[SUB_REAL].owner) {
12130 #ifdef HAVE_PRI
12131 if (!i->pri)
12132 #endif
12133 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
12134 continue;
12135 }
12136 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
12137 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
12138 continue;
12139 }
12140 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
12141 if (res > 0) {
12142 if (i->mwimonitor_fsk) {
12143 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
12144 pthread_attr_t attr;
12145 pthread_t threadid;
12146 struct mwi_thread_data *mtd;
12147
12148 pthread_attr_init(&attr);
12149 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
12150
12151 ast_debug(1, "Maybe some MWI on port %d!\n", i->channel);
12152 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
12153 mtd->pvt = i;
12154 memcpy(mtd->buf, buf, res);
12155 mtd->len = res;
12156 i->mwimonitoractive = 1;
12157 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
12158 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
12159 i->mwimonitoractive = 0;
12160 ast_free(mtd);
12161 }
12162 }
12163 }
12164
12165 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
12166 int energy;
12167 struct timeval now;
12168
12169
12170
12171 if (1 == i->dtmfcid_holdoff_state) {
12172 gettimeofday(&i->dtmfcid_delay, NULL);
12173 i->dtmfcid_holdoff_state = 2;
12174 } else if (2 == i->dtmfcid_holdoff_state) {
12175 gettimeofday(&now, NULL);
12176 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
12177 i->dtmfcid_holdoff_state = 0;
12178 }
12179 } else {
12180 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
12181 if (!i->mwisendactive && energy > dtmfcid_level) {
12182 pthread_t threadid;
12183 struct ast_channel *chan;
12184 ast_mutex_unlock(&iflock);
12185 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
12186
12187 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
12188 i->dtmfcid_holdoff_state = 1;
12189 } else {
12190 struct ast_callid *callid = NULL;
12191 int callid_created = ast_callid_threadstorage_auto(&callid);
12192 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL, callid);
12193 if (!chan) {
12194 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
12195 } else {
12196 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
12197 if (res) {
12198 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
12199 ast_hangup(chan);
12200 } else {
12201 i->dtmfcid_holdoff_state = 1;
12202 }
12203 }
12204 ast_callid_threadstorage_auto_clean(callid, callid_created);
12205 }
12206 ast_mutex_lock(&iflock);
12207 }
12208 }
12209 }
12210 if (i->mwisendactive) {
12211 mwi_send_process_buffer(i, res);
12212 }
12213 } else {
12214 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
12215 }
12216 }
12217 if (pollres & POLLPRI) {
12218 if (i->owner || i->subs[SUB_REAL].owner) {
12219 #ifdef HAVE_PRI
12220 if (!i->pri)
12221 #endif
12222 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
12223 continue;
12224 }
12225 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
12226 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
12227
12228 ast_mutex_unlock(&iflock);
12229 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
12230 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
12231 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
12232 else
12233 doomed = handle_init_event(i, res);
12234 }
12235 ast_mutex_lock(&iflock);
12236 }
12237 }
12238 }
12239 ast_mutex_unlock(&iflock);
12240 }
12241
12242 pthread_cleanup_pop(1);
12243 return NULL;
12244
12245 }
12246
12247 static int restart_monitor(void)
12248 {
12249
12250 if (monitor_thread == AST_PTHREADT_STOP)
12251 return 0;
12252 ast_mutex_lock(&monlock);
12253 if (monitor_thread == pthread_self()) {
12254 ast_mutex_unlock(&monlock);
12255 ast_log(LOG_WARNING, "Cannot kill myself\n");
12256 return -1;
12257 }
12258 if (monitor_thread != AST_PTHREADT_NULL) {
12259
12260 pthread_kill(monitor_thread, SIGURG);
12261 } else {
12262
12263 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12264 ast_mutex_unlock(&monlock);
12265 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12266 return -1;
12267 }
12268 }
12269 ast_mutex_unlock(&monlock);
12270 return 0;
12271 }
12272
12273 #if defined(HAVE_PRI)
12274 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12275 {
12276 int x;
12277 int trunkgroup;
12278
12279 trunkgroup = pris[*span].mastertrunkgroup;
12280 if (trunkgroup) {
12281
12282 for (x = 0; x < NUM_SPANS; x++) {
12283 if (pris[x].pri.trunkgroup == trunkgroup) {
12284 *span = x;
12285 return 0;
12286 }
12287 }
12288 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12289 *span = -1;
12290 } else {
12291 if (pris[*span].pri.trunkgroup) {
12292 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);
12293 *span = -1;
12294 } else if (pris[*span].mastertrunkgroup) {
12295 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12296 *span = -1;
12297 } else {
12298 if (si->totalchans == 31) {
12299
12300 pris[*span].dchannels[0] = 16 + offset;
12301 } else if (si->totalchans == 24) {
12302
12303 pris[*span].dchannels[0] = 24 + offset;
12304 } else if (si->totalchans == 3) {
12305
12306 pris[*span].dchannels[0] = 3 + offset;
12307 } else {
12308 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);
12309 *span = -1;
12310 return 0;
12311 }
12312 pris[*span].pri.span = *span + 1;
12313 }
12314 }
12315 return 0;
12316 }
12317 #endif
12318
12319 #if defined(HAVE_PRI)
12320 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12321 {
12322 struct dahdi_spaninfo si;
12323 struct dahdi_params p;
12324 int fd;
12325 int span;
12326 int ospan=0;
12327 int x,y;
12328 for (x = 0; x < NUM_SPANS; x++) {
12329 if (pris[x].pri.trunkgroup == trunkgroup) {
12330 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12331 return -1;
12332 }
12333 }
12334 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12335 if (!channels[y])
12336 break;
12337 memset(&si, 0, sizeof(si));
12338 memset(&p, 0, sizeof(p));
12339 fd = open("/dev/dahdi/channel", O_RDWR);
12340 if (fd < 0) {
12341 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12342 return -1;
12343 }
12344 x = channels[y];
12345 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12346 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12347 close(fd);
12348 return -1;
12349 }
12350 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12351 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12352 close(fd);
12353 return -1;
12354 }
12355 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12356 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12357 close(fd);
12358 return -1;
12359 }
12360 span = p.spanno - 1;
12361 if (pris[span].pri.trunkgroup) {
12362 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12363 close(fd);
12364 return -1;
12365 }
12366 if (pris[span].pri.pvts[0]) {
12367 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12368 close(fd);
12369 return -1;
12370 }
12371 if (!y) {
12372 pris[span].pri.trunkgroup = trunkgroup;
12373 ospan = span;
12374 }
12375 pris[ospan].dchannels[y] = channels[y];
12376 pris[span].pri.span = span + 1;
12377 close(fd);
12378 }
12379 return 0;
12380 }
12381 #endif
12382
12383 #if defined(HAVE_PRI)
12384 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12385 {
12386 if (pris[span].mastertrunkgroup) {
12387 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);
12388 return -1;
12389 }
12390 pris[span].mastertrunkgroup = trunkgroup;
12391 pris[span].prilogicalspan = logicalspan;
12392 return 0;
12393 }
12394 #endif
12395
12396 #if defined(HAVE_SS7)
12397 static unsigned int parse_pointcode(const char *pcstring)
12398 {
12399 unsigned int code1, code2, code3;
12400 int numvals;
12401
12402 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12403 if (numvals == 1)
12404 return code1;
12405 if (numvals == 3)
12406 return (code1 << 16) | (code2 << 8) | code3;
12407
12408 return 0;
12409 }
12410 #endif
12411
12412 #if defined(HAVE_SS7)
12413 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12414 {
12415 if ((linkset < 0) || (linkset >= NUM_SPANS))
12416 return NULL;
12417 else
12418 return &linksets[linkset - 1];
12419 }
12420 #endif
12421
12422 #ifdef HAVE_OPENR2
12423 static void dahdi_r2_destroy_links(void)
12424 {
12425 int i = 0;
12426 if (!r2links) {
12427 return;
12428 }
12429 for (; i < r2links_count; i++) {
12430 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12431 pthread_cancel(r2links[i]->r2master);
12432 pthread_join(r2links[i]->r2master, NULL);
12433 openr2_context_delete(r2links[i]->protocol_context);
12434 }
12435 ast_free(r2links[i]);
12436 }
12437 ast_free(r2links);
12438 r2links = NULL;
12439 r2links_count = 0;
12440 }
12441
12442
12443 #define R2_LINK_CAPACITY 30
12444 static struct dahdi_mfcr2 *dahdi_r2_get_link(const struct dahdi_chan_conf *conf)
12445 {
12446 struct dahdi_mfcr2 *new_r2link = NULL;
12447 struct dahdi_mfcr2 **new_r2links = NULL;
12448
12449
12450
12451
12452
12453 if (!r2links_count ||
12454 memcmp(&conf->mfcr2, &r2links[r2links_count - 1]->conf, sizeof(conf->mfcr2)) ||
12455 (r2links[r2links_count - 1]->numchans == R2_LINK_CAPACITY)) {
12456 new_r2link = ast_calloc(1, sizeof(**r2links));
12457 if (!new_r2link) {
12458 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12459 return NULL;
12460 }
12461 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12462 if (!new_r2links) {
12463 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12464 ast_free(new_r2link);
12465 return NULL;
12466 }
12467 r2links = new_r2links;
12468 new_r2link->r2master = AST_PTHREADT_NULL;
12469 r2links[r2links_count] = new_r2link;
12470 r2links_count++;
12471 ast_debug(1, "Created new R2 link!\n");
12472 }
12473 return r2links[r2links_count - 1];
12474 }
12475
12476 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12477 {
12478 char tmplogdir[] = "/tmp";
12479 char logdir[OR2_MAX_PATH];
12480 int threshold = 0;
12481 int snres = 0;
12482 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12483 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12484 conf->mfcr2.max_dnis);
12485 if (!r2_link->protocol_context) {
12486 return -1;
12487 }
12488 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12489 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12490 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12491 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12492 #endif
12493 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12494 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12495 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12496 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12497 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12498 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
12499 openr2_context_set_dtmf_dialing(r2_link->protocol_context, conf->mfcr2.dtmf_dialing, conf->mfcr2.dtmf_time_on, conf->mfcr2.dtmf_time_off);
12500 openr2_context_set_dtmf_detection(r2_link->protocol_context, conf->mfcr2.dtmf_detection);
12501 #endif
12502 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
12503 openr2_context_set_dtmf_detection_end_timeout(r2_link->protocol_context, conf->mfcr2.dtmf_end_timeout);
12504 #endif
12505 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12506 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12507 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12508 }
12509 } else {
12510 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12511 if (snres >= sizeof(logdir)) {
12512 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12513 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12514 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12515 }
12516 } else {
12517 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12518 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12519 }
12520 }
12521 }
12522 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12523 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12524 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12525 }
12526 }
12527
12528 memcpy(&r2_link->conf, conf, sizeof(r2_link->conf));
12529 return 0;
12530 }
12531 #endif
12532
12533
12534
12535
12536
12537
12538 static int sigtype_to_signalling(int sigtype)
12539 {
12540 return sigtype;
12541 }
12542
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12556 {
12557 struct stat stbuf;
12558 int num;
12559
12560 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12561 if (stat(path, &stbuf) < 0) {
12562 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12563 return -errno;
12564 }
12565 if (!S_ISCHR(stbuf.st_mode)) {
12566 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12567 return -EINVAL;
12568 }
12569 num = minor(stbuf.st_rdev);
12570 ast_debug(1, "%s -> %d\n", path, num);
12571 return num;
12572
12573 }
12574
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585
12586
12587
12588
12589 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12590 {
12591
12592 struct dahdi_pvt *tmp;
12593 char fn[80];
12594 struct dahdi_bufferinfo bi;
12595
12596 int res;
12597 #if defined(HAVE_PRI)
12598 int span = 0;
12599 #endif
12600 int here = 0;
12601 int x;
12602 struct analog_pvt *analog_p = NULL;
12603 struct dahdi_params p;
12604 #if defined(HAVE_PRI)
12605 struct dahdi_spaninfo si;
12606 struct sig_pri_chan *pri_chan = NULL;
12607 #endif
12608 #if defined(HAVE_SS7)
12609 struct sig_ss7_chan *ss7_chan = NULL;
12610 #endif
12611
12612
12613 for (tmp = iflist; tmp; tmp = tmp->next) {
12614 if (!tmp->destroy) {
12615 if (tmp->channel == channel) {
12616
12617 here = 1;
12618 break;
12619 }
12620 if (tmp->channel > channel) {
12621
12622 tmp = NULL;
12623 break;
12624 }
12625 }
12626 }
12627
12628 if (!here && reloading != 1) {
12629 tmp = ast_calloc(1, sizeof(*tmp));
12630 if (!tmp) {
12631 return NULL;
12632 }
12633 tmp->cc_params = ast_cc_config_params_init();
12634 if (!tmp->cc_params) {
12635 ast_free(tmp);
12636 return NULL;
12637 }
12638 ast_mutex_init(&tmp->lock);
12639 ifcount++;
12640 for (x = 0; x < 3; x++)
12641 tmp->subs[x].dfd = -1;
12642 tmp->channel = channel;
12643 tmp->priindication_oob = conf->chan.priindication_oob;
12644 }
12645
12646 if (tmp) {
12647 int chan_sig = conf->chan.sig;
12648
12649
12650 if (reloading && tmp->vars) {
12651 ast_variables_destroy(tmp->vars);
12652 tmp->vars = NULL;
12653 }
12654
12655 if (!here) {
12656
12657 if ((channel != CHAN_PSEUDO)) {
12658 int count = 0;
12659
12660 snprintf(fn, sizeof(fn), "%d", channel);
12661
12662 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12663 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12664 usleep(1);
12665 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12666 count++;
12667 }
12668
12669 if (tmp->subs[SUB_REAL].dfd < 0) {
12670 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);
12671 destroy_dahdi_pvt(tmp);
12672 return NULL;
12673 }
12674 memset(&p, 0, sizeof(p));
12675 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12676 if (res < 0) {
12677 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12678 destroy_dahdi_pvt(tmp);
12679 return NULL;
12680 }
12681 if (conf->is_sig_auto)
12682 chan_sig = sigtype_to_signalling(p.sigtype);
12683 if (p.sigtype != (chan_sig & 0x3ffff)) {
12684 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));
12685 destroy_dahdi_pvt(tmp);
12686 return NULL;
12687 }
12688 tmp->law_default = p.curlaw;
12689 tmp->law = p.curlaw;
12690 tmp->span = p.spanno;
12691 #if defined(HAVE_PRI)
12692 span = p.spanno - 1;
12693 #endif
12694 } else {
12695 chan_sig = 0;
12696 }
12697 tmp->sig = chan_sig;
12698 tmp->outsigmod = conf->chan.outsigmod;
12699
12700 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12701 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), tmp);
12702 if (!analog_p) {
12703 destroy_dahdi_pvt(tmp);
12704 return NULL;
12705 }
12706 tmp->sig_pvt = analog_p;
12707 }
12708 #if defined(HAVE_SS7)
12709 if (chan_sig == SIG_SS7) {
12710 struct dahdi_ss7 *ss7;
12711 int clear = 0;
12712
12713 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12714 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12715 destroy_dahdi_pvt(tmp);
12716 return NULL;
12717 }
12718
12719 ss7 = ss7_resolve_linkset(cur_linkset);
12720 if (!ss7) {
12721 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12722 destroy_dahdi_pvt(tmp);
12723 return NULL;
12724 }
12725 ss7->ss7.span = cur_linkset;
12726 if (cur_cicbeginswith < 0) {
12727 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12728 destroy_dahdi_pvt(tmp);
12729 return NULL;
12730 }
12731 ss7_chan = sig_ss7_chan_new(tmp, &ss7->ss7);
12732 if (!ss7_chan) {
12733 destroy_dahdi_pvt(tmp);
12734 return NULL;
12735 }
12736 tmp->sig_pvt = ss7_chan;
12737 tmp->ss7 = &ss7->ss7;
12738
12739 ss7_chan->channel = tmp->channel;
12740 ss7_chan->cic = cur_cicbeginswith++;
12741
12742
12743 ss7_chan->dpc = cur_defaultdpc;
12744
12745 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12746
12747 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12748 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12749 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12750 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12751
12752 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12753 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12754 }
12755 #endif
12756 #ifdef HAVE_OPENR2
12757 if (chan_sig == SIG_MFCR2) {
12758 struct dahdi_mfcr2 *r2_link;
12759 r2_link = dahdi_r2_get_link(conf);
12760 if (!r2_link) {
12761 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12762 destroy_dahdi_pvt(tmp);
12763 return NULL;
12764 }
12765 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12766 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12767 destroy_dahdi_pvt(tmp);
12768 return NULL;
12769 }
12770 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12771 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12772 destroy_dahdi_pvt(tmp);
12773 return NULL;
12774 }
12775 r2_link->pvts[r2_link->numchans++] = tmp;
12776 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12777 tmp->subs[SUB_REAL].dfd,
12778 NULL, NULL);
12779 if (!tmp->r2chan) {
12780 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12781 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12782 destroy_dahdi_pvt(tmp);
12783 return NULL;
12784 }
12785 tmp->mfcr2 = r2_link;
12786 if (conf->mfcr2.call_files) {
12787 openr2_chan_enable_call_files(tmp->r2chan);
12788 }
12789 openr2_chan_set_client_data(tmp->r2chan, tmp);
12790
12791 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12792 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12793 tmp->mfcr2_category = conf->mfcr2.category;
12794 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12795 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12796 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12797 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12798 tmp->mfcr2call = 0;
12799 tmp->mfcr2_dnis_index = 0;
12800 tmp->mfcr2_ani_index = 0;
12801 }
12802 #endif
12803 #ifdef HAVE_PRI
12804 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12805 int offset;
12806 int matchesdchan;
12807 int x,y;
12808 int myswitchtype = 0;
12809
12810 offset = 0;
12811 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12812 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12813 destroy_dahdi_pvt(tmp);
12814 return NULL;
12815 }
12816 if (span >= NUM_SPANS) {
12817 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12818 destroy_dahdi_pvt(tmp);
12819 return NULL;
12820 } else {
12821 si.spanno = 0;
12822 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12823 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12824 destroy_dahdi_pvt(tmp);
12825 return NULL;
12826 }
12827
12828 tmp->logicalspan = pris[span].prilogicalspan;
12829 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12830 if (span < 0) {
12831 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12832 destroy_dahdi_pvt(tmp);
12833 return NULL;
12834 }
12835 myswitchtype = conf->pri.pri.switchtype;
12836
12837 matchesdchan=0;
12838 for (x = 0; x < NUM_SPANS; x++) {
12839 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12840 if (pris[x].dchannels[y] == tmp->channel) {
12841 matchesdchan = 1;
12842 break;
12843 }
12844 }
12845 }
12846 if (!matchesdchan) {
12847 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12848 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12849 destroy_dahdi_pvt(tmp);
12850 return NULL;
12851 }
12852 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12853 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12854 destroy_dahdi_pvt(tmp);
12855 return NULL;
12856 }
12857 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12858 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));
12859 destroy_dahdi_pvt(tmp);
12860 return NULL;
12861 }
12862 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12863 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12864 destroy_dahdi_pvt(tmp);
12865 return NULL;
12866 }
12867 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12868 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12869 destroy_dahdi_pvt(tmp);
12870 return NULL;
12871 }
12872 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12873 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12874 destroy_dahdi_pvt(tmp);
12875 return NULL;
12876 }
12877 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12878 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12879 destroy_dahdi_pvt(tmp);
12880 return NULL;
12881 }
12882 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12883 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12884 pris[span].pri.trunkgroup);
12885 destroy_dahdi_pvt(tmp);
12886 return NULL;
12887 }
12888
12889 pri_chan = sig_pri_chan_new(tmp, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12890 if (!pri_chan) {
12891 destroy_dahdi_pvt(tmp);
12892 return NULL;
12893 }
12894 tmp->sig_pvt = pri_chan;
12895 tmp->pri = &pris[span].pri;
12896
12897 tmp->priexclusive = conf->chan.priexclusive;
12898
12899 if (!tmp->pri->cc_params) {
12900 tmp->pri->cc_params = ast_cc_config_params_init();
12901 if (!tmp->pri->cc_params) {
12902 destroy_dahdi_pvt(tmp);
12903 return NULL;
12904 }
12905 }
12906 ast_cc_copy_config_params(tmp->pri->cc_params,
12907 conf->chan.cc_params);
12908
12909 pris[span].pri.sig = chan_sig;
12910 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12911 pris[span].pri.switchtype = myswitchtype;
12912 pris[span].pri.nsf = conf->pri.pri.nsf;
12913 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12914 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12915 pris[span].pri.cpndialplan = conf->pri.pri.cpndialplan;
12916 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12917 pris[span].pri.minunused = conf->pri.pri.minunused;
12918 pris[span].pri.minidle = conf->pri.pri.minidle;
12919 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12920 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12921 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12922 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12923 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12924 #endif
12925 #ifdef HAVE_PRI_INBANDDISCONNECT
12926 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12927 #endif
12928 #if defined(HAVE_PRI_CALL_HOLD)
12929 pris[span].pri.hold_disconnect_transfer =
12930 conf->pri.pri.hold_disconnect_transfer;
12931 #endif
12932 #if defined(HAVE_PRI_CCSS)
12933 pris[span].pri.cc_ptmp_recall_mode =
12934 conf->pri.pri.cc_ptmp_recall_mode;
12935 pris[span].pri.cc_qsig_signaling_link_req =
12936 conf->pri.pri.cc_qsig_signaling_link_req;
12937 pris[span].pri.cc_qsig_signaling_link_rsp =
12938 conf->pri.pri.cc_qsig_signaling_link_rsp;
12939 #endif
12940 #if defined(HAVE_PRI_CALL_WAITING)
12941 pris[span].pri.max_call_waiting_calls =
12942 conf->pri.pri.max_call_waiting_calls;
12943 pris[span].pri.allow_call_waiting_calls =
12944 conf->pri.pri.allow_call_waiting_calls;
12945 #endif
12946 pris[span].pri.transfer = conf->chan.transfer;
12947 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12948 #if defined(HAVE_PRI_L2_PERSISTENCE)
12949 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12950 #endif
12951 pris[span].pri.colp_send = conf->pri.pri.colp_send;
12952 #if defined(HAVE_PRI_AOC_EVENTS)
12953 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12954 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12955 #endif
12956 if (chan_sig == SIG_BRI_PTMP) {
12957 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12958 } else {
12959
12960 pris[span].pri.layer1_ignored = 0;
12961 }
12962 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12963 pris[span].pri.inband_on_proceeding = conf->pri.pri.inband_on_proceeding;
12964 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12965 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12966 #if defined(HAVE_PRI_MWI)
12967 ast_copy_string(pris[span].pri.mwi_mailboxes,
12968 conf->pri.pri.mwi_mailboxes,
12969 sizeof(pris[span].pri.mwi_mailboxes));
12970 ast_copy_string(pris[span].pri.mwi_vm_numbers,
12971 conf->pri.pri.mwi_vm_numbers,
12972 sizeof(pris[span].pri.mwi_vm_numbers));
12973 #endif
12974 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12975 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12976 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12977 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12978 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12979 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12980 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12981 pris[span].pri.moh_signaling = conf->pri.pri.moh_signaling;
12982 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12983 #if defined(HAVE_PRI_DISPLAY_TEXT)
12984 pris[span].pri.display_flags_send = conf->pri.pri.display_flags_send;
12985 pris[span].pri.display_flags_receive = conf->pri.pri.display_flags_receive;
12986 #endif
12987 #if defined(HAVE_PRI_MCID)
12988 pris[span].pri.mcid_send = conf->pri.pri.mcid_send;
12989 #endif
12990 #if defined(HAVE_PRI_DATETIME_SEND)
12991 pris[span].pri.datetime_send = conf->pri.pri.datetime_send;
12992 #endif
12993
12994 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12995 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12996 }
12997
12998 #if defined(HAVE_PRI_CALL_WAITING)
12999
13000 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
13001 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
13002 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
13003 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
13004 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
13005 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
13006 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
13007 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
13008 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
13009 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
13010 #endif
13011 } else {
13012 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
13013 destroy_dahdi_pvt(tmp);
13014 return NULL;
13015 }
13016 }
13017 }
13018 #endif
13019 } else {
13020
13021 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));
13022 chan_sig = tmp->sig;
13023 if (tmp->subs[SUB_REAL].dfd > -1) {
13024 memset(&p, 0, sizeof(p));
13025 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13026 }
13027 }
13028
13029 switch (chan_sig) {
13030 case SIG_FXSKS:
13031 case SIG_FXSLS:
13032 case SIG_EM:
13033 case SIG_EM_E1:
13034 case SIG_EMWINK:
13035 case SIG_FEATD:
13036 case SIG_FEATDMF:
13037 case SIG_FEATDMF_TA:
13038 case SIG_FEATB:
13039 case SIG_E911:
13040 case SIG_SF:
13041 case SIG_SFWINK:
13042 case SIG_FGC_CAMA:
13043 case SIG_FGC_CAMAMF:
13044 case SIG_SF_FEATD:
13045 case SIG_SF_FEATDMF:
13046 case SIG_SF_FEATB:
13047 p.starttime = 250;
13048 break;
13049 }
13050
13051 if (tmp->radio) {
13052
13053 p.channo = channel;
13054 p.rxwinktime = 1;
13055 p.rxflashtime = 1;
13056 p.starttime = 1;
13057 p.debouncetime = 5;
13058 } else {
13059 p.channo = channel;
13060
13061 if (conf->timing.prewinktime >= 0)
13062 p.prewinktime = conf->timing.prewinktime;
13063 if (conf->timing.preflashtime >= 0)
13064 p.preflashtime = conf->timing.preflashtime;
13065 if (conf->timing.winktime >= 0)
13066 p.winktime = conf->timing.winktime;
13067 if (conf->timing.flashtime >= 0)
13068 p.flashtime = conf->timing.flashtime;
13069 if (conf->timing.starttime >= 0)
13070 p.starttime = conf->timing.starttime;
13071 if (conf->timing.rxwinktime >= 0)
13072 p.rxwinktime = conf->timing.rxwinktime;
13073 if (conf->timing.rxflashtime >= 0)
13074 p.rxflashtime = conf->timing.rxflashtime;
13075 if (conf->timing.debouncetime >= 0)
13076 p.debouncetime = conf->timing.debouncetime;
13077 }
13078
13079
13080 if (tmp->subs[SUB_REAL].dfd >= 0)
13081 {
13082 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
13083 if (res < 0) {
13084 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
13085 destroy_dahdi_pvt(tmp);
13086 return NULL;
13087 }
13088 }
13089 #if 1
13090 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
13091 memset(&bi, 0, sizeof(bi));
13092 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13093 if (!res) {
13094 bi.txbufpolicy = conf->chan.buf_policy;
13095 bi.rxbufpolicy = conf->chan.buf_policy;
13096 bi.numbufs = conf->chan.buf_no;
13097 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13098 if (res < 0) {
13099 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
13100 }
13101 } else {
13102 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
13103 }
13104 tmp->buf_policy = conf->chan.buf_policy;
13105 tmp->buf_no = conf->chan.buf_no;
13106 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
13107 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
13108 tmp->faxbuf_no = conf->chan.faxbuf_no;
13109
13110
13111
13112
13113 tmp->bufsize = bi.bufsize;
13114 }
13115 #endif
13116 tmp->immediate = conf->chan.immediate;
13117 tmp->transfertobusy = conf->chan.transfertobusy;
13118 if (chan_sig & __DAHDI_SIG_FXS) {
13119 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
13120 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
13121 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
13122 }
13123 tmp->ringt_base = ringt_base;
13124 tmp->firstradio = 0;
13125 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
13126 tmp->permcallwaiting = conf->chan.callwaiting;
13127 else
13128 tmp->permcallwaiting = 0;
13129
13130 tmp->destroy = 0;
13131 tmp->drings = conf->chan.drings;
13132
13133
13134 if (tmp->drings.ringnum[0].range == 0)
13135 tmp->drings.ringnum[0].range = 10;
13136 if (tmp->drings.ringnum[1].range == 0)
13137 tmp->drings.ringnum[1].range = 10;
13138 if (tmp->drings.ringnum[2].range == 0)
13139 tmp->drings.ringnum[2].range = 10;
13140
13141 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
13142 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
13143 tmp->threewaycalling = conf->chan.threewaycalling;
13144 tmp->adsi = conf->chan.adsi;
13145 tmp->use_smdi = conf->chan.use_smdi;
13146 tmp->permhidecallerid = conf->chan.hidecallerid;
13147 tmp->hidecalleridname = conf->chan.hidecalleridname;
13148 tmp->callreturn = conf->chan.callreturn;
13149 tmp->echocancel = conf->chan.echocancel;
13150 tmp->echotraining = conf->chan.echotraining;
13151 tmp->pulse = conf->chan.pulse;
13152 if (tmp->echocancel.head.tap_length) {
13153 tmp->echocanbridged = conf->chan.echocanbridged;
13154 } else {
13155 if (conf->chan.echocanbridged)
13156 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
13157 tmp->echocanbridged = 0;
13158 }
13159 tmp->busydetect = conf->chan.busydetect;
13160 tmp->busycount = conf->chan.busycount;
13161 tmp->busy_cadence = conf->chan.busy_cadence;
13162 tmp->callprogress = conf->chan.callprogress;
13163 tmp->waitfordialtone = conf->chan.waitfordialtone;
13164 tmp->dialtone_detect = conf->chan.dialtone_detect;
13165 tmp->cancallforward = conf->chan.cancallforward;
13166 tmp->dtmfrelax = conf->chan.dtmfrelax;
13167 tmp->callwaiting = tmp->permcallwaiting;
13168 tmp->hidecallerid = tmp->permhidecallerid;
13169 tmp->channel = channel;
13170 tmp->stripmsd = conf->chan.stripmsd;
13171 tmp->use_callerid = conf->chan.use_callerid;
13172 tmp->cid_signalling = conf->chan.cid_signalling;
13173 tmp->cid_start = conf->chan.cid_start;
13174 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
13175 tmp->restrictcid = conf->chan.restrictcid;
13176 tmp->use_callingpres = conf->chan.use_callingpres;
13177 if (tmp->usedistinctiveringdetection) {
13178 if (!tmp->use_callerid) {
13179 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
13180 tmp->use_callerid = 1;
13181 }
13182 }
13183
13184 if (tmp->cid_signalling == CID_SIG_SMDI) {
13185 if (!tmp->use_smdi) {
13186 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
13187 tmp->use_smdi = 1;
13188 }
13189 }
13190 if (tmp->use_smdi) {
13191 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
13192 if (!(tmp->smdi_iface)) {
13193 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
13194 tmp->use_smdi = 0;
13195 }
13196 }
13197
13198 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
13199 tmp->amaflags = conf->chan.amaflags;
13200 if (!here) {
13201 tmp->confno = -1;
13202 tmp->propconfno = -1;
13203 }
13204 tmp->canpark = conf->chan.canpark;
13205 tmp->transfer = conf->chan.transfer;
13206 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
13207 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
13208 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
13209 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
13210 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
13211 ast_copy_string(tmp->description, conf->chan.description, sizeof(tmp->description));
13212 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
13213 tmp->cid_ton = 0;
13214 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
13215 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
13216 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
13217 } else {
13218 tmp->cid_num[0] = '\0';
13219 tmp->cid_name[0] = '\0';
13220 }
13221 #if defined(HAVE_PRI)
13222 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
13223 tmp->cid_tag[0] = '\0';
13224 } else
13225 #endif
13226 {
13227 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
13228 }
13229 tmp->cid_subaddr[0] = '\0';
13230 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
13231 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
13232 char *mailbox, *context;
13233 mailbox = context = ast_strdupa(tmp->mailbox);
13234 strsep(&context, "@");
13235 if (ast_strlen_zero(context))
13236 context = "default";
13237 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
13238 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
13239 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
13240 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
13241 AST_EVENT_IE_END);
13242 }
13243 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13244 tmp->mwisend_setting = conf->chan.mwisend_setting;
13245 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
13246 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
13247 #endif
13248
13249 tmp->group = conf->chan.group;
13250 tmp->callgroup = conf->chan.callgroup;
13251 tmp->pickupgroup= conf->chan.pickupgroup;
13252 ast_unref_namedgroups(tmp->named_callgroups);
13253 tmp->named_callgroups = ast_ref_namedgroups(conf->chan.named_callgroups);
13254 ast_unref_namedgroups(tmp->named_pickupgroups);
13255 tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
13256 if (conf->chan.vars) {
13257 struct ast_variable *v, *tmpvar;
13258 for (v = conf->chan.vars ; v ; v = v->next) {
13259 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
13260 tmpvar->next = tmp->vars;
13261 tmp->vars = tmpvar;
13262 }
13263 }
13264 }
13265 tmp->cid_rxgain = conf->chan.cid_rxgain;
13266 tmp->rxgain = conf->chan.rxgain;
13267 tmp->txgain = conf->chan.txgain;
13268 tmp->txdrc = conf->chan.txdrc;
13269 tmp->rxdrc = conf->chan.rxdrc;
13270 tmp->tonezone = conf->chan.tonezone;
13271 if (tmp->subs[SUB_REAL].dfd > -1) {
13272 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13273 if (tmp->dsp)
13274 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13275 update_conf(tmp);
13276 if (!here) {
13277 switch (chan_sig) {
13278 case SIG_PRI_LIB_HANDLE_CASES:
13279 case SIG_SS7:
13280 case SIG_MFCR2:
13281 break;
13282 default:
13283
13284 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13285 break;
13286 }
13287 }
13288 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13289 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13290
13291 switch (tmp->sig) {
13292 #ifdef HAVE_PRI
13293 case SIG_PRI_LIB_HANDLE_CASES:
13294 sig_pri_set_alarm(tmp->sig_pvt, 1);
13295 break;
13296 #endif
13297 #if defined(HAVE_SS7)
13298 case SIG_SS7:
13299 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13300 break;
13301 #endif
13302 default:
13303
13304 analog_p = tmp->sig_pvt;
13305 if (analog_p) {
13306 analog_p->inalarm = 1;
13307 }
13308 tmp->inalarm = 1;
13309 break;
13310 }
13311 handle_alarms(tmp, res);
13312 }
13313 }
13314
13315 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13316 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13317 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13318 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13319 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13320
13321 if (!here) {
13322 tmp->locallyblocked = 0;
13323 tmp->remotelyblocked = 0;
13324 switch (tmp->sig) {
13325 #if defined(HAVE_PRI)
13326 case SIG_PRI_LIB_HANDLE_CASES:
13327 tmp->inservice = 1;
13328 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13329 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13330 if (chan_sig == SIG_PRI) {
13331 char db_chan_name[20];
13332 char db_answer[5];
13333
13334
13335
13336
13337
13338 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13339 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13340 unsigned *why;
13341
13342 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13343 if (tmp->pri->enable_service_message_support) {
13344 char state;
13345
13346 sscanf(db_answer, "%1c:%30u", &state, why);
13347
13348
13349 *why &= (SRVST_NEAREND | SRVST_FAREND);
13350 }
13351 if (!*why) {
13352 ast_db_del(db_chan_name, SRVST_DBKEY);
13353 }
13354 }
13355 }
13356 #endif
13357 break;
13358 #endif
13359 #if defined(HAVE_SS7)
13360 case SIG_SS7:
13361 tmp->inservice = 0;
13362 break;
13363 #endif
13364 default:
13365
13366 tmp->inservice = 1;
13367 break;
13368 }
13369 }
13370
13371 switch (tmp->sig) {
13372 #if defined(HAVE_PRI)
13373 case SIG_PRI_LIB_HANDLE_CASES:
13374 if (pri_chan) {
13375 pri_chan->channel = tmp->channel;
13376 pri_chan->hidecallerid = tmp->hidecallerid;
13377 pri_chan->hidecalleridname = tmp->hidecalleridname;
13378 pri_chan->immediate = tmp->immediate;
13379 pri_chan->inalarm = tmp->inalarm;
13380 pri_chan->priexclusive = tmp->priexclusive;
13381 pri_chan->priindication_oob = tmp->priindication_oob;
13382 pri_chan->use_callerid = tmp->use_callerid;
13383 pri_chan->use_callingpres = tmp->use_callingpres;
13384 ast_copy_string(pri_chan->context, tmp->context,
13385 sizeof(pri_chan->context));
13386 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13387 sizeof(pri_chan->mohinterpret));
13388 pri_chan->stripmsd = tmp->stripmsd;
13389 }
13390 break;
13391 #endif
13392 #if defined(HAVE_SS7)
13393 case SIG_SS7:
13394 if (ss7_chan) {
13395 ss7_chan->inalarm = tmp->inalarm;
13396
13397 ss7_chan->stripmsd = tmp->stripmsd;
13398 ss7_chan->hidecallerid = tmp->hidecallerid;
13399 ss7_chan->use_callerid = tmp->use_callerid;
13400 ss7_chan->use_callingpres = tmp->use_callingpres;
13401 ss7_chan->immediate = tmp->immediate;
13402 ss7_chan->locallyblocked = tmp->locallyblocked;
13403 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13404 ast_copy_string(ss7_chan->context, tmp->context,
13405 sizeof(ss7_chan->context));
13406 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13407 sizeof(ss7_chan->mohinterpret));
13408 }
13409 break;
13410 #endif
13411 default:
13412
13413 analog_p = tmp->sig_pvt;
13414 if (analog_p) {
13415 analog_p->channel = tmp->channel;
13416 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13417 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13418 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13419 analog_p->permcallwaiting = conf->chan.callwaiting;
13420 analog_p->callreturn = conf->chan.callreturn;
13421 analog_p->cancallforward = conf->chan.cancallforward;
13422 analog_p->canpark = conf->chan.canpark;
13423 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13424 analog_p->immediate = conf->chan.immediate;
13425 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13426 analog_p->pulse = conf->chan.pulse;
13427 analog_p->threewaycalling = conf->chan.threewaycalling;
13428 analog_p->transfer = conf->chan.transfer;
13429 analog_p->transfertobusy = conf->chan.transfertobusy;
13430 analog_p->use_callerid = tmp->use_callerid;
13431 analog_p->use_smdi = tmp->use_smdi;
13432 analog_p->smdi_iface = tmp->smdi_iface;
13433 analog_p->outsigmod = ANALOG_SIG_NONE;
13434 analog_p->echotraining = conf->chan.echotraining;
13435 analog_p->cid_signalling = conf->chan.cid_signalling;
13436 analog_p->stripmsd = conf->chan.stripmsd;
13437 switch (conf->chan.cid_start) {
13438 case CID_START_POLARITY:
13439 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13440 break;
13441 case CID_START_POLARITY_IN:
13442 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13443 break;
13444 case CID_START_DTMF_NOALERT:
13445 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13446 break;
13447 default:
13448 analog_p->cid_start = ANALOG_CID_START_RING;
13449 break;
13450 }
13451 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13452 analog_p->ringt = conf->chan.ringt;
13453 analog_p->ringt_base = ringt_base;
13454 analog_p->onhooktime = time(NULL);
13455 if (chan_sig & __DAHDI_SIG_FXO) {
13456 memset(&p, 0, sizeof(p));
13457 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13458 if (!res) {
13459 analog_p->fxsoffhookstate = p.rxisoffhook;
13460 }
13461 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13462 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13463 #endif
13464 }
13465 analog_p->msgstate = -1;
13466
13467 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13468 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13469 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13470
13471 analog_config_complete(analog_p);
13472 }
13473 break;
13474 }
13475 #if defined(HAVE_PRI)
13476 if (tmp->channel == CHAN_PSEUDO) {
13477
13478
13479
13480
13481 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13482 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13483 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13484 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13485 }
13486 #endif
13487 }
13488 if (tmp && !here) {
13489
13490 dahdi_iflist_insert(tmp);
13491 }
13492 return tmp;
13493 }
13494
13495 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13496 {
13497 #if defined(HAVE_PRI)
13498 if (0 < span) {
13499
13500 if (!p->pri || p->pri->span != span) {
13501 return 0;
13502 }
13503 if (!groupmatch && channelmatch == -1) {
13504
13505 *groupmatched = 1;
13506 return 1;
13507 }
13508 }
13509 #endif
13510
13511 if (groupmatch) {
13512 if ((p->group & groupmatch) != groupmatch)
13513
13514 return 0;
13515 *groupmatched = 1;
13516 }
13517
13518 if (channelmatch != -1) {
13519 if (p->channel != channelmatch)
13520
13521 return 0;
13522 *channelmatched = 1;
13523 }
13524
13525 return 1;
13526 }
13527
13528 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13529 {
13530 struct dahdi_pvt *p = *pvt;
13531
13532 if (p->inalarm)
13533 return 0;
13534
13535 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13536 return analog_available(p->sig_pvt);
13537
13538 switch (p->sig) {
13539 #if defined(HAVE_PRI)
13540 case SIG_PRI_LIB_HANDLE_CASES:
13541 {
13542 struct sig_pri_chan *pvt_chan;
13543 int res;
13544
13545 pvt_chan = p->sig_pvt;
13546 res = sig_pri_available(&pvt_chan, is_specific_channel);
13547 *pvt = pvt_chan->chan_pvt;
13548 return res;
13549 }
13550 #endif
13551 #if defined(HAVE_SS7)
13552 case SIG_SS7:
13553 return sig_ss7_available(p->sig_pvt);
13554 #endif
13555 default:
13556 break;
13557 }
13558
13559 if (p->locallyblocked || p->remotelyblocked) {
13560 return 0;
13561 }
13562
13563
13564 if (!p->owner) {
13565 #ifdef HAVE_OPENR2
13566
13567 if (p->mfcr2) {
13568 if (p->mfcr2call) {
13569 return 0;
13570 } else {
13571 return 1;
13572 }
13573 }
13574 #endif
13575 return 1;
13576 }
13577
13578 return 0;
13579 }
13580
13581 #if defined(HAVE_PRI)
13582 #if defined(HAVE_PRI_CALL_WAITING)
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13596 {
13597 struct dahdi_pvt *pvt = priv;
13598
13599 pvt->stripmsd = pri->ch_cfg.stripmsd;
13600 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13601 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13602 pvt->immediate = pri->ch_cfg.immediate;
13603 pvt->priexclusive = pri->ch_cfg.priexclusive;
13604 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13605 pvt->use_callerid = pri->ch_cfg.use_callerid;
13606 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13607 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13608 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13609 }
13610 #endif
13611 #endif
13612
13613 #if defined(HAVE_PRI)
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624
13625
13626 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13627 {
13628 int pvt_idx;
13629 int res;
13630 unsigned idx;
13631 struct dahdi_pvt *pvt;
13632 struct sig_pri_chan *chan;
13633 struct dahdi_bufferinfo bi;
13634
13635 static int nobch_channel = CHAN_PSEUDO;
13636
13637
13638 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13639 if (!pri->pvts[pvt_idx]) {
13640 break;
13641 }
13642 }
13643 if (pri->numchans == pvt_idx) {
13644 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13645 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13646 return -1;
13647 }
13648
13649
13650 pri->pvts[pvt_idx] = NULL;
13651 ++pri->numchans;
13652 }
13653
13654 pvt = ast_calloc(1, sizeof(*pvt));
13655 if (!pvt) {
13656 return -1;
13657 }
13658 pvt->cc_params = ast_cc_config_params_init();
13659 if (!pvt->cc_params) {
13660 ast_free(pvt);
13661 return -1;
13662 }
13663 ast_mutex_init(&pvt->lock);
13664 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13665 pvt->subs[idx].dfd = -1;
13666 }
13667 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13668 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13669 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13670 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13671
13672 chan = sig_pri_chan_new(pvt, pri, 0, 0, 0);
13673 if (!chan) {
13674 destroy_dahdi_pvt(pvt);
13675 return -1;
13676 }
13677 chan->no_b_channel = 1;
13678
13679
13680
13681
13682
13683
13684 pvt->law_default = DAHDI_LAW_ALAW;
13685
13686 pvt->sig = pri->sig;
13687 pvt->outsigmod = -1;
13688 pvt->pri = pri;
13689 pvt->sig_pvt = chan;
13690 pri->pvts[pvt_idx] = chan;
13691
13692 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13693 if (pvt->subs[SUB_REAL].dfd < 0) {
13694 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13695 strerror(errno));
13696 destroy_dahdi_pvt(pvt);
13697 return -1;
13698 }
13699 memset(&bi, 0, sizeof(bi));
13700 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13701 if (!res) {
13702 pvt->bufsize = bi.bufsize;
13703 bi.txbufpolicy = pvt->buf_policy;
13704 bi.rxbufpolicy = pvt->buf_policy;
13705 bi.numbufs = pvt->buf_no;
13706 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13707 if (res < 0) {
13708 ast_log(LOG_WARNING,
13709 "Unable to set buffer policy on no B channel interface: %s\n",
13710 strerror(errno));
13711 }
13712 } else
13713 ast_log(LOG_WARNING,
13714 "Unable to check buffer policy on no B channel interface: %s\n",
13715 strerror(errno));
13716
13717 --nobch_channel;
13718 if (CHAN_PSEUDO < nobch_channel) {
13719 nobch_channel = CHAN_PSEUDO - 1;
13720 }
13721 pvt->channel = nobch_channel;
13722 pvt->span = pri->span;
13723 chan->channel = pvt->channel;
13724
13725 dahdi_nobch_insert(pri, pvt);
13726
13727 return pvt_idx;
13728 }
13729 #endif
13730
13731
13732
13733
13734
13735
13736 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13737 {
13738 struct dahdi_pvt *p;
13739 struct dahdi_bufferinfo bi;
13740 int res;
13741
13742 p = ast_malloc(sizeof(*p));
13743 if (!p) {
13744 return NULL;
13745 }
13746 *p = *src;
13747
13748
13749 p->cc_params = ast_cc_config_params_init();
13750 if (!p->cc_params) {
13751 ast_free(p);
13752 return NULL;
13753 }
13754 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13755
13756 p->which_iflist = DAHDI_IFLIST_NONE;
13757 p->next = NULL;
13758 p->prev = NULL;
13759 ast_mutex_init(&p->lock);
13760 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13761 if (p->subs[SUB_REAL].dfd < 0) {
13762 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13763 destroy_dahdi_pvt(p);
13764 return NULL;
13765 }
13766 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13767 if (!res) {
13768 bi.txbufpolicy = src->buf_policy;
13769 bi.rxbufpolicy = src->buf_policy;
13770 bi.numbufs = src->buf_no;
13771 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13772 if (res < 0) {
13773 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13774 }
13775 } else
13776 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13777 p->destroy = 1;
13778 dahdi_iflist_insert(p);
13779 return p;
13780 }
13781
13782 struct dahdi_starting_point {
13783
13784 ast_group_t groupmatch;
13785
13786 int channelmatch;
13787
13788 int rr_starting_point;
13789
13790 int span;
13791
13792 int cadance;
13793
13794 char opt;
13795
13796 char backwards;
13797
13798 char roundrobin;
13799 };
13800 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13801 {
13802 char *dest;
13803 char *s;
13804 int x;
13805 int res = 0;
13806 struct dahdi_pvt *p;
13807 char *subdir = NULL;
13808 AST_DECLARE_APP_ARGS(args,
13809 AST_APP_ARG(group);
13810
13811
13812 AST_APP_ARG(other);
13813 );
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838 if (data) {
13839 dest = ast_strdupa(data);
13840 } else {
13841 ast_log(LOG_WARNING, "Channel requested with no data\n");
13842 return NULL;
13843 }
13844 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13845 if (!args.argc || ast_strlen_zero(args.group)) {
13846 ast_log(LOG_WARNING, "No channel/group specified\n");
13847 return NULL;
13848 }
13849
13850
13851 memset(param, 0, sizeof(*param));
13852 param->channelmatch = -1;
13853
13854 if (strchr(args.group, '!') != NULL) {
13855 char *prev = args.group;
13856 while ((s = strchr(prev, '!')) != NULL) {
13857 *s++ = '/';
13858 prev = s;
13859 }
13860 *(prev - 1) = '\0';
13861 subdir = args.group;
13862 args.group = prev;
13863 } else if (args.group[0] == 'i') {
13864
13865 res = sscanf(args.group + 1, "%30d", &x);
13866 if (res < 1) {
13867 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13868 return NULL;
13869 }
13870 param->span = x;
13871
13872
13873 s = strchr(args.group, '-');
13874 if (!s) {
13875
13876 return iflist;
13877 }
13878 args.group = s + 1;
13879 res = 0;
13880 }
13881 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13882
13883 s = args.group + 1;
13884 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13885 if (res < 1) {
13886 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13887 return NULL;
13888 }
13889 param->groupmatch = ((ast_group_t) 1 << x);
13890
13891 if (toupper(args.group[0]) == 'G') {
13892 if (args.group[0] == 'G') {
13893 param->backwards = 1;
13894 p = ifend;
13895 } else
13896 p = iflist;
13897 } else {
13898 if (ARRAY_LEN(round_robin) <= x) {
13899 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13900 x, data);
13901 return NULL;
13902 }
13903 if (args.group[0] == 'R') {
13904 param->backwards = 1;
13905 p = round_robin[x] ? round_robin[x]->prev : ifend;
13906 if (!p)
13907 p = ifend;
13908 } else {
13909 p = round_robin[x] ? round_robin[x]->next : iflist;
13910 if (!p)
13911 p = iflist;
13912 }
13913 param->roundrobin = 1;
13914 param->rr_starting_point = x;
13915 }
13916 } else {
13917 s = args.group;
13918 if (!strcasecmp(s, "pseudo")) {
13919
13920 x = CHAN_PSEUDO;
13921 param->channelmatch = x;
13922 } else {
13923 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13924 if (res < 1) {
13925 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13926 return NULL;
13927 } else {
13928 param->channelmatch = x;
13929 }
13930 }
13931 if (subdir) {
13932 char path[PATH_MAX];
13933 struct stat stbuf;
13934
13935 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13936 subdir, param->channelmatch);
13937 if (stat(path, &stbuf) < 0) {
13938 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13939 path, strerror(errno));
13940 return NULL;
13941 }
13942 if (!S_ISCHR(stbuf.st_mode)) {
13943 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13944 path);
13945 return NULL;
13946 }
13947 param->channelmatch = minor(stbuf.st_rdev);
13948 }
13949
13950 p = iflist;
13951 }
13952
13953 if (param->opt == 'r' && res < 3) {
13954 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13955 param->opt = '\0';
13956 }
13957
13958 return p;
13959 }
13960
13961 static struct ast_channel *dahdi_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
13962 {
13963 int callwait = 0;
13964 struct dahdi_pvt *p;
13965 struct ast_channel *tmp = NULL;
13966 struct dahdi_pvt *exitpvt;
13967 int channelmatched = 0;
13968 int groupmatched = 0;
13969 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13970 int transcapdigital = 0;
13971 #endif
13972 struct dahdi_starting_point start;
13973 struct ast_callid *callid = NULL;
13974 int callid_created = ast_callid_threadstorage_auto(&callid);
13975
13976 ast_mutex_lock(&iflock);
13977 p = determine_starting_point(data, &start);
13978 if (!p) {
13979
13980 ast_mutex_unlock(&iflock);
13981 ast_callid_threadstorage_auto_clean(callid, callid_created);
13982 return NULL;
13983 }
13984
13985
13986 exitpvt = p;
13987 while (p && !tmp) {
13988 if (start.roundrobin)
13989 round_robin[start.rr_starting_point] = p;
13990
13991 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13992 && available(&p, channelmatched)) {
13993 ast_debug(1, "Using channel %d\n", p->channel);
13994
13995 callwait = (p->owner != NULL);
13996 #ifdef HAVE_OPENR2
13997 if (p->mfcr2) {
13998 ast_mutex_lock(&p->lock);
13999 if (p->mfcr2call) {
14000 ast_mutex_unlock(&p->lock);
14001 ast_debug(1, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
14002 goto next;
14003 }
14004 p->mfcr2call = 1;
14005 ast_mutex_unlock(&p->lock);
14006 }
14007 #endif
14008 if (p->channel == CHAN_PSEUDO) {
14009 p = duplicate_pseudo(p);
14010 if (!p) {
14011 break;
14012 }
14013 }
14014
14015 p->distinctivering = 0;
14016
14017 switch (start.opt) {
14018 case '\0':
14019
14020 break;
14021 case 'c':
14022
14023 p->confirmanswer = 1;
14024 break;
14025 case 'r':
14026
14027 p->distinctivering = start.cadance;
14028 break;
14029 case 'd':
14030 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14031
14032 transcapdigital = AST_TRANS_CAP_DIGITAL;
14033 #endif
14034 break;
14035 default:
14036 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, data);
14037 break;
14038 }
14039
14040 p->outgoing = 1;
14041 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
14042 tmp = analog_request(p->sig_pvt, &callwait, requestor);
14043 #ifdef HAVE_PRI
14044 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
14045
14046
14047
14048
14049
14050 ast_mutex_lock(&p->lock);
14051 ast_mutex_unlock(&p->lock);
14052
14053 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
14054 sizeof(p->dnid));
14055 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
14056 #endif
14057 #if defined(HAVE_SS7)
14058 } else if (p->sig == SIG_SS7) {
14059 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
14060 #endif
14061 } else {
14062 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? ast_channel_linkedid(requestor) : "", callid);
14063 }
14064 if (!tmp) {
14065 p->outgoing = 0;
14066 #if defined(HAVE_PRI)
14067 switch (p->sig) {
14068 case SIG_PRI_LIB_HANDLE_CASES:
14069 #if defined(HAVE_PRI_CALL_WAITING)
14070 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
14071 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
14072 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
14073 }
14074 #endif
14075
14076
14077
14078
14079 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
14080 break;
14081 default:
14082 break;
14083 }
14084 #endif
14085 } else {
14086 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", data);
14087 }
14088 break;
14089 }
14090 #ifdef HAVE_OPENR2
14091 next:
14092 #endif
14093 if (start.backwards) {
14094 p = p->prev;
14095 if (!p)
14096 p = ifend;
14097 } else {
14098 p = p->next;
14099 if (!p)
14100 p = iflist;
14101 }
14102
14103 if (p == exitpvt)
14104 break;
14105 }
14106 ast_mutex_unlock(&iflock);
14107 restart_monitor();
14108 if (cause && !tmp) {
14109 if (callwait || channelmatched) {
14110 *cause = AST_CAUSE_BUSY;
14111 } else if (groupmatched) {
14112 *cause = AST_CAUSE_CONGESTION;
14113 } else {
14114
14115
14116
14117
14118 }
14119 }
14120
14121 ast_callid_threadstorage_auto_clean(callid, callid_created);
14122 return tmp;
14123 }
14124
14125
14126
14127
14128
14129
14130
14131
14132
14133
14134
14135 static int dahdi_devicestate(const char *data)
14136 {
14137 #if defined(HAVE_PRI)
14138 const char *device;
14139 unsigned span;
14140 int res;
14141
14142 device = data;
14143
14144 if (*device != 'I') {
14145
14146 return AST_DEVICE_UNKNOWN;
14147 }
14148 res = sscanf(device, "I%30u", &span);
14149 if (res != 1 || !span || NUM_SPANS < span) {
14150
14151 return AST_DEVICE_UNKNOWN;
14152 }
14153 device = strchr(device, '/');
14154 if (!device) {
14155
14156 return AST_DEVICE_UNKNOWN;
14157 }
14158
14159
14160
14161
14162
14163 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14164 ++device;
14165 if (!strcmp(device, "congestion"))
14166 #endif
14167 {
14168 return pris[span - 1].pri.congestion_devstate;
14169 }
14170 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
14171 else if (!strcmp(device, "threshold")) {
14172 return pris[span - 1].pri.threshold_devstate;
14173 }
14174 return AST_DEVICE_UNKNOWN;
14175 #endif
14176 #else
14177 return AST_DEVICE_UNKNOWN;
14178 #endif
14179 }
14180
14181
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193
14194
14195
14196
14197 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
14198 {
14199 struct dahdi_pvt *p;
14200 struct dahdi_pvt *exitpvt;
14201 struct dahdi_starting_point start;
14202 int groupmatched = 0;
14203 int channelmatched = 0;
14204
14205 ast_mutex_lock(&iflock);
14206 p = determine_starting_point(dest, &start);
14207 if (!p) {
14208 ast_mutex_unlock(&iflock);
14209 return -1;
14210 }
14211 exitpvt = p;
14212 for (;;) {
14213 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
14214
14215 struct ast_str *device_name;
14216 char *dash;
14217 const char *monitor_type;
14218 char dialstring[AST_CHANNEL_NAME];
14219 char full_device_name[AST_CHANNEL_NAME];
14220
14221 switch (ast_get_cc_monitor_policy(p->cc_params)) {
14222 case AST_CC_MONITOR_NEVER:
14223 break;
14224 case AST_CC_MONITOR_NATIVE:
14225 case AST_CC_MONITOR_ALWAYS:
14226 case AST_CC_MONITOR_GENERIC:
14227 #if defined(HAVE_PRI)
14228 if (dahdi_sig_pri_lib_handles(p->sig)) {
14229
14230
14231
14232
14233 snprintf(full_device_name, sizeof(full_device_name),
14234 "DAHDI/I%d/congestion", p->pri->span);
14235 } else
14236 #endif
14237 {
14238 #if defined(HAVE_PRI)
14239 device_name = create_channel_name(p, 1, "");
14240 #else
14241 device_name = create_channel_name(p);
14242 #endif
14243 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
14244 device_name ? ast_str_buffer(device_name) : "");
14245 ast_free(device_name);
14246
14247
14248
14249
14250
14251 dash = strrchr(full_device_name, '-');
14252 if (dash) {
14253 *dash = '\0';
14254 }
14255 }
14256 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
14257
14258
14259
14260
14261
14262
14263
14264 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
14265 callback(inbound,
14266 #if defined(HAVE_PRI)
14267 p->pri ? p->pri->cc_params : p->cc_params,
14268 #else
14269 p->cc_params,
14270 #endif
14271 monitor_type, full_device_name, dialstring, NULL);
14272 break;
14273 }
14274 }
14275 p = start.backwards ? p->prev : p->next;
14276 if (!p) {
14277 p = start.backwards ? ifend : iflist;
14278 }
14279 if (p == exitpvt) {
14280 break;
14281 }
14282 }
14283 ast_mutex_unlock(&iflock);
14284 return 0;
14285 }
14286
14287 #if defined(HAVE_SS7)
14288 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14289 {
14290 int i;
14291
14292 if (ss7) {
14293 for (i = 0; i < NUM_SPANS; i++) {
14294 if (linksets[i].ss7.ss7 == ss7) {
14295 ast_verbose_callid(NULL, "[%d] %s", i + 1, s);
14296 return;
14297 }
14298 }
14299 }
14300 ast_verbose_callid(NULL, "%s", s);
14301 }
14302 #endif
14303
14304 #if defined(HAVE_SS7)
14305 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14306 {
14307 int i;
14308
14309 if (ss7) {
14310 for (i = 0; i < NUM_SPANS; i++) {
14311 if (linksets[i].ss7.ss7 == ss7) {
14312 ast_log_callid(LOG_ERROR, NULL, "[%d] %s", i + 1, s);
14313 return;
14314 }
14315 }
14316 }
14317 ast_log_callid(LOG_ERROR, NULL, "%s", s);
14318 }
14319 #endif
14320
14321 #if defined(HAVE_OPENR2)
14322 static void *mfcr2_monitor(void *data)
14323 {
14324 struct dahdi_mfcr2 *mfcr2 = data;
14325
14326
14327
14328
14329
14330 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14331 int res = 0;
14332 int i = 0;
14333 int oldstate = 0;
14334 int quit_loop = 0;
14335 int maxsleep = 20;
14336 int was_idle = 0;
14337 int pollsize = 0;
14338
14339
14340 for (i = 0; i < mfcr2->numchans; i++) {
14341 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14342 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14343 }
14344 while (1) {
14345
14346
14347 pollsize = 0;
14348 for (i = 0; i < mfcr2->numchans; i++) {
14349 pollers[i].revents = 0;
14350 pollers[i].events = 0;
14351 if (mfcr2->pvts[i]->owner) {
14352 continue;
14353 }
14354 if (!mfcr2->pvts[i]->r2chan) {
14355 ast_debug(1, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14356 quit_loop = 1;
14357 break;
14358 }
14359 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14360 pollers[i].events = POLLIN | POLLPRI;
14361 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14362 pollsize++;
14363 }
14364 if (quit_loop) {
14365 break;
14366 }
14367 if (pollsize == 0) {
14368 if (!was_idle) {
14369 ast_debug(1, "Monitor thread going idle since everybody has an owner\n");
14370 was_idle = 1;
14371 }
14372 poll(NULL, 0, maxsleep);
14373 continue;
14374 }
14375 was_idle = 0;
14376
14377
14378 pthread_testcancel();
14379 res = poll(pollers, mfcr2->numchans, maxsleep);
14380 pthread_testcancel();
14381 if ((res < 0) && (errno != EINTR)) {
14382 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14383 break;
14384 }
14385
14386 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14387 for (i = 0; i < mfcr2->numchans; i++) {
14388 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14389 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14390 }
14391 }
14392 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14393 }
14394 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14395 return 0;
14396 }
14397 #endif
14398
14399 #if defined(HAVE_PRI)
14400 static void dahdi_pri_message(struct pri *pri, char *s)
14401 {
14402 int x;
14403 int y;
14404 int dchan = -1;
14405 int span = -1;
14406 int dchancount = 0;
14407
14408 if (pri) {
14409 for (x = 0; x < NUM_SPANS; x++) {
14410 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14411 if (pris[x].pri.dchans[y]) {
14412 dchancount++;
14413 }
14414
14415 if (pris[x].pri.dchans[y] == pri) {
14416 dchan = y;
14417 }
14418 }
14419 if (dchan >= 0) {
14420 span = x;
14421 break;
14422 }
14423 dchancount = 0;
14424 }
14425 if (-1 < span) {
14426 if (1 < dchancount) {
14427 ast_verbose_callid(NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14428 } else {
14429 ast_verbose_callid(NULL, "PRI Span: %d %s", span + 1, s);
14430 }
14431 } else {
14432 ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14433 }
14434 } else {
14435 ast_verbose_callid(NULL, "PRI Span: ? %s", s);
14436 }
14437
14438 ast_mutex_lock(&pridebugfdlock);
14439
14440 if (pridebugfd >= 0) {
14441 if (write(pridebugfd, s, strlen(s)) < 0) {
14442 ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14443 }
14444 }
14445
14446 ast_mutex_unlock(&pridebugfdlock);
14447 }
14448 #endif
14449
14450 #if defined(HAVE_PRI)
14451 static void dahdi_pri_error(struct pri *pri, char *s)
14452 {
14453 int x;
14454 int y;
14455 int dchan = -1;
14456 int span = -1;
14457 int dchancount = 0;
14458
14459 if (pri) {
14460 for (x = 0; x < NUM_SPANS; x++) {
14461 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14462 if (pris[x].pri.dchans[y]) {
14463 dchancount++;
14464 }
14465
14466 if (pris[x].pri.dchans[y] == pri) {
14467 dchan = y;
14468 }
14469 }
14470 if (dchan >= 0) {
14471 span = x;
14472 break;
14473 }
14474 dchancount = 0;
14475 }
14476 if (-1 < span) {
14477 if (1 < dchancount) {
14478 ast_log_callid(LOG_ERROR, NULL, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14479 } else {
14480 ast_log_callid(LOG_ERROR, NULL, "PRI Span: %d %s", span + 1, s);
14481 }
14482 } else {
14483 ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14484 }
14485 } else {
14486 ast_log_callid(LOG_ERROR, NULL, "PRI Span: ? %s", s);
14487 }
14488
14489 ast_mutex_lock(&pridebugfdlock);
14490
14491 if (pridebugfd >= 0) {
14492 if (write(pridebugfd, s, strlen(s)) < 0) {
14493 ast_log_callid(LOG_WARNING, NULL, "write() failed: %s\n", strerror(errno));
14494 }
14495 }
14496
14497 ast_mutex_unlock(&pridebugfdlock);
14498 }
14499 #endif
14500
14501 #if defined(HAVE_PRI)
14502 static int prepare_pri(struct dahdi_pri *pri)
14503 {
14504 int i, res, x;
14505 struct dahdi_params p;
14506 struct dahdi_bufferinfo bi;
14507 struct dahdi_spaninfo si;
14508
14509 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14510 if (!pri->dchannels[i])
14511 break;
14512 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14513 x = pri->dchannels[i];
14514 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14515 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14516 return -1;
14517 }
14518 memset(&p, 0, sizeof(p));
14519 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14520 if (res) {
14521 dahdi_close_pri_fd(pri, i);
14522 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14523 return -1;
14524 }
14525 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14526 dahdi_close_pri_fd(pri, i);
14527 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14528 return -1;
14529 }
14530 memset(&si, 0, sizeof(si));
14531 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14532 if (res) {
14533 dahdi_close_pri_fd(pri, i);
14534 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14535 }
14536 if (!si.alarms) {
14537 pri_event_noalarm(&pri->pri, i, 1);
14538 } else {
14539 pri_event_alarm(&pri->pri, i, 1);
14540 }
14541 memset(&bi, 0, sizeof(bi));
14542 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14543 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14544 bi.numbufs = 32;
14545 bi.bufsize = 1024;
14546 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14547 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14548 dahdi_close_pri_fd(pri, i);
14549 return -1;
14550 }
14551 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14552 }
14553 return 0;
14554 }
14555 #endif
14556
14557 #if defined(HAVE_PRI)
14558 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14559 {
14560 int which, span;
14561 char *ret = NULL;
14562
14563 if (pos != rpos)
14564 return ret;
14565
14566 for (which = span = 0; span < NUM_SPANS; span++) {
14567 if (pris[span].pri.pri && ++which > state) {
14568 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14569 ret = NULL;
14570 }
14571 break;
14572 }
14573 }
14574 return ret;
14575 }
14576 #endif
14577
14578 #if defined(HAVE_PRI)
14579 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14580 {
14581 return complete_span_helper(line,word,pos,state,3);
14582 }
14583 #endif
14584
14585 #if defined(HAVE_PRI)
14586 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14587 {
14588 int myfd;
14589 switch (cmd) {
14590 case CLI_INIT:
14591 e->command = "pri set debug file";
14592 e->usage = "Usage: pri set debug file [output-file]\n"
14593 " Sends PRI debug output to the specified output file\n";
14594 return NULL;
14595 case CLI_GENERATE:
14596 return NULL;
14597 }
14598 if (a->argc < 5)
14599 return CLI_SHOWUSAGE;
14600
14601 if (ast_strlen_zero(a->argv[4]))
14602 return CLI_SHOWUSAGE;
14603
14604 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14605 if (myfd < 0) {
14606 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14607 return CLI_SUCCESS;
14608 }
14609
14610 ast_mutex_lock(&pridebugfdlock);
14611
14612 if (pridebugfd >= 0)
14613 close(pridebugfd);
14614
14615 pridebugfd = myfd;
14616 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14617 ast_mutex_unlock(&pridebugfdlock);
14618 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14619 return CLI_SUCCESS;
14620 }
14621 #endif
14622
14623 #if defined(HAVE_PRI)
14624 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14625 {
14626 int span;
14627 int x;
14628 int debugmask = 0;
14629 int level = 0;
14630 switch (cmd) {
14631 case CLI_INIT:
14632 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";
14633 e->usage =
14634 "Usage: pri set debug {<level>|on|off|hex|intense} span <span>\n"
14635 " Enables debugging on a given PRI span\n"
14636 " Level is a bitmap of the following values:\n"
14637 " 1 General debugging incl. state changes\n"
14638 " 2 Decoded Q.931 messages\n"
14639 " 4 Decoded Q.921 messages\n"
14640 " 8 Raw hex dumps of Q.921 frames\n"
14641 " on - equivalent to 3\n"
14642 " hex - equivalent to 8\n"
14643 " intense - equivalent to 15\n";
14644 return NULL;
14645 case CLI_GENERATE:
14646 return complete_span_4(a->line, a->word, a->pos, a->n);
14647 }
14648 if (a->argc < 6) {
14649 return CLI_SHOWUSAGE;
14650 }
14651
14652 if (!strcasecmp(a->argv[3], "on")) {
14653 level = 3;
14654 } else if (!strcasecmp(a->argv[3], "off")) {
14655 level = 0;
14656 } else if (!strcasecmp(a->argv[3], "intense")) {
14657 level = 15;
14658 } else if (!strcasecmp(a->argv[3], "hex")) {
14659 level = 8;
14660 } else {
14661 level = atoi(a->argv[3]);
14662 }
14663 span = atoi(a->argv[5]);
14664 if ((span < 1) || (span > NUM_SPANS)) {
14665 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14666 return CLI_SUCCESS;
14667 }
14668 if (!pris[span-1].pri.pri) {
14669 ast_cli(a->fd, "No PRI running on span %d\n", span);
14670 return CLI_SUCCESS;
14671 }
14672
14673 if (level & 1) debugmask |= SIG_PRI_DEBUG_NORMAL;
14674 if (level & 2) debugmask |= PRI_DEBUG_Q931_DUMP;
14675 if (level & 4) debugmask |= PRI_DEBUG_Q921_DUMP;
14676 if (level & 8) debugmask |= PRI_DEBUG_Q921_RAW;
14677
14678
14679 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14680 if (pris[span - 1].pri.dchans[x]) {
14681 pri_set_debug(pris[span - 1].pri.dchans[x], debugmask);
14682 }
14683 }
14684 if (level == 0) {
14685
14686 ast_mutex_lock(&pridebugfdlock);
14687 if (0 <= pridebugfd) {
14688 close(pridebugfd);
14689 pridebugfd = -1;
14690 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14691 pridebugfilename);
14692 }
14693 ast_mutex_unlock(&pridebugfdlock);
14694 }
14695 pris[span - 1].pri.debug = (level) ? 1 : 0;
14696 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14697 return CLI_SUCCESS;
14698 }
14699 #endif
14700
14701 #if defined(HAVE_PRI)
14702 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14703 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14704 {
14705 unsigned *why;
14706 int channel;
14707 int trunkgroup;
14708 int x, y, fd = a->fd;
14709 int interfaceid = 0;
14710 char db_chan_name[20], db_answer[5];
14711 struct dahdi_pvt *tmp;
14712 struct dahdi_pri *pri;
14713
14714 if (a->argc < 5 || a->argc > 6)
14715 return CLI_SHOWUSAGE;
14716 if (strchr(a->argv[4], ':')) {
14717 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14718 return CLI_SHOWUSAGE;
14719 if ((trunkgroup < 1) || (channel < 1))
14720 return CLI_SHOWUSAGE;
14721 pri = NULL;
14722 for (x=0;x<NUM_SPANS;x++) {
14723 if (pris[x].pri.trunkgroup == trunkgroup) {
14724 pri = pris + x;
14725 break;
14726 }
14727 }
14728 if (!pri) {
14729 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14730 return CLI_FAILURE;
14731 }
14732 } else
14733 channel = atoi(a->argv[4]);
14734
14735 if (a->argc == 6)
14736 interfaceid = atoi(a->argv[5]);
14737
14738
14739 for (x = 0; x < NUM_SPANS; x++) {
14740 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14741 if (pris[x].dchannels[y] == channel) {
14742 pri = pris + x;
14743 if (pri->pri.enable_service_message_support) {
14744 ast_mutex_lock(&pri->pri.lock);
14745 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14746 ast_mutex_unlock(&pri->pri.lock);
14747 } else {
14748 ast_cli(fd,
14749 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14750 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14751 }
14752 return CLI_SUCCESS;
14753 }
14754 }
14755 }
14756
14757
14758 ast_mutex_lock(&iflock);
14759 for (tmp = iflist; tmp; tmp = tmp->next) {
14760 if (tmp->pri && tmp->channel == channel) {
14761 ast_mutex_unlock(&iflock);
14762 ast_mutex_lock(&tmp->pri->lock);
14763 if (!tmp->pri->enable_service_message_support) {
14764 ast_mutex_unlock(&tmp->pri->lock);
14765 ast_cli(fd,
14766 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14767 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14768 return CLI_SUCCESS;
14769 }
14770 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14771 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14772 switch(changestatus) {
14773 case 0:
14774
14775 ast_db_del(db_chan_name, SRVST_DBKEY);
14776 *why &= ~SRVST_NEAREND;
14777 if (*why) {
14778 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14779 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14780 } else {
14781 dahdi_pri_update_span_devstate(tmp->pri);
14782 }
14783 break;
14784
14785 case 2:
14786
14787 ast_db_del(db_chan_name, SRVST_DBKEY);
14788 *why |= SRVST_NEAREND;
14789 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14790 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14791 dahdi_pri_update_span_devstate(tmp->pri);
14792 break;
14793
14794
14795 default:
14796 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14797 break;
14798 }
14799 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14800 ast_mutex_unlock(&tmp->pri->lock);
14801 return CLI_SUCCESS;
14802 }
14803 }
14804 ast_mutex_unlock(&iflock);
14805
14806 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14807 return CLI_FAILURE;
14808 }
14809
14810 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14811 {
14812 switch (cmd) {
14813 case CLI_INIT:
14814 e->command = "pri service enable channel";
14815 e->usage =
14816 "Usage: pri service enable channel <channel> [<interface id>]\n"
14817 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14818 " to restore a channel to service, with optional interface id\n"
14819 " as agreed upon with remote switch operator\n";
14820 return NULL;
14821 case CLI_GENERATE:
14822 return NULL;
14823 }
14824 return handle_pri_service_generic(e, cmd, a, 0);
14825 }
14826
14827 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14828 {
14829 switch (cmd) {
14830 case CLI_INIT:
14831 e->command = "pri service disable channel";
14832 e->usage =
14833 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14834 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14835 " to remove a channel from service, with optional interface id\n"
14836 " as agreed upon with remote switch operator\n";
14837 return NULL;
14838 case CLI_GENERATE:
14839 return NULL;
14840 }
14841 return handle_pri_service_generic(e, cmd, a, 2);
14842 }
14843 #endif
14844 #endif
14845
14846 #if defined(HAVE_PRI)
14847 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14848 {
14849 int span;
14850
14851 switch (cmd) {
14852 case CLI_INIT:
14853 e->command = "pri show channels";
14854 e->usage =
14855 "Usage: pri show channels\n"
14856 " Displays PRI channel information such as the current mapping\n"
14857 " of DAHDI B channels to Asterisk channel names and which calls\n"
14858 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14859 " are not associated with any B channel.\n";
14860 return NULL;
14861 case CLI_GENERATE:
14862 return NULL;
14863 }
14864
14865 if (a->argc != 3)
14866 return CLI_SHOWUSAGE;
14867
14868 sig_pri_cli_show_channels_header(a->fd);
14869 for (span = 0; span < NUM_SPANS; ++span) {
14870 if (pris[span].pri.pri) {
14871 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14872 }
14873 }
14874 return CLI_SUCCESS;
14875 }
14876 #endif
14877
14878 #if defined(HAVE_PRI)
14879 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14880 {
14881 int span;
14882
14883 switch (cmd) {
14884 case CLI_INIT:
14885 e->command = "pri show spans";
14886 e->usage =
14887 "Usage: pri show spans\n"
14888 " Displays PRI span information\n";
14889 return NULL;
14890 case CLI_GENERATE:
14891 return NULL;
14892 }
14893
14894 if (a->argc != 3)
14895 return CLI_SHOWUSAGE;
14896
14897 for (span = 0; span < NUM_SPANS; span++) {
14898 if (pris[span].pri.pri) {
14899 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14900 }
14901 }
14902 return CLI_SUCCESS;
14903 }
14904 #endif
14905
14906 #if defined(HAVE_PRI)
14907 #define container_of(ptr, type, member) \
14908 ((type *)((char *)(ptr) - offsetof(type, member)))
14909
14910
14911
14912
14913
14914
14915
14916
14917
14918
14919
14920
14921
14922 static int pri_destroy_dchan(struct sig_pri_span *pri)
14923 {
14924 int i;
14925 struct dahdi_pri* dahdi_pri;
14926
14927 if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
14928 return 0;
14929 }
14930 pthread_cancel(pri->master);
14931 pthread_join(pri->master, NULL);
14932
14933
14934 dahdi_pri = container_of(pri, struct dahdi_pri, pri);
14935 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14936 ast_debug(4, "closing pri_fd %d\n", i);
14937 dahdi_close_pri_fd(dahdi_pri, i);
14938 }
14939 pri->pri = NULL;
14940 ast_debug(1, "PRI span %d destroyed\n", pri->span);
14941 return 1;
14942 }
14943
14944 static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
14945 struct ast_cli_args *a)
14946 {
14947 int span;
14948 int i;
14949 int res;
14950
14951 switch (cmd) {
14952 case CLI_INIT:
14953 e->command = "pri destroy span";
14954 e->usage =
14955 "Usage: pri destroy span <span>\n"
14956 " Destorys D-channel of span and its B-channels.\n"
14957 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
14958 return NULL;
14959 case CLI_GENERATE:
14960 return complete_span_4(a->line, a->word, a->pos, a->n);
14961 }
14962
14963 if (a->argc < 4) {
14964 return CLI_SHOWUSAGE;
14965 }
14966 res = sscanf(a->argv[3], "%30d", &span);
14967 if ((res != 1) || span < 1 || span > NUM_SPANS) {
14968 ast_cli(a->fd,
14969 "Invalid span '%s'. Should be a number from %d to %d\n",
14970 a->argv[3], 1, NUM_SPANS);
14971 return CLI_SUCCESS;
14972 }
14973 if (!pris[span - 1].pri.pri) {
14974 ast_cli(a->fd, "No PRI running on span %d\n", span);
14975 return CLI_SUCCESS;
14976 }
14977
14978 for (i = 0; i < pris[span - 1].pri.numchans; i++) {
14979 int channel;
14980 struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
14981
14982 if (!pvt) {
14983 continue;
14984 }
14985 channel = pvt->channel;
14986 ast_debug(2, "About to destroy B-channel %d.\n", channel);
14987 dahdi_destroy_channel_bynum(channel);
14988 }
14989 ast_debug(2, "About to destroy D-channel of span %d.\n", span);
14990 pri_destroy_dchan(&pris[span - 1].pri);
14991
14992 return CLI_SUCCESS;
14993 }
14994
14995 #endif
14996
14997 #if defined(HAVE_PRI)
14998 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14999 {
15000 int span;
15001
15002 switch (cmd) {
15003 case CLI_INIT:
15004 e->command = "pri show span";
15005 e->usage =
15006 "Usage: pri show span <span>\n"
15007 " Displays PRI Information on a given PRI span\n";
15008 return NULL;
15009 case CLI_GENERATE:
15010 return complete_span_4(a->line, a->word, a->pos, a->n);
15011 }
15012
15013 if (a->argc < 4)
15014 return CLI_SHOWUSAGE;
15015 span = atoi(a->argv[3]);
15016 if ((span < 1) || (span > NUM_SPANS)) {
15017 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
15018 return CLI_SUCCESS;
15019 }
15020 if (!pris[span-1].pri.pri) {
15021 ast_cli(a->fd, "No PRI running on span %d\n", span);
15022 return CLI_SUCCESS;
15023 }
15024
15025 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
15026
15027 return CLI_SUCCESS;
15028 }
15029 #endif
15030
15031 #if defined(HAVE_PRI)
15032 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15033 {
15034 int x;
15035 int span;
15036 int count=0;
15037 int debug;
15038
15039 switch (cmd) {
15040 case CLI_INIT:
15041 e->command = "pri show debug";
15042 e->usage =
15043 "Usage: pri show debug\n"
15044 " Show the debug state of pri spans\n";
15045 return NULL;
15046 case CLI_GENERATE:
15047 return NULL;
15048 }
15049
15050 for (span = 0; span < NUM_SPANS; span++) {
15051 if (pris[span].pri.pri) {
15052 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
15053 if (pris[span].pri.dchans[x]) {
15054 debug = pri_get_debug(pris[span].pri.dchans[x]);
15055 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" );
15056 count++;
15057 }
15058 }
15059 }
15060
15061 }
15062 ast_mutex_lock(&pridebugfdlock);
15063 if (pridebugfd >= 0)
15064 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
15065 ast_mutex_unlock(&pridebugfdlock);
15066
15067 if (!count)
15068 ast_cli(a->fd, "No PRI running\n");
15069 return CLI_SUCCESS;
15070 }
15071 #endif
15072
15073 #if defined(HAVE_PRI)
15074 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15075 {
15076 switch (cmd) {
15077 case CLI_INIT:
15078 e->command = "pri show version";
15079 e->usage =
15080 "Usage: pri show version\n"
15081 "Show libpri version information\n";
15082 return NULL;
15083 case CLI_GENERATE:
15084 return NULL;
15085 }
15086
15087 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
15088
15089 return CLI_SUCCESS;
15090 }
15091 #endif
15092
15093 #if defined(HAVE_PRI)
15094 static struct ast_cli_entry dahdi_pri_cli[] = {
15095 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
15096 #if defined(HAVE_PRI_SERVICE_MESSAGES)
15097 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
15098 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
15099 #endif
15100 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
15101 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
15102 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
15103 AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
15104 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
15105 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
15106 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
15107 };
15108 #endif
15109
15110 #ifdef HAVE_OPENR2
15111
15112 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15113 {
15114 switch (cmd) {
15115 case CLI_INIT:
15116 e->command = "mfcr2 show version";
15117 e->usage =
15118 "Usage: mfcr2 show version\n"
15119 " Shows the version of the OpenR2 library being used.\n";
15120 return NULL;
15121 case CLI_GENERATE:
15122 return NULL;
15123 }
15124 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
15125 return CLI_SUCCESS;
15126 }
15127
15128 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15129 {
15130 #define FORMAT "%4s %40s\n"
15131 int i = 0;
15132 int numvariants = 0;
15133 const openr2_variant_entry_t *variants;
15134 switch (cmd) {
15135 case CLI_INIT:
15136 e->command = "mfcr2 show variants";
15137 e->usage =
15138 "Usage: mfcr2 show variants\n"
15139 " Shows the list of MFC/R2 variants supported.\n";
15140 return NULL;
15141 case CLI_GENERATE:
15142 return NULL;
15143 }
15144 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
15145 ast_cli(a->fd, "Failed to get list of variants.\n");
15146 return CLI_FAILURE;
15147 }
15148 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
15149 for (i = 0; i < numvariants; i++) {
15150 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
15151 }
15152 return CLI_SUCCESS;
15153 #undef FORMAT
15154 }
15155
15156 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15157 {
15158 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
15159 int filtertype = 0;
15160 int targetnum = 0;
15161 char channo[5];
15162 char anino[5];
15163 char dnisno[5];
15164 struct dahdi_pvt *p;
15165 openr2_context_t *r2context;
15166 openr2_variant_t r2variant;
15167 switch (cmd) {
15168 case CLI_INIT:
15169 e->command = "mfcr2 show channels [group|context]";
15170 e->usage =
15171 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
15172 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
15173 return NULL;
15174 case CLI_GENERATE:
15175 return NULL;
15176 }
15177 if (!((a->argc == 3) || (a->argc == 5))) {
15178 return CLI_SHOWUSAGE;
15179 }
15180 if (a->argc == 5) {
15181 if (!strcasecmp(a->argv[3], "group")) {
15182 targetnum = atoi(a->argv[4]);
15183 if ((targetnum < 0) || (targetnum > 63))
15184 return CLI_SHOWUSAGE;
15185 targetnum = 1 << targetnum;
15186 filtertype = 1;
15187 } else if (!strcasecmp(a->argv[3], "context")) {
15188 filtertype = 2;
15189 } else {
15190 return CLI_SHOWUSAGE;
15191 }
15192 }
15193 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
15194 ast_mutex_lock(&iflock);
15195 for (p = iflist; p; p = p->next) {
15196 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15197 continue;
15198 }
15199 if (filtertype) {
15200 switch(filtertype) {
15201 case 1:
15202 if (p->group != targetnum) {
15203 continue;
15204 }
15205 break;
15206 case 2:
15207 if (strcasecmp(p->context, a->argv[4])) {
15208 continue;
15209 }
15210 break;
15211 default:
15212 ;
15213 }
15214 }
15215 r2context = openr2_chan_get_context(p->r2chan);
15216 r2variant = openr2_context_get_variant(r2context);
15217 snprintf(channo, sizeof(channo), "%d", p->channel);
15218 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
15219 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
15220 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
15221 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
15222 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
15223 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
15224 }
15225 ast_mutex_unlock(&iflock);
15226 return CLI_SUCCESS;
15227 #undef FORMAT
15228 }
15229
15230 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15231 {
15232 struct dahdi_pvt *p = NULL;
15233 int channo = 0;
15234 char *toklevel = NULL;
15235 char *saveptr = NULL;
15236 char *logval = NULL;
15237 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
15238 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
15239 switch (cmd) {
15240 case CLI_INIT:
15241 e->command = "mfcr2 set debug";
15242 e->usage =
15243 "Usage: mfcr2 set debug <loglevel> <channel>\n"
15244 " Set a new logging level for the specified channel.\n"
15245 " If no channel is specified the logging level will be applied to all channels.\n";
15246 return NULL;
15247 case CLI_GENERATE:
15248 return NULL;
15249 }
15250 if (a->argc < 4) {
15251 return CLI_SHOWUSAGE;
15252 }
15253 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15254 logval = ast_strdupa(a->argv[3]);
15255 toklevel = strtok_r(logval, ",", &saveptr);
15256 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15257 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
15258 return CLI_FAILURE;
15259 } else if (OR2_LOG_NOTHING == tmplevel) {
15260 loglevel = tmplevel;
15261 } else {
15262 loglevel |= tmplevel;
15263 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
15264 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
15265 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
15266 continue;
15267 }
15268 loglevel |= tmplevel;
15269 }
15270 }
15271 ast_mutex_lock(&iflock);
15272 for (p = iflist; p; p = p->next) {
15273 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15274 continue;
15275 }
15276 if ((channo != -1) && (p->channel != channo )) {
15277 continue;
15278 }
15279 openr2_chan_set_log_level(p->r2chan, loglevel);
15280 if (channo != -1) {
15281 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
15282 break;
15283 }
15284 }
15285 if ((channo != -1) && !p) {
15286 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15287 }
15288 if (channo == -1) {
15289 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
15290 }
15291 ast_mutex_unlock(&iflock);
15292 return CLI_SUCCESS;
15293 }
15294
15295 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15296 {
15297 struct dahdi_pvt *p = NULL;
15298 int channo = 0;
15299 switch (cmd) {
15300 case CLI_INIT:
15301 e->command = "mfcr2 call files [on|off]";
15302 e->usage =
15303 "Usage: mfcr2 call files [on|off] <channel>\n"
15304 " Enable call files creation on the specified channel.\n"
15305 " If no channel is specified call files creation policy will be applied to all channels.\n";
15306 return NULL;
15307 case CLI_GENERATE:
15308 return NULL;
15309 }
15310 if (a->argc < 4) {
15311 return CLI_SHOWUSAGE;
15312 }
15313 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
15314 ast_mutex_lock(&iflock);
15315 for (p = iflist; p; p = p->next) {
15316 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15317 continue;
15318 }
15319 if ((channo != -1) && (p->channel != channo )) {
15320 continue;
15321 }
15322 if (ast_true(a->argv[3])) {
15323 openr2_chan_enable_call_files(p->r2chan);
15324 } else {
15325 openr2_chan_disable_call_files(p->r2chan);
15326 }
15327 if (channo != -1) {
15328 if (ast_true(a->argv[3])) {
15329 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
15330 } else {
15331 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
15332 }
15333 break;
15334 }
15335 }
15336 if ((channo != -1) && !p) {
15337 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15338 }
15339 if (channo == -1) {
15340 if (ast_true(a->argv[3])) {
15341 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
15342 } else {
15343 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
15344 }
15345 }
15346 ast_mutex_unlock(&iflock);
15347 return CLI_SUCCESS;
15348 }
15349
15350 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15351 {
15352 struct dahdi_pvt *p = NULL;
15353 int channo = 0;
15354 switch (cmd) {
15355 case CLI_INIT:
15356 e->command = "mfcr2 set idle";
15357 e->usage =
15358 "Usage: mfcr2 set idle <channel>\n"
15359 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15360 " Force the given channel into IDLE state.\n"
15361 " If no channel is specified, all channels will be set to IDLE.\n";
15362 return NULL;
15363 case CLI_GENERATE:
15364 return NULL;
15365 }
15366 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15367 ast_mutex_lock(&iflock);
15368 for (p = iflist; p; p = p->next) {
15369 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15370 continue;
15371 }
15372 if ((channo != -1) && (p->channel != channo )) {
15373 continue;
15374 }
15375 openr2_chan_set_idle(p->r2chan);
15376 ast_mutex_lock(&p->lock);
15377 p->locallyblocked = 0;
15378 p->mfcr2call = 0;
15379 ast_mutex_unlock(&p->lock);
15380 if (channo != -1) {
15381 break;
15382 }
15383 }
15384 if ((channo != -1) && !p) {
15385 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15386 }
15387 ast_mutex_unlock(&iflock);
15388 return CLI_SUCCESS;
15389 }
15390
15391 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15392 {
15393 struct dahdi_pvt *p = NULL;
15394 int channo = 0;
15395 switch (cmd) {
15396 case CLI_INIT:
15397 e->command = "mfcr2 set blocked";
15398 e->usage =
15399 "Usage: mfcr2 set blocked <channel>\n"
15400 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15401 " Force the given channel into BLOCKED state.\n"
15402 " If no channel is specified, all channels will be set to BLOCKED.\n";
15403 return NULL;
15404 case CLI_GENERATE:
15405 return NULL;
15406 }
15407 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15408 ast_mutex_lock(&iflock);
15409 for (p = iflist; p; p = p->next) {
15410 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15411 continue;
15412 }
15413 if ((channo != -1) && (p->channel != channo )) {
15414 continue;
15415 }
15416 openr2_chan_set_blocked(p->r2chan);
15417 ast_mutex_lock(&p->lock);
15418 p->locallyblocked = 1;
15419 ast_mutex_unlock(&p->lock);
15420 if (channo != -1) {
15421 break;
15422 }
15423 }
15424 if ((channo != -1) && !p) {
15425 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15426 }
15427 ast_mutex_unlock(&iflock);
15428 return CLI_SUCCESS;
15429 }
15430
15431 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15432 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15433 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15434 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15435 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15436 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15437 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15438 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15439 };
15440
15441 #endif
15442
15443 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15444 {
15445 int channel;
15446 int ret;
15447 switch (cmd) {
15448 case CLI_INIT:
15449 e->command = "dahdi destroy channel";
15450 e->usage =
15451 "Usage: dahdi destroy channel <chan num>\n"
15452 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15453 return NULL;
15454 case CLI_GENERATE:
15455 return NULL;
15456 }
15457 if (a->argc != 4)
15458 return CLI_SHOWUSAGE;
15459
15460 channel = atoi(a->argv[3]);
15461 ret = dahdi_destroy_channel_bynum(channel);
15462 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15463 }
15464
15465 static void dahdi_softhangup_all(void)
15466 {
15467 struct dahdi_pvt *p;
15468 retry:
15469 ast_mutex_lock(&iflock);
15470 for (p = iflist; p; p = p->next) {
15471 ast_mutex_lock(&p->lock);
15472 if (p->owner && !p->restartpending) {
15473 if (ast_channel_trylock(p->owner)) {
15474 if (option_debug > 2)
15475 ast_verbose("Avoiding deadlock\n");
15476
15477 ast_mutex_unlock(&p->lock);
15478 ast_mutex_unlock(&iflock);
15479 goto retry;
15480 }
15481 if (option_debug > 2)
15482 ast_verbose("Softhanging up on %s\n", ast_channel_name(p->owner));
15483 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15484 p->restartpending = 1;
15485 num_restart_pending++;
15486 ast_channel_unlock(p->owner);
15487 }
15488 ast_mutex_unlock(&p->lock);
15489 }
15490 ast_mutex_unlock(&iflock);
15491 }
15492
15493 static int setup_dahdi(int reload);
15494 static int dahdi_restart(void)
15495 {
15496 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15497 int i, j;
15498 #endif
15499 int cancel_code;
15500 struct dahdi_pvt *p;
15501
15502 ast_mutex_lock(&restart_lock);
15503 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15504 dahdi_softhangup_all();
15505 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15506 #ifdef HAVE_OPENR2
15507 dahdi_r2_destroy_links();
15508 #endif
15509
15510 #if defined(HAVE_PRI)
15511 for (i = 0; i < NUM_SPANS; i++) {
15512 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15513 cancel_code = pthread_cancel(pris[i].pri.master);
15514 pthread_kill(pris[i].pri.master, SIGURG);
15515 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);
15516 pthread_join(pris[i].pri.master, NULL);
15517 ast_debug(4, "Joined thread of span %d\n", i);
15518 }
15519 }
15520 #endif
15521
15522 #if defined(HAVE_SS7)
15523 for (i = 0; i < NUM_SPANS; i++) {
15524 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15525 cancel_code = pthread_cancel(linksets[i].ss7.master);
15526 pthread_kill(linksets[i].ss7.master, SIGURG);
15527 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);
15528 pthread_join(linksets[i].ss7.master, NULL);
15529 ast_debug(4, "Joined thread of span %d\n", i);
15530 }
15531 }
15532 #endif
15533
15534 ast_mutex_lock(&monlock);
15535 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15536 cancel_code = pthread_cancel(monitor_thread);
15537 pthread_kill(monitor_thread, SIGURG);
15538 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15539 pthread_join(monitor_thread, NULL);
15540 ast_debug(4, "Joined monitor thread\n");
15541 }
15542 monitor_thread = AST_PTHREADT_NULL;
15543
15544 ast_mutex_lock(&ss_thread_lock);
15545 while (ss_thread_count > 0) {
15546 int x = DAHDI_FLASH;
15547 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15548
15549 ast_mutex_lock(&iflock);
15550 for (p = iflist; p; p = p->next) {
15551 if (p->owner) {
15552
15553 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15554 }
15555 }
15556 ast_mutex_unlock(&iflock);
15557 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15558 }
15559
15560
15561 dahdi_softhangup_all();
15562 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15563 destroy_all_channels();
15564 memset(round_robin, 0, sizeof(round_robin));
15565 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15566
15567 ast_mutex_unlock(&monlock);
15568
15569 #ifdef HAVE_PRI
15570 for (i = 0; i < NUM_SPANS; i++) {
15571 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15572 dahdi_close_pri_fd(&(pris[i]), j);
15573 }
15574
15575 memset(pris, 0, sizeof(pris));
15576 for (i = 0; i < NUM_SPANS; i++) {
15577 sig_pri_init_pri(&pris[i].pri);
15578 }
15579 pri_set_error(dahdi_pri_error);
15580 pri_set_message(dahdi_pri_message);
15581 #endif
15582 #if defined(HAVE_SS7)
15583 for (i = 0; i < NUM_SPANS; i++) {
15584 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15585 dahdi_close_ss7_fd(&(linksets[i]), j);
15586 }
15587
15588 memset(linksets, 0, sizeof(linksets));
15589 for (i = 0; i < NUM_SPANS; i++) {
15590 sig_ss7_init_linkset(&linksets[i].ss7);
15591 }
15592 ss7_set_error(dahdi_ss7_error);
15593 ss7_set_message(dahdi_ss7_message);
15594 #endif
15595
15596 if (setup_dahdi(2) != 0) {
15597 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15598 ast_mutex_unlock(&ss_thread_lock);
15599 return 1;
15600 }
15601 ast_mutex_unlock(&ss_thread_lock);
15602 ast_mutex_unlock(&restart_lock);
15603 return 0;
15604 }
15605
15606 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15607 {
15608 switch (cmd) {
15609 case CLI_INIT:
15610 e->command = "dahdi restart";
15611 e->usage =
15612 "Usage: dahdi restart\n"
15613 " Restarts the DAHDI channels: destroys them all and then\n"
15614 " re-reads them from chan_dahdi.conf.\n"
15615 " Note that this will STOP any running CALL on DAHDI channels.\n"
15616 "";
15617 return NULL;
15618 case CLI_GENERATE:
15619 return NULL;
15620 }
15621 if (a->argc != 2)
15622 return CLI_SHOWUSAGE;
15623
15624 if (dahdi_restart() != 0)
15625 return CLI_FAILURE;
15626 return CLI_SUCCESS;
15627 }
15628
15629 static int action_dahdirestart(struct mansession *s, const struct message *m)
15630 {
15631 if (dahdi_restart() != 0) {
15632 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15633 return 1;
15634 }
15635 astman_send_ack(s, m, "DAHDIRestart: Success");
15636 return 0;
15637 }
15638
15639 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15640 {
15641 #define FORMAT "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15642 #define FORMAT2 "%7s %-15.15s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s %-32.32s\n"
15643 ast_group_t targetnum = 0;
15644 int filtertype = 0;
15645 struct dahdi_pvt *tmp = NULL;
15646 char tmps[20] = "";
15647 char statestr[20] = "";
15648 char blockstr[20] = "";
15649
15650 switch (cmd) {
15651 case CLI_INIT:
15652 e->command = "dahdi show channels [group|context]";
15653 e->usage =
15654 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15655 " Shows a list of available channels with optional filtering\n"
15656 " <group> must be a number between 0 and 63\n";
15657 return NULL;
15658 case CLI_GENERATE:
15659 return NULL;
15660 }
15661
15662
15663
15664 if (!((a->argc == 3) || (a->argc == 5)))
15665 return CLI_SHOWUSAGE;
15666
15667 if (a->argc == 5) {
15668 if (!strcasecmp(a->argv[3], "group")) {
15669 targetnum = atoi(a->argv[4]);
15670 if (63 < targetnum) {
15671 return CLI_SHOWUSAGE;
15672 }
15673 targetnum = ((ast_group_t) 1) << targetnum;
15674 filtertype = 1;
15675 } else if (!strcasecmp(a->argv[3], "context")) {
15676 filtertype = 2;
15677 }
15678 }
15679
15680 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
15681 ast_mutex_lock(&iflock);
15682 for (tmp = iflist; tmp; tmp = tmp->next) {
15683 if (filtertype) {
15684 switch(filtertype) {
15685 case 1:
15686 if (!(tmp->group & targetnum)) {
15687 continue;
15688 }
15689 break;
15690 case 2:
15691 if (strcasecmp(tmp->context, a->argv[4])) {
15692 continue;
15693 }
15694 break;
15695 default:
15696 break;
15697 }
15698 }
15699 if (tmp->channel > 0) {
15700 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15701 } else
15702 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15703
15704 if (tmp->locallyblocked)
15705 blockstr[0] = 'L';
15706 else
15707 blockstr[0] = ' ';
15708
15709 if (tmp->remotelyblocked)
15710 blockstr[1] = 'R';
15711 else
15712 blockstr[1] = ' ';
15713
15714 blockstr[2] = '\0';
15715
15716 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15717
15718 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
15719 }
15720 ast_mutex_unlock(&iflock);
15721 return CLI_SUCCESS;
15722 #undef FORMAT
15723 #undef FORMAT2
15724 }
15725
15726 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15727 {
15728 int channel;
15729 struct dahdi_pvt *tmp = NULL;
15730 struct dahdi_confinfo ci;
15731 struct dahdi_params ps;
15732 int x;
15733
15734 switch (cmd) {
15735 case CLI_INIT:
15736 e->command = "dahdi show channel";
15737 e->usage =
15738 "Usage: dahdi show channel <chan num>\n"
15739 " Detailed information about a given channel\n";
15740 return NULL;
15741 case CLI_GENERATE:
15742 return NULL;
15743 }
15744
15745 if (a->argc != 4)
15746 return CLI_SHOWUSAGE;
15747
15748 channel = atoi(a->argv[3]);
15749
15750 ast_mutex_lock(&iflock);
15751 for (tmp = iflist; tmp; tmp = tmp->next) {
15752 if (tmp->channel == channel) {
15753 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15754 ast_cli(a->fd, "Description: %s\n", tmp->description);
15755 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15756 ast_cli(a->fd, "Span: %d\n", tmp->span);
15757 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15758 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15759 ast_cli(a->fd, "Context: %s\n", tmp->context);
15760 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15761 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15762 #if defined(HAVE_PRI)
15763 #if defined(HAVE_PRI_SUBADDR)
15764 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15765 #endif
15766 #endif
15767 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15768 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15769 if (tmp->vars) {
15770 struct ast_variable *v;
15771 ast_cli(a->fd, "Variables:\n");
15772 for (v = tmp->vars ; v ; v = v->next)
15773 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15774 }
15775 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15776 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15777 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15778 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15779 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? ast_channel_name(tmp->owner) : "<None>");
15780 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)" : "");
15781 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)" : "");
15782 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)" : "");
15783 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15784 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15785 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15786 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15787 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15788 if (tmp->busydetect) {
15789 #if defined(BUSYDETECT_TONEONLY)
15790 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15791 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15792 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15793 #endif
15794 #ifdef BUSYDETECT_DEBUG
15795 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15796 #endif
15797 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15798 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);
15799 }
15800 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15801 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15802 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15803 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15804 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15805 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15806 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15807 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15808 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15809 ast_cli(a->fd, "Echo Cancellation:\n");
15810
15811 if (tmp->echocancel.head.tap_length) {
15812 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15813 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15814 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15815 }
15816 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15817 } else {
15818 ast_cli(a->fd, "\tnone\n");
15819 }
15820 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15821 if (tmp->master)
15822 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15823 for (x = 0; x < MAX_SLAVES; x++) {
15824 if (tmp->slaves[x])
15825 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15826 }
15827 #ifdef HAVE_OPENR2
15828 if (tmp->mfcr2) {
15829 char calldir[OR2_MAX_PATH];
15830 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15831 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15832 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15833 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15834 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15835 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15836 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15837 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15838 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15839 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15840 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
15841 ast_cli(a->fd, "MFC/R2 DTMF Dialing: %s\n", openr2_context_get_dtmf_dialing(r2context, NULL, NULL) ? "Yes" : "No");
15842 ast_cli(a->fd, "MFC/R2 DTMF Detection: %s\n", openr2_context_get_dtmf_detection(r2context) ? "Yes" : "No");
15843 #endif
15844 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15845 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15846 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15847 #endif
15848 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15849 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15850 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15851 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15852 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15853 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15854 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15855 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15856 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15857 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15858 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15859 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15860 }
15861 #endif
15862 #if defined(HAVE_SS7)
15863 if (tmp->ss7) {
15864 struct sig_ss7_chan *chan = tmp->sig_pvt;
15865
15866 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15867 }
15868 #endif
15869 #ifdef HAVE_PRI
15870 if (tmp->pri) {
15871 struct sig_pri_chan *chan = tmp->sig_pvt;
15872
15873 ast_cli(a->fd, "PRI Flags: ");
15874 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15875 ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15876 }
15877 if (chan->call)
15878 ast_cli(a->fd, "Call ");
15879 if (chan->allocated) {
15880 ast_cli(a->fd, "Allocated ");
15881 }
15882 ast_cli(a->fd, "\n");
15883 if (tmp->logicalspan)
15884 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15885 else
15886 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15887 }
15888 #endif
15889 memset(&ci, 0, sizeof(ci));
15890 ps.channo = tmp->channel;
15891 if (tmp->subs[SUB_REAL].dfd > -1) {
15892 memset(&ci, 0, sizeof(ci));
15893 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15894 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15895 }
15896 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15897 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15898 }
15899 memset(&ps, 0, sizeof(ps));
15900 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15901 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15902 } else {
15903 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15904 }
15905 }
15906 ast_mutex_unlock(&iflock);
15907 return CLI_SUCCESS;
15908 }
15909 }
15910 ast_mutex_unlock(&iflock);
15911
15912 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15913 return CLI_FAILURE;
15914 }
15915
15916 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15917 {
15918 int i, j;
15919 switch (cmd) {
15920 case CLI_INIT:
15921 e->command = "dahdi show cadences";
15922 e->usage =
15923 "Usage: dahdi show cadences\n"
15924 " Shows all cadences currently defined\n";
15925 return NULL;
15926 case CLI_GENERATE:
15927 return NULL;
15928 }
15929 for (i = 0; i < num_cadence; i++) {
15930 char output[1024];
15931 char tmp[16], tmp2[64];
15932 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15933 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15934
15935 for (j = 0; j < 16; j++) {
15936 if (cadences[i].ringcadence[j] == 0)
15937 break;
15938 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15939 if (cidrings[i] * 2 - 1 == j)
15940 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15941 else
15942 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15943 if (j != 0)
15944 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15945 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15946 }
15947 ast_cli(a->fd,"%s\n",output);
15948 }
15949 return CLI_SUCCESS;
15950 }
15951
15952
15953 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15954 {
15955 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15956 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15957 int span;
15958 int res;
15959 char alarmstr[50];
15960
15961 int ctl;
15962 struct dahdi_spaninfo s;
15963
15964 switch (cmd) {
15965 case CLI_INIT:
15966 e->command = "dahdi show status";
15967 e->usage =
15968 "Usage: dahdi show status\n"
15969 " Shows a list of DAHDI cards with status\n";
15970 return NULL;
15971 case CLI_GENERATE:
15972 return NULL;
15973 }
15974 ctl = open("/dev/dahdi/ctl", O_RDWR);
15975 if (ctl < 0) {
15976 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15977 return CLI_FAILURE;
15978 }
15979 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15980
15981 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15982 s.spanno = span;
15983 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15984 if (res) {
15985 continue;
15986 }
15987 alarmstr[0] = '\0';
15988 if (s.alarms > 0) {
15989 if (s.alarms & DAHDI_ALARM_BLUE)
15990 strcat(alarmstr, "BLU/");
15991 if (s.alarms & DAHDI_ALARM_YELLOW)
15992 strcat(alarmstr, "YEL/");
15993 if (s.alarms & DAHDI_ALARM_RED)
15994 strcat(alarmstr, "RED/");
15995 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15996 strcat(alarmstr, "LB/");
15997 if (s.alarms & DAHDI_ALARM_RECOVER)
15998 strcat(alarmstr, "REC/");
15999 if (s.alarms & DAHDI_ALARM_NOTOPEN)
16000 strcat(alarmstr, "NOP/");
16001 if (!strlen(alarmstr))
16002 strcat(alarmstr, "UUU/");
16003 if (strlen(alarmstr)) {
16004
16005 alarmstr[strlen(alarmstr) - 1] = '\0';
16006 }
16007 } else {
16008 if (s.numchans)
16009 strcpy(alarmstr, "OK");
16010 else
16011 strcpy(alarmstr, "UNCONFIGURED");
16012 }
16013
16014 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
16015 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
16016 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
16017 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
16018 "CAS",
16019 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
16020 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
16021 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
16022 "Unk",
16023 s.lineconfig & DAHDI_CONFIG_CRC4 ?
16024 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
16025 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
16026 lbostr[s.lbo]
16027 );
16028 }
16029 close(ctl);
16030
16031 return CLI_SUCCESS;
16032 #undef FORMAT
16033 #undef FORMAT2
16034 }
16035
16036 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16037 {
16038 int pseudo_fd = -1;
16039 struct dahdi_versioninfo vi;
16040
16041 switch (cmd) {
16042 case CLI_INIT:
16043 e->command = "dahdi show version";
16044 e->usage =
16045 "Usage: dahdi show version\n"
16046 " Shows the DAHDI version in use\n";
16047 return NULL;
16048 case CLI_GENERATE:
16049 return NULL;
16050 }
16051 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
16052 ast_cli(a->fd, "Failed to open control file to get version.\n");
16053 return CLI_SUCCESS;
16054 }
16055
16056 strcpy(vi.version, "Unknown");
16057 strcpy(vi.echo_canceller, "Unknown");
16058
16059 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
16060 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
16061 else
16062 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
16063
16064 close(pseudo_fd);
16065
16066 return CLI_SUCCESS;
16067 }
16068
16069 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16070 {
16071 int channel;
16072 int gain;
16073 int tx;
16074 struct dahdi_hwgain hwgain;
16075 struct dahdi_pvt *tmp = NULL;
16076
16077 switch (cmd) {
16078 case CLI_INIT:
16079 e->command = "dahdi set hwgain {rx|tx}";
16080 e->usage =
16081 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
16082 " Sets the hardware gain on a given channel. Changes take effect\n"
16083 " immediately whether the channel is in use or not.\n"
16084 "\n"
16085 " <rx|tx> which direction do you want to change (relative to our module)\n"
16086 " <chan num> is the channel number relative to the device\n"
16087 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"
16088 "\n"
16089 " Please note:\n"
16090 " * This is currently the only way to set hwgain by the channel driver.\n"
16091 " * hwgain is only supportable by hardware with analog ports because\n"
16092 " hwgain works on the analog side of an analog-digital conversion.\n";
16093 return NULL;
16094 case CLI_GENERATE:
16095 return NULL;
16096 }
16097
16098 if (a->argc != 6)
16099 return CLI_SHOWUSAGE;
16100
16101 if (!strcasecmp("rx", a->argv[3]))
16102 tx = 0;
16103 else if (!strcasecmp("tx", a->argv[3]))
16104 tx = 1;
16105 else
16106 return CLI_SHOWUSAGE;
16107
16108 channel = atoi(a->argv[4]);
16109 gain = atof(a->argv[5])*10.0;
16110
16111 ast_mutex_lock(&iflock);
16112
16113 for (tmp = iflist; tmp; tmp = tmp->next) {
16114
16115 if (tmp->channel != channel)
16116 continue;
16117
16118 if (tmp->subs[SUB_REAL].dfd == -1)
16119 break;
16120
16121 hwgain.newgain = gain;
16122 hwgain.tx = tx;
16123 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
16124 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
16125 ast_mutex_unlock(&iflock);
16126 return CLI_FAILURE;
16127 }
16128 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
16129 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
16130 break;
16131 }
16132
16133 ast_mutex_unlock(&iflock);
16134
16135 if (tmp)
16136 return CLI_SUCCESS;
16137
16138 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16139 return CLI_FAILURE;
16140
16141 }
16142
16143 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16144 {
16145 int channel;
16146 float gain;
16147 int tx;
16148 int res;
16149 struct dahdi_pvt *tmp = NULL;
16150
16151 switch (cmd) {
16152 case CLI_INIT:
16153 e->command = "dahdi set swgain {rx|tx}";
16154 e->usage =
16155 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
16156 " Sets the software gain on a given channel and overrides the\n"
16157 " value provided at module loadtime. Changes take effect\n"
16158 " immediately whether the channel is in use or not.\n"
16159 "\n"
16160 " <rx|tx> which direction do you want to change (relative to our module)\n"
16161 " <chan num> is the channel number relative to the device\n"
16162 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
16163 return NULL;
16164 case CLI_GENERATE:
16165 return NULL;
16166 }
16167
16168 if (a->argc != 6)
16169 return CLI_SHOWUSAGE;
16170
16171 if (!strcasecmp("rx", a->argv[3]))
16172 tx = 0;
16173 else if (!strcasecmp("tx", a->argv[3]))
16174 tx = 1;
16175 else
16176 return CLI_SHOWUSAGE;
16177
16178 channel = atoi(a->argv[4]);
16179 gain = atof(a->argv[5]);
16180
16181 ast_mutex_lock(&iflock);
16182 for (tmp = iflist; tmp; tmp = tmp->next) {
16183
16184 if (tmp->channel != channel)
16185 continue;
16186
16187 if (tmp->subs[SUB_REAL].dfd == -1)
16188 break;
16189
16190 if (tx)
16191 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
16192 else
16193 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
16194
16195 if (res) {
16196 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
16197 ast_mutex_unlock(&iflock);
16198 return CLI_FAILURE;
16199 }
16200
16201 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
16202 tx ? "tx" : "rx", gain, channel);
16203
16204 if (tx) {
16205 tmp->txgain = gain;
16206 } else {
16207 tmp->rxgain = gain;
16208 }
16209 break;
16210 }
16211 ast_mutex_unlock(&iflock);
16212
16213 if (tmp)
16214 return CLI_SUCCESS;
16215
16216 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16217 return CLI_FAILURE;
16218
16219 }
16220
16221 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16222 {
16223 int channel;
16224 int on;
16225 struct dahdi_pvt *dahdi_chan = NULL;
16226
16227 switch (cmd) {
16228 case CLI_INIT:
16229 e->command = "dahdi set dnd";
16230 e->usage =
16231 "Usage: dahdi set dnd <chan#> <on|off>\n"
16232 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
16233 " Changes take effect immediately.\n"
16234 " <chan num> is the channel number\n"
16235 " <on|off> Enable or disable DND mode?\n"
16236 ;
16237 return NULL;
16238 case CLI_GENERATE:
16239 return NULL;
16240 }
16241
16242 if (a->argc != 5)
16243 return CLI_SHOWUSAGE;
16244
16245 if ((channel = atoi(a->argv[3])) <= 0) {
16246 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
16247 return CLI_SHOWUSAGE;
16248 }
16249
16250 if (ast_true(a->argv[4]))
16251 on = 1;
16252 else if (ast_false(a->argv[4]))
16253 on = 0;
16254 else {
16255 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
16256 return CLI_SHOWUSAGE;
16257 }
16258
16259 ast_mutex_lock(&iflock);
16260 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
16261 if (dahdi_chan->channel != channel)
16262 continue;
16263
16264
16265 dahdi_dnd(dahdi_chan, on);
16266 break;
16267 }
16268 ast_mutex_unlock(&iflock);
16269
16270 if (!dahdi_chan) {
16271 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
16272 return CLI_FAILURE;
16273 }
16274
16275 return CLI_SUCCESS;
16276 }
16277
16278 static struct ast_cli_entry dahdi_cli[] = {
16279 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
16280 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
16281 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
16282 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
16283 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
16284 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
16285 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
16286 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
16287 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
16288 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
16289 };
16290
16291 #define TRANSFER 0
16292 #define HANGUP 1
16293
16294 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
16295 {
16296 if (p) {
16297 switch (mode) {
16298 case TRANSFER:
16299 p->fake_event = DAHDI_EVENT_WINKFLASH;
16300 break;
16301 case HANGUP:
16302 p->fake_event = DAHDI_EVENT_ONHOOK;
16303 break;
16304 default:
16305 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));
16306 }
16307 }
16308 return 0;
16309 }
16310 static struct dahdi_pvt *find_channel(int channel)
16311 {
16312 struct dahdi_pvt *p;
16313
16314 ast_mutex_lock(&iflock);
16315 for (p = iflist; p; p = p->next) {
16316 if (p->channel == channel) {
16317 break;
16318 }
16319 }
16320 ast_mutex_unlock(&iflock);
16321 return p;
16322 }
16323
16324
16325
16326
16327
16328
16329
16330
16331
16332
16333 static struct dahdi_pvt *find_channel_from_str(const char *channel)
16334 {
16335 int chan_num;
16336
16337 if (sscanf(channel, "%30d", &chan_num) != 1) {
16338
16339 return NULL;
16340 }
16341
16342 return find_channel(chan_num);
16343 }
16344
16345 static int action_dahdidndon(struct mansession *s, const struct message *m)
16346 {
16347 struct dahdi_pvt *p;
16348 const char *channel = astman_get_header(m, "DAHDIChannel");
16349
16350 if (ast_strlen_zero(channel)) {
16351 astman_send_error(s, m, "No channel specified");
16352 return 0;
16353 }
16354 p = find_channel_from_str(channel);
16355 if (!p) {
16356 astman_send_error(s, m, "No such channel");
16357 return 0;
16358 }
16359 dahdi_dnd(p, 1);
16360 astman_send_ack(s, m, "DND Enabled");
16361 return 0;
16362 }
16363
16364 static int action_dahdidndoff(struct mansession *s, const struct message *m)
16365 {
16366 struct dahdi_pvt *p;
16367 const char *channel = astman_get_header(m, "DAHDIChannel");
16368
16369 if (ast_strlen_zero(channel)) {
16370 astman_send_error(s, m, "No channel specified");
16371 return 0;
16372 }
16373 p = find_channel_from_str(channel);
16374 if (!p) {
16375 astman_send_error(s, m, "No such channel");
16376 return 0;
16377 }
16378 dahdi_dnd(p, 0);
16379 astman_send_ack(s, m, "DND Disabled");
16380 return 0;
16381 }
16382
16383 static int action_transfer(struct mansession *s, const struct message *m)
16384 {
16385 struct dahdi_pvt *p;
16386 const char *channel = astman_get_header(m, "DAHDIChannel");
16387
16388 if (ast_strlen_zero(channel)) {
16389 astman_send_error(s, m, "No channel specified");
16390 return 0;
16391 }
16392 p = find_channel_from_str(channel);
16393 if (!p) {
16394 astman_send_error(s, m, "No such channel");
16395 return 0;
16396 }
16397 if (!analog_lib_handles(p->sig, 0, 0)) {
16398 astman_send_error(s, m, "Channel signaling is not analog");
16399 return 0;
16400 }
16401 dahdi_fake_event(p,TRANSFER);
16402 astman_send_ack(s, m, "DAHDITransfer");
16403 return 0;
16404 }
16405
16406 static int action_transferhangup(struct mansession *s, const struct message *m)
16407 {
16408 struct dahdi_pvt *p;
16409 const char *channel = astman_get_header(m, "DAHDIChannel");
16410
16411 if (ast_strlen_zero(channel)) {
16412 astman_send_error(s, m, "No channel specified");
16413 return 0;
16414 }
16415 p = find_channel_from_str(channel);
16416 if (!p) {
16417 astman_send_error(s, m, "No such channel");
16418 return 0;
16419 }
16420 if (!analog_lib_handles(p->sig, 0, 0)) {
16421 astman_send_error(s, m, "Channel signaling is not analog");
16422 return 0;
16423 }
16424 dahdi_fake_event(p,HANGUP);
16425 astman_send_ack(s, m, "DAHDIHangup");
16426 return 0;
16427 }
16428
16429 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16430 {
16431 struct dahdi_pvt *p;
16432 const char *channel = astman_get_header(m, "DAHDIChannel");
16433 const char *number = astman_get_header(m, "Number");
16434 int i;
16435
16436 if (ast_strlen_zero(channel)) {
16437 astman_send_error(s, m, "No channel specified");
16438 return 0;
16439 }
16440 if (ast_strlen_zero(number)) {
16441 astman_send_error(s, m, "No number specified");
16442 return 0;
16443 }
16444 p = find_channel_from_str(channel);
16445 if (!p) {
16446 astman_send_error(s, m, "No such channel");
16447 return 0;
16448 }
16449 if (!p->owner) {
16450 astman_send_error(s, m, "Channel does not have it's owner");
16451 return 0;
16452 }
16453 for (i = 0; i < strlen(number); i++) {
16454 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16455 dahdi_queue_frame(p, &f);
16456 }
16457 astman_send_ack(s, m, "DAHDIDialOffhook");
16458 return 0;
16459 }
16460
16461 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16462 {
16463 struct dahdi_pvt *tmp = NULL;
16464 const char *id = astman_get_header(m, "ActionID");
16465 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16466 char idText[256] = "";
16467 int channels = 0;
16468 int dahdichanquery;
16469
16470 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16471
16472 dahdichanquery = -1;
16473 }
16474
16475 astman_send_ack(s, m, "DAHDI channel status will follow");
16476 if (!ast_strlen_zero(id))
16477 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16478
16479 ast_mutex_lock(&iflock);
16480
16481 for (tmp = iflist; tmp; tmp = tmp->next) {
16482 if (tmp->channel > 0) {
16483 int alm;
16484
16485
16486 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16487 continue;
16488
16489 alm = get_alarms(tmp);
16490 channels++;
16491 if (tmp->owner) {
16492
16493 astman_append(s,
16494 "Event: DAHDIShowChannels\r\n"
16495 "DAHDIChannel: %d\r\n"
16496 "Channel: %s\r\n"
16497 "Uniqueid: %s\r\n"
16498 "AccountCode: %s\r\n"
16499 "Signalling: %s\r\n"
16500 "SignallingCode: %d\r\n"
16501 "Context: %s\r\n"
16502 "DND: %s\r\n"
16503 "Alarm: %s\r\n"
16504 "Description: %s\r\n"
16505 "%s"
16506 "\r\n",
16507 tmp->channel,
16508 ast_channel_name(tmp->owner),
16509 ast_channel_uniqueid(tmp->owner),
16510 ast_channel_accountcode(tmp->owner),
16511 sig2str(tmp->sig),
16512 tmp->sig,
16513 tmp->context,
16514 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16515 alarm2str(alm),
16516 tmp->description, idText);
16517 } else {
16518 astman_append(s,
16519 "Event: DAHDIShowChannels\r\n"
16520 "DAHDIChannel: %d\r\n"
16521 "Signalling: %s\r\n"
16522 "SignallingCode: %d\r\n"
16523 "Context: %s\r\n"
16524 "DND: %s\r\n"
16525 "Alarm: %s\r\n"
16526 "Description: %s\r\n"
16527 "%s"
16528 "\r\n",
16529 tmp->channel, sig2str(tmp->sig), tmp->sig,
16530 tmp->context,
16531 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16532 alarm2str(alm),
16533 tmp->description, idText);
16534 }
16535 }
16536 }
16537
16538 ast_mutex_unlock(&iflock);
16539
16540 astman_append(s,
16541 "Event: DAHDIShowChannelsComplete\r\n"
16542 "%s"
16543 "Items: %d\r\n"
16544 "\r\n",
16545 idText,
16546 channels);
16547 return 0;
16548 }
16549
16550 #if defined(HAVE_PRI)
16551 static int action_prishowspans(struct mansession *s, const struct message *m)
16552 {
16553 int count;
16554 int idx;
16555 int span_query;
16556 struct dahdi_pri *dspan;
16557 const char *id = astman_get_header(m, "ActionID");
16558 const char *span_str = astman_get_header(m, "Span");
16559 char action_id[256];
16560 const char *show_cmd = "PRIShowSpans";
16561
16562
16563 if (!ast_strlen_zero(span_str)) {
16564 span_query = atoi(span_str);
16565 } else {
16566 span_query = 0;
16567 }
16568
16569 if (!ast_strlen_zero(id)) {
16570 snprintf(action_id, sizeof(action_id), "ActionID: %s\r\n", id);
16571 } else {
16572 action_id[0] = '\0';
16573 }
16574
16575 astman_send_ack(s, m, "Span status will follow");
16576
16577 count = 0;
16578 for (idx = 0; idx < ARRAY_LEN(pris); ++idx) {
16579 dspan = &pris[idx];
16580
16581
16582 if (0 < span_query && dspan->pri.span != span_query) {
16583 continue;
16584 }
16585
16586 if (dspan->pri.pri) {
16587 count += sig_pri_ami_show_spans(s, show_cmd, &dspan->pri, dspan->dchannels,
16588 action_id);
16589 }
16590 }
16591
16592 astman_append(s,
16593 "Event: %sComplete\r\n"
16594 "Items: %d\r\n"
16595 "%s"
16596 "\r\n",
16597 show_cmd,
16598 count,
16599 action_id);
16600 return 0;
16601 }
16602 #endif
16603
16604 #if defined(HAVE_SS7)
16605 static int linkset_addsigchan(int sigchan)
16606 {
16607 struct dahdi_ss7 *link;
16608 int res;
16609 int curfd;
16610 struct dahdi_params params;
16611 struct dahdi_bufferinfo bi;
16612 struct dahdi_spaninfo si;
16613
16614 if (sigchan < 0) {
16615 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16616 return -1;
16617 }
16618 if (cur_ss7type < 0) {
16619 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16620 return -1;
16621 }
16622 if (cur_pointcode < 0) {
16623 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16624 return -1;
16625 }
16626 if (cur_adjpointcode < 0) {
16627 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16628 return -1;
16629 }
16630 if (cur_defaultdpc < 0) {
16631 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16632 return -1;
16633 }
16634 if (cur_networkindicator < 0) {
16635 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16636 return -1;
16637 }
16638 link = ss7_resolve_linkset(cur_linkset);
16639 if (!link) {
16640 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16641 return -1;
16642 }
16643 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16644 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16645 return -1;
16646 }
16647
16648 curfd = link->ss7.numsigchans;
16649
16650
16651 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16652 if (link->ss7.fds[curfd] < 0) {
16653 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16654 strerror(errno));
16655 return -1;
16656 }
16657 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16658 dahdi_close_ss7_fd(link, curfd);
16659 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16660 strerror(errno));
16661 return -1;
16662 }
16663
16664
16665 memset(¶ms, 0, sizeof(params));
16666 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16667 if (res) {
16668 dahdi_close_ss7_fd(link, curfd);
16669 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16670 strerror(errno));
16671 return -1;
16672 }
16673 if (params.sigtype != DAHDI_SIG_HDLCFCS
16674 && params.sigtype != DAHDI_SIG_HARDHDLC
16675 && params.sigtype != DAHDI_SIG_MTP2) {
16676 dahdi_close_ss7_fd(link, curfd);
16677 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16678 return -1;
16679 }
16680
16681
16682 memset(&bi, 0, sizeof(bi));
16683 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16684 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16685 bi.numbufs = 32;
16686 bi.bufsize = 512;
16687 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16688 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16689 sigchan, strerror(errno));
16690 dahdi_close_ss7_fd(link, curfd);
16691 return -1;
16692 }
16693
16694
16695 memset(&si, 0, sizeof(si));
16696 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16697 if (res) {
16698 dahdi_close_ss7_fd(link, curfd);
16699 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16700 strerror(errno));
16701 }
16702
16703 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16704 (params.sigtype == DAHDI_SIG_MTP2)
16705 ? SS7_TRANSPORT_DAHDIMTP2
16706 : SS7_TRANSPORT_DAHDIDCHAN,
16707 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16708 if (res) {
16709 dahdi_close_ss7_fd(link, curfd);
16710 return -1;
16711 }
16712
16713 ++link->ss7.numsigchans;
16714
16715 return 0;
16716 }
16717 #endif
16718
16719 #if defined(HAVE_SS7)
16720 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16721 {
16722 int span;
16723 switch (cmd) {
16724 case CLI_INIT:
16725 e->command = "ss7 set debug {on|off} linkset";
16726 e->usage =
16727 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16728 " Enables debugging on a given SS7 linkset\n";
16729 return NULL;
16730 case CLI_GENERATE:
16731 return NULL;
16732 }
16733 if (a->argc < 6)
16734 return CLI_SHOWUSAGE;
16735 span = atoi(a->argv[5]);
16736 if ((span < 1) || (span > NUM_SPANS)) {
16737 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16738 return CLI_SUCCESS;
16739 }
16740 if (!linksets[span-1].ss7.ss7) {
16741 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16742 } else {
16743 if (!strcasecmp(a->argv[3], "on")) {
16744 linksets[span - 1].ss7.debug = 1;
16745 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16746 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16747 } else {
16748 linksets[span - 1].ss7.debug = 0;
16749 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16750 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16751 }
16752 }
16753
16754 return CLI_SUCCESS;
16755 }
16756 #endif
16757
16758 #if defined(HAVE_SS7)
16759 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16760 {
16761 int linkset, cic;
16762 int blocked = -1, i;
16763 switch (cmd) {
16764 case CLI_INIT:
16765 e->command = "ss7 block cic";
16766 e->usage =
16767 "Usage: ss7 block cic <linkset> <CIC>\n"
16768 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16769 return NULL;
16770 case CLI_GENERATE:
16771 return NULL;
16772 }
16773 if (a->argc == 5)
16774 linkset = atoi(a->argv[3]);
16775 else
16776 return CLI_SHOWUSAGE;
16777
16778 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16779 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16780 return CLI_SUCCESS;
16781 }
16782
16783 if (!linksets[linkset-1].ss7.ss7) {
16784 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16785 return CLI_SUCCESS;
16786 }
16787
16788 cic = atoi(a->argv[4]);
16789
16790 if (cic < 1) {
16791 ast_cli(a->fd, "Invalid CIC specified!\n");
16792 return CLI_SUCCESS;
16793 }
16794
16795 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16796 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16797 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16798 if (!blocked) {
16799 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16800 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16801 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16802 }
16803 }
16804 }
16805
16806 if (blocked < 0) {
16807 ast_cli(a->fd, "Invalid CIC specified!\n");
16808 return CLI_SUCCESS;
16809 }
16810
16811 if (!blocked)
16812 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16813 else
16814 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16815
16816
16817 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16818
16819 return CLI_SUCCESS;
16820 }
16821 #endif
16822
16823 #if defined(HAVE_SS7)
16824 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16825 {
16826 int linkset;
16827 int i;
16828 switch (cmd) {
16829 case CLI_INIT:
16830 e->command = "ss7 block linkset";
16831 e->usage =
16832 "Usage: ss7 block linkset <linkset number>\n"
16833 " Sends a remote blocking request for all CICs on the given linkset\n";
16834 return NULL;
16835 case CLI_GENERATE:
16836 return NULL;
16837 }
16838 if (a->argc == 4)
16839 linkset = atoi(a->argv[3]);
16840 else
16841 return CLI_SHOWUSAGE;
16842
16843 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16844 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16845 return CLI_SUCCESS;
16846 }
16847
16848 if (!linksets[linkset-1].ss7.ss7) {
16849 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16850 return CLI_SUCCESS;
16851 }
16852
16853 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16854 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16855 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16856 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16857 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16858 }
16859
16860
16861 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16862
16863 return CLI_SUCCESS;
16864 }
16865 #endif
16866
16867 #if defined(HAVE_SS7)
16868 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16869 {
16870 int linkset, cic;
16871 int i, blocked = -1;
16872 switch (cmd) {
16873 case CLI_INIT:
16874 e->command = "ss7 unblock cic";
16875 e->usage =
16876 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16877 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16878 return NULL;
16879 case CLI_GENERATE:
16880 return NULL;
16881 }
16882
16883 if (a->argc == 5)
16884 linkset = atoi(a->argv[3]);
16885 else
16886 return CLI_SHOWUSAGE;
16887
16888 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16889 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16890 return CLI_SUCCESS;
16891 }
16892
16893 if (!linksets[linkset-1].ss7.ss7) {
16894 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16895 return CLI_SUCCESS;
16896 }
16897
16898 cic = atoi(a->argv[4]);
16899
16900 if (cic < 1) {
16901 ast_cli(a->fd, "Invalid CIC specified!\n");
16902 return CLI_SUCCESS;
16903 }
16904
16905 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16906 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16907 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16908 if (blocked) {
16909 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16910 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16911 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16912 }
16913 }
16914 }
16915
16916 if (blocked > 0)
16917 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16918
16919
16920 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16921
16922 return CLI_SUCCESS;
16923 }
16924 #endif
16925
16926 #if defined(HAVE_SS7)
16927 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16928 {
16929 int linkset;
16930 int i;
16931 switch (cmd) {
16932 case CLI_INIT:
16933 e->command = "ss7 unblock linkset";
16934 e->usage =
16935 "Usage: ss7 unblock linkset <linkset number>\n"
16936 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16937 return NULL;
16938 case CLI_GENERATE:
16939 return NULL;
16940 }
16941
16942 if (a->argc == 4)
16943 linkset = atoi(a->argv[3]);
16944 else
16945 return CLI_SHOWUSAGE;
16946
16947 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16948 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16949 return CLI_SUCCESS;
16950 }
16951
16952 if (!linksets[linkset-1].ss7.ss7) {
16953 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16954 return CLI_SUCCESS;
16955 }
16956
16957 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16958 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16959 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16960 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16961 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16962 }
16963
16964
16965 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16966
16967 return CLI_SUCCESS;
16968 }
16969 #endif
16970
16971 #if defined(HAVE_SS7)
16972 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16973 {
16974 int linkset;
16975 struct sig_ss7_linkset *ss7;
16976 switch (cmd) {
16977 case CLI_INIT:
16978 e->command = "ss7 show linkset";
16979 e->usage =
16980 "Usage: ss7 show linkset <span>\n"
16981 " Shows the status of an SS7 linkset.\n";
16982 return NULL;
16983 case CLI_GENERATE:
16984 return NULL;
16985 }
16986
16987 if (a->argc < 4)
16988 return CLI_SHOWUSAGE;
16989 linkset = atoi(a->argv[3]);
16990 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16991 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16992 return CLI_SUCCESS;
16993 }
16994 ss7 = &linksets[linkset - 1].ss7;
16995 if (!ss7->ss7) {
16996 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16997 return CLI_SUCCESS;
16998 }
16999
17000 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
17001
17002 return CLI_SUCCESS;
17003 }
17004 #endif
17005
17006 #if defined(HAVE_SS7)
17007 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17008 {
17009 int linkset;
17010
17011 switch (cmd) {
17012 case CLI_INIT:
17013 e->command = "ss7 show channels";
17014 e->usage =
17015 "Usage: ss7 show channels\n"
17016 " Displays SS7 channel information at a glance.\n";
17017 return NULL;
17018 case CLI_GENERATE:
17019 return NULL;
17020 }
17021
17022 if (a->argc != 3)
17023 return CLI_SHOWUSAGE;
17024
17025 sig_ss7_cli_show_channels_header(a->fd);
17026 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
17027 if (linksets[linkset].ss7.ss7) {
17028 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
17029 }
17030 }
17031 return CLI_SUCCESS;
17032 }
17033 #endif
17034
17035 #if defined(HAVE_SS7)
17036 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
17037 {
17038 switch (cmd) {
17039 case CLI_INIT:
17040 e->command = "ss7 show version";
17041 e->usage =
17042 "Usage: ss7 show version\n"
17043 " Show the libss7 version\n";
17044 return NULL;
17045 case CLI_GENERATE:
17046 return NULL;
17047 }
17048
17049 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
17050
17051 return CLI_SUCCESS;
17052 }
17053 #endif
17054
17055 #if defined(HAVE_SS7)
17056 static struct ast_cli_entry dahdi_ss7_cli[] = {
17057 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
17058 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
17059 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
17060 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
17061 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
17062 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
17063 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
17064 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
17065 };
17066 #endif
17067
17068 #if defined(HAVE_PRI)
17069 #if defined(HAVE_PRI_CCSS)
17070
17071
17072
17073
17074
17075
17076
17077
17078
17079
17080
17081
17082
17083
17084
17085
17086
17087 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
17088 {
17089 struct dahdi_pvt *pvt;
17090 struct sig_pri_chan *pvt_chan;
17091 int res;
17092
17093 ast_assert(!strcmp(ast_channel_tech(chan)->type, "DAHDI"));
17094
17095 pvt = ast_channel_tech_pvt(chan);
17096 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
17097 pvt_chan = pvt->sig_pvt;
17098 } else {
17099 pvt_chan = NULL;
17100 }
17101 if (!pvt_chan) {
17102 return -1;
17103 }
17104
17105 ast_module_ref(ast_module_info->self);
17106
17107 res = sig_pri_cc_agent_init(agent, pvt_chan);
17108 if (res) {
17109 ast_module_unref(ast_module_info->self);
17110 }
17111 return res;
17112 }
17113 #endif
17114 #endif
17115
17116 #if defined(HAVE_PRI)
17117 #if defined(HAVE_PRI_CCSS)
17118
17119
17120
17121
17122
17123
17124
17125
17126
17127
17128
17129
17130
17131 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
17132 {
17133 sig_pri_cc_agent_destructor(agent);
17134
17135 ast_module_unref(ast_module_info->self);
17136 }
17137 #endif
17138 #endif
17139
17140 #if defined(HAVE_PRI)
17141 #if defined(HAVE_PRI_CCSS)
17142 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
17143 .type = dahdi_pri_cc_type,
17144 .init = dahdi_pri_cc_agent_init,
17145 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
17146 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
17147 .respond = sig_pri_cc_agent_req_rsp,
17148 .status_request = sig_pri_cc_agent_status_req,
17149 .stop_ringing = sig_pri_cc_agent_stop_ringing,
17150 .party_b_free = sig_pri_cc_agent_party_b_free,
17151 .start_monitoring = sig_pri_cc_agent_start_monitoring,
17152 .callee_available = sig_pri_cc_agent_callee_available,
17153 .destructor = dahdi_pri_cc_agent_destructor,
17154 };
17155 #endif
17156 #endif
17157
17158 #if defined(HAVE_PRI)
17159 #if defined(HAVE_PRI_CCSS)
17160 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
17161 .type = dahdi_pri_cc_type,
17162 .request_cc = sig_pri_cc_monitor_req_cc,
17163 .suspend = sig_pri_cc_monitor_suspend,
17164 .unsuspend = sig_pri_cc_monitor_unsuspend,
17165 .status_response = sig_pri_cc_monitor_status_rsp,
17166 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
17167 .destructor = sig_pri_cc_monitor_destructor,
17168 };
17169 #endif
17170 #endif
17171
17172 static int __unload_module(void)
17173 {
17174 struct dahdi_pvt *p;
17175 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17176 int i, j;
17177 #endif
17178
17179 #ifdef HAVE_PRI
17180 for (i = 0; i < NUM_SPANS; i++) {
17181 if (pris[i].pri.master != AST_PTHREADT_NULL) {
17182 pthread_cancel(pris[i].pri.master);
17183 pthread_kill(pris[i].pri.master, SIGURG);
17184 }
17185 }
17186 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17187 ast_unregister_application(dahdi_send_keypad_facility_app);
17188 #ifdef HAVE_PRI_PROG_W_CAUSE
17189 ast_unregister_application(dahdi_send_callrerouting_facility_app);
17190 #endif
17191 #endif
17192 #if defined(HAVE_SS7)
17193 for (i = 0; i < NUM_SPANS; i++) {
17194 if (linksets[i].ss7.master != AST_PTHREADT_NULL) {
17195 pthread_cancel(linksets[i].ss7.master);
17196 pthread_kill(linksets[i].ss7.master, SIGURG);
17197 }
17198 }
17199 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17200 #endif
17201 #if defined(HAVE_OPENR2)
17202 dahdi_r2_destroy_links();
17203 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17204 ast_unregister_application(dahdi_accept_r2_call_app);
17205 #endif
17206
17207 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17208 ast_manager_unregister("DAHDIDialOffhook");
17209 ast_manager_unregister("DAHDIHangup");
17210 ast_manager_unregister("DAHDITransfer");
17211 ast_manager_unregister("DAHDIDNDoff");
17212 ast_manager_unregister("DAHDIDNDon");
17213 ast_manager_unregister("DAHDIShowChannels");
17214 ast_manager_unregister("DAHDIRestart");
17215 #if defined(HAVE_PRI)
17216 ast_manager_unregister("PRIShowSpans");
17217 #endif
17218 ast_data_unregister(NULL);
17219 ast_channel_unregister(&dahdi_tech);
17220
17221
17222 ast_mutex_lock(&iflock);
17223 for (p = iflist; p; p = p->next) {
17224 if (p->owner)
17225 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
17226 }
17227 ast_mutex_unlock(&iflock);
17228
17229 ast_mutex_lock(&monlock);
17230 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
17231 pthread_cancel(monitor_thread);
17232 pthread_kill(monitor_thread, SIGURG);
17233 pthread_join(monitor_thread, NULL);
17234 }
17235 monitor_thread = AST_PTHREADT_STOP;
17236 ast_mutex_unlock(&monlock);
17237
17238 destroy_all_channels();
17239
17240 #if defined(HAVE_PRI)
17241 for (i = 0; i < NUM_SPANS; i++) {
17242 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
17243 pthread_join(pris[i].pri.master, NULL);
17244 }
17245 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
17246 dahdi_close_pri_fd(&(pris[i]), j);
17247 }
17248 sig_pri_stop_pri(&pris[i].pri);
17249 }
17250 #if defined(HAVE_PRI_CCSS)
17251 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
17252 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
17253 #endif
17254 sig_pri_unload();
17255 #endif
17256
17257 #if defined(HAVE_SS7)
17258 for (i = 0; i < NUM_SPANS; i++) {
17259 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
17260 pthread_join(linksets[i].ss7.master, NULL);
17261 }
17262 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
17263 dahdi_close_ss7_fd(&(linksets[i]), j);
17264 }
17265 }
17266 #endif
17267 ast_cond_destroy(&ss_thread_complete);
17268
17269 dahdi_tech.capabilities = ast_format_cap_destroy(dahdi_tech.capabilities);
17270 return 0;
17271 }
17272
17273 static int unload_module(void)
17274 {
17275 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17276 int y;
17277 #endif
17278 #ifdef HAVE_PRI
17279 for (y = 0; y < NUM_SPANS; y++)
17280 ast_mutex_destroy(&pris[y].pri.lock);
17281 #endif
17282 #if defined(HAVE_SS7)
17283 for (y = 0; y < NUM_SPANS; y++)
17284 ast_mutex_destroy(&linksets[y].ss7.lock);
17285 #endif
17286 return __unload_module();
17287 }
17288
17289 static void string_replace(char *str, int char1, int char2)
17290 {
17291 for (; *str; str++) {
17292 if (*str == char1) {
17293 *str = char2;
17294 }
17295 }
17296 }
17297
17298 static char *parse_spanchan(char *chanstr, char **subdir)
17299 {
17300 char *p;
17301
17302 if ((p = strrchr(chanstr, '!')) == NULL) {
17303 *subdir = NULL;
17304 return chanstr;
17305 }
17306 *p++ = '\0';
17307 string_replace(chanstr, '!', '/');
17308 *subdir = chanstr;
17309 return p;
17310 }
17311
17312 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
17313 {
17314 char *c, *chan;
17315 char *subdir;
17316 int x, start, finish;
17317 struct dahdi_pvt *tmp;
17318
17319 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
17320 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
17321 return -1;
17322 }
17323
17324 c = ast_strdupa(value);
17325 c = parse_spanchan(c, &subdir);
17326
17327 while ((chan = strsep(&c, ","))) {
17328 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
17329
17330 } else if (sscanf(chan, "%30d", &start)) {
17331
17332 finish = start;
17333 } else if (!strcasecmp(chan, "pseudo")) {
17334 finish = start = CHAN_PSEUDO;
17335 if (found_pseudo)
17336 *found_pseudo = 1;
17337 } else {
17338 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
17339 return -1;
17340 }
17341 if (finish < start) {
17342 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
17343 x = finish;
17344 finish = start;
17345 start = x;
17346 }
17347
17348 for (x = start; x <= finish; x++) {
17349 char fn[PATH_MAX];
17350 int real_channel = x;
17351
17352 if (!ast_strlen_zero(subdir)) {
17353 real_channel = device2chan(subdir, x, fn, sizeof(fn));
17354 if (real_channel < 0) {
17355 if (conf->ignore_failed_channels) {
17356 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
17357 subdir, x, real_channel);
17358 continue;
17359 } else {
17360 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
17361 subdir, x, real_channel);
17362 return -1;
17363 }
17364 }
17365 }
17366 tmp = mkintf(real_channel, conf, reload);
17367
17368 if (tmp) {
17369 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
17370 } else {
17371 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
17372 (reload == 1) ? "reconfigure" : "register", value);
17373 return -1;
17374 }
17375 }
17376 }
17377
17378 return 0;
17379 }
17380
17381
17382
17383 #define MAX_CHANLIST_LEN 80
17384
17385 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
17386 {
17387 char *parse = ast_strdupa(data);
17388 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
17389 unsigned int param_count;
17390 unsigned int x;
17391
17392 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
17393 return;
17394
17395 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
17396
17397
17398
17399 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
17400
17401 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
17402 confp->chan.echocancel.head.tap_length = x;
17403 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
17404 confp->chan.echocancel.head.tap_length = 128;
17405
17406
17407
17408 for (x = 1; x < param_count; x++) {
17409 struct {
17410 char *name;
17411 char *value;
17412 } param;
17413
17414 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
17415 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
17416 continue;
17417 }
17418
17419 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
17420 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
17421 continue;
17422 }
17423
17424 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
17425
17426 if (param.value) {
17427 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
17428 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
17429 continue;
17430 }
17431 }
17432 confp->chan.echocancel.head.param_count++;
17433 }
17434 }
17435
17436 #if defined(HAVE_PRI)
17437 #if defined(HAVE_PRI_DISPLAY_TEXT)
17438
17439
17440
17441
17442
17443
17444
17445
17446
17447 static unsigned long dahdi_display_text_option(const char *value)
17448 {
17449 char *val_str;
17450 char *opt_str;
17451 unsigned long options;
17452
17453 options = 0;
17454 val_str = ast_strdupa(value);
17455
17456 for (;;) {
17457 opt_str = strsep(&val_str, ",");
17458 if (!opt_str) {
17459 break;
17460 }
17461 opt_str = ast_strip(opt_str);
17462 if (!*opt_str) {
17463 continue;
17464 }
17465
17466 if (!strcasecmp(opt_str, "block")) {
17467 options |= PRI_DISPLAY_OPTION_BLOCK;
17468 } else if (!strcasecmp(opt_str, "name_initial")) {
17469 options |= PRI_DISPLAY_OPTION_NAME_INITIAL;
17470 } else if (!strcasecmp(opt_str, "name_update")) {
17471 options |= PRI_DISPLAY_OPTION_NAME_UPDATE;
17472 } else if (!strcasecmp(opt_str, "name")) {
17473 options |= (PRI_DISPLAY_OPTION_NAME_INITIAL | PRI_DISPLAY_OPTION_NAME_UPDATE);
17474 } else if (!strcasecmp(opt_str, "text")) {
17475 options |= PRI_DISPLAY_OPTION_TEXT;
17476 }
17477 }
17478 return options;
17479 }
17480 #endif
17481 #endif
17482
17483 #if defined(HAVE_PRI)
17484 #if defined(HAVE_PRI_DATETIME_SEND)
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494 static int dahdi_datetime_send_option(const char *value)
17495 {
17496 int option;
17497
17498 option = PRI_DATE_TIME_SEND_DEFAULT;
17499
17500 if (ast_false(value)) {
17501 option = PRI_DATE_TIME_SEND_NO;
17502 } else if (!strcasecmp(value, "date")) {
17503 option = PRI_DATE_TIME_SEND_DATE;
17504 } else if (!strcasecmp(value, "date_hh")) {
17505 option = PRI_DATE_TIME_SEND_DATE_HH;
17506 } else if (!strcasecmp(value, "date_hhmm")) {
17507 option = PRI_DATE_TIME_SEND_DATE_HHMM;
17508 } else if (!strcasecmp(value, "date_hhmmss")) {
17509 option = PRI_DATE_TIME_SEND_DATE_HHMMSS;
17510 }
17511
17512 return option;
17513 }
17514 #endif
17515 #endif
17516
17517
17518 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
17519
17520 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
17521
17522 static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_pattern *busy_cadence)
17523 {
17524 int count_pattern = 0;
17525 int norval = 0;
17526 char *temp = NULL;
17527
17528 for (; ;) {
17529
17530 if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
17531 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17532 break;
17533 }
17534
17535 busy_cadence->pattern[count_pattern] = norval;
17536
17537 count_pattern++;
17538 if (count_pattern == 4) {
17539 break;
17540 }
17541
17542 temp = strchr(v->value, ',');
17543 if (temp == NULL) {
17544 break;
17545 }
17546 v->value = temp + 1;
17547 }
17548 busy_cadence->length = count_pattern;
17549
17550 if (count_pattern % 2 != 0) {
17551
17552 ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
17553 }
17554
17555 }
17556
17557 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17558 {
17559 struct dahdi_pvt *tmp;
17560 int y;
17561 int found_pseudo = 0;
17562 struct ast_variable *dahdichan = NULL;
17563
17564 for (; v; v = v->next) {
17565 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17566 continue;
17567
17568
17569 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17570 if (options & PROC_DAHDI_OPT_NOCHAN) {
17571 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17572 continue;
17573 }
17574 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17575 if (confp->ignore_failed_channels) {
17576 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17577 continue;
17578 } else {
17579 return -1;
17580 }
17581 }
17582 ast_debug(1, "Channel '%s' configured.\n", v->value);
17583 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17584 confp->ignore_failed_channels = ast_true(v->value);
17585 } else if (!strcasecmp(v->name, "buffers")) {
17586 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17587 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17588 confp->chan.buf_no = numbufs;
17589 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17590 }
17591 } else if (!strcasecmp(v->name, "faxbuffers")) {
17592 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17593 confp->chan.usefaxbuffers = 1;
17594 }
17595 } else if (!strcasecmp(v->name, "dahdichan")) {
17596
17597 dahdichan = v;
17598 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17599 usedistinctiveringdetection = ast_true(v->value);
17600 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17601 distinctiveringaftercid = ast_true(v->value);
17602 } else if (!strcasecmp(v->name, "dring1context")) {
17603 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17604 } else if (!strcasecmp(v->name, "dring2context")) {
17605 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17606 } else if (!strcasecmp(v->name, "dring3context")) {
17607 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17608 } else if (!strcasecmp(v->name, "dring1range")) {
17609 confp->chan.drings.ringnum[0].range = atoi(v->value);
17610 } else if (!strcasecmp(v->name, "dring2range")) {
17611 confp->chan.drings.ringnum[1].range = atoi(v->value);
17612 } else if (!strcasecmp(v->name, "dring3range")) {
17613 confp->chan.drings.ringnum[2].range = atoi(v->value);
17614 } else if (!strcasecmp(v->name, "dring1")) {
17615 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]);
17616 } else if (!strcasecmp(v->name, "dring2")) {
17617 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]);
17618 } else if (!strcasecmp(v->name, "dring3")) {
17619 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]);
17620 } else if (!strcasecmp(v->name, "usecallerid")) {
17621 confp->chan.use_callerid = ast_true(v->value);
17622 } else if (!strcasecmp(v->name, "cidsignalling")) {
17623 if (!strcasecmp(v->value, "bell"))
17624 confp->chan.cid_signalling = CID_SIG_BELL;
17625 else if (!strcasecmp(v->value, "v23"))
17626 confp->chan.cid_signalling = CID_SIG_V23;
17627 else if (!strcasecmp(v->value, "dtmf"))
17628 confp->chan.cid_signalling = CID_SIG_DTMF;
17629 else if (!strcasecmp(v->value, "smdi"))
17630 confp->chan.cid_signalling = CID_SIG_SMDI;
17631 else if (!strcasecmp(v->value, "v23_jp"))
17632 confp->chan.cid_signalling = CID_SIG_V23_JP;
17633 else if (ast_true(v->value))
17634 confp->chan.cid_signalling = CID_SIG_BELL;
17635 } else if (!strcasecmp(v->name, "cidstart")) {
17636 if (!strcasecmp(v->value, "ring"))
17637 confp->chan.cid_start = CID_START_RING;
17638 else if (!strcasecmp(v->value, "polarity_in"))
17639 confp->chan.cid_start = CID_START_POLARITY_IN;
17640 else if (!strcasecmp(v->value, "polarity"))
17641 confp->chan.cid_start = CID_START_POLARITY;
17642 else if (!strcasecmp(v->value, "dtmf"))
17643 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17644 else if (ast_true(v->value))
17645 confp->chan.cid_start = CID_START_RING;
17646 } else if (!strcasecmp(v->name, "threewaycalling")) {
17647 confp->chan.threewaycalling = ast_true(v->value);
17648 } else if (!strcasecmp(v->name, "cancallforward")) {
17649 confp->chan.cancallforward = ast_true(v->value);
17650 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17651 if (ast_true(v->value))
17652 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17653 else
17654 confp->chan.dtmfrelax = 0;
17655 } else if (!strcasecmp(v->name, "mailbox")) {
17656 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17657 } else if (!strcasecmp(v->name, "description")) {
17658 ast_copy_string(confp->chan.description, v->value, sizeof(confp->chan.description));
17659 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17660 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17661 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17662 }
17663 } else if (!strcasecmp(v->name, "adsi")) {
17664 confp->chan.adsi = ast_true(v->value);
17665 } else if (!strcasecmp(v->name, "usesmdi")) {
17666 confp->chan.use_smdi = ast_true(v->value);
17667 } else if (!strcasecmp(v->name, "smdiport")) {
17668 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17669 } else if (!strcasecmp(v->name, "transfer")) {
17670 confp->chan.transfer = ast_true(v->value);
17671 } else if (!strcasecmp(v->name, "canpark")) {
17672 confp->chan.canpark = ast_true(v->value);
17673 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17674 confp->chan.echocanbridged = ast_true(v->value);
17675 } else if (!strcasecmp(v->name, "busydetect")) {
17676 confp->chan.busydetect = ast_true(v->value);
17677 } else if (!strcasecmp(v->name, "busycount")) {
17678 confp->chan.busycount = atoi(v->value);
17679 } else if (!strcasecmp(v->name, "busypattern")) {
17680 parse_busy_pattern(v, &confp->chan.busy_cadence);
17681 } else if (!strcasecmp(v->name, "callprogress")) {
17682 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17683 if (ast_true(v->value))
17684 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17685 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17686 confp->chan.waitfordialtone = atoi(v->value);
17687 } else if (!strcasecmp(v->name, "dialtone_detect")) {
17688 if (!strcasecmp(v->value, "always")) {
17689 confp->chan.dialtone_detect = -1;
17690 } else if (ast_true(v->value)) {
17691 confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
17692 } else if (ast_false(v->value)) {
17693 confp->chan.dialtone_detect = 0;
17694 } else {
17695 confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
17696 }
17697 } else if (!strcasecmp(v->name, "faxdetect")) {
17698 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17699 if (!strcasecmp(v->value, "incoming")) {
17700 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17701 } else if (!strcasecmp(v->value, "outgoing")) {
17702 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17703 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17704 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17705 } else if (!strcasecmp(v->name, "echocancel")) {
17706 process_echocancel(confp, v->value, v->lineno);
17707 } else if (!strcasecmp(v->name, "echotraining")) {
17708 if (sscanf(v->value, "%30d", &y) == 1) {
17709 if ((y < 10) || (y > 4000)) {
17710 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17711 } else {
17712 confp->chan.echotraining = y;
17713 }
17714 } else if (ast_true(v->value)) {
17715 confp->chan.echotraining = 400;
17716 } else
17717 confp->chan.echotraining = 0;
17718 } else if (!strcasecmp(v->name, "hidecallerid")) {
17719 confp->chan.hidecallerid = ast_true(v->value);
17720 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17721 confp->chan.hidecalleridname = ast_true(v->value);
17722 } else if (!strcasecmp(v->name, "pulsedial")) {
17723 confp->chan.pulse = ast_true(v->value);
17724 } else if (!strcasecmp(v->name, "callreturn")) {
17725 confp->chan.callreturn = ast_true(v->value);
17726 } else if (!strcasecmp(v->name, "callwaiting")) {
17727 confp->chan.callwaiting = ast_true(v->value);
17728 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17729 confp->chan.callwaitingcallerid = ast_true(v->value);
17730 } else if (!strcasecmp(v->name, "context")) {
17731 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17732 } else if (!strcasecmp(v->name, "language")) {
17733 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17734 } else if (!strcasecmp(v->name, "progzone")) {
17735 ast_copy_string(progzone, v->value, sizeof(progzone));
17736 } else if (!strcasecmp(v->name, "mohinterpret")
17737 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17738 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17739 } else if (!strcasecmp(v->name, "mohsuggest")) {
17740 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17741 } else if (!strcasecmp(v->name, "parkinglot")) {
17742 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17743 } else if (!strcasecmp(v->name, "stripmsd")) {
17744 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17745 confp->chan.stripmsd = atoi(v->value);
17746 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17747 numbufs = atoi(v->value);
17748 } else if (!strcasecmp(v->name, "group")) {
17749 confp->chan.group = ast_get_group(v->value);
17750 } else if (!strcasecmp(v->name, "callgroup")) {
17751 if (!strcasecmp(v->value, "none"))
17752 confp->chan.callgroup = 0;
17753 else
17754 confp->chan.callgroup = ast_get_group(v->value);
17755 } else if (!strcasecmp(v->name, "pickupgroup")) {
17756 if (!strcasecmp(v->value, "none"))
17757 confp->chan.pickupgroup = 0;
17758 else
17759 confp->chan.pickupgroup = ast_get_group(v->value);
17760 } else if (!strcasecmp(v->name, "namedcallgroup")) {
17761 confp->chan.named_callgroups = ast_get_namedgroups(v->value);
17762 } else if (!strcasecmp(v->name, "namedpickupgroup")) {
17763 confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
17764 } else if (!strcasecmp(v->name, "setvar")) {
17765 char *varname = ast_strdupa(v->value), *varval = NULL;
17766 struct ast_variable *tmpvar;
17767 if (varname && (varval = strchr(varname, '='))) {
17768 *varval++ = '\0';
17769 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17770 tmpvar->next = confp->chan.vars;
17771 confp->chan.vars = tmpvar;
17772 }
17773 }
17774 } else if (!strcasecmp(v->name, "immediate")) {
17775 confp->chan.immediate = ast_true(v->value);
17776 } else if (!strcasecmp(v->name, "transfertobusy")) {
17777 confp->chan.transfertobusy = ast_true(v->value);
17778 } else if (!strcasecmp(v->name, "mwimonitor")) {
17779 confp->chan.mwimonitor_neon = 0;
17780 confp->chan.mwimonitor_fsk = 0;
17781 confp->chan.mwimonitor_rpas = 0;
17782 if (strcasestr(v->value, "fsk")) {
17783 confp->chan.mwimonitor_fsk = 1;
17784 }
17785 if (strcasestr(v->value, "rpas")) {
17786 confp->chan.mwimonitor_rpas = 1;
17787 }
17788 if (strcasestr(v->value, "neon")) {
17789 confp->chan.mwimonitor_neon = 1;
17790 }
17791
17792 if (ast_true(v->value)) {
17793 confp->chan.mwimonitor_fsk = 1;
17794 }
17795 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17796 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17797 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17798 }
17799 } else if (!strcasecmp(v->name, "rxgain")) {
17800 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17801 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17802 }
17803 } else if (!strcasecmp(v->name, "txgain")) {
17804 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17805 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17806 }
17807 } else if (!strcasecmp(v->name, "txdrc")) {
17808 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17809 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17810 }
17811 } else if (!strcasecmp(v->name, "rxdrc")) {
17812 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17813 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17814 }
17815 } else if (!strcasecmp(v->name, "tonezone")) {
17816 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17817 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17818 }
17819 } else if (!strcasecmp(v->name, "callerid")) {
17820 if (!strcasecmp(v->value, "asreceived")) {
17821 confp->chan.cid_num[0] = '\0';
17822 confp->chan.cid_name[0] = '\0';
17823 } else {
17824 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17825 }
17826 } else if (!strcasecmp(v->name, "fullname")) {
17827 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17828 } else if (!strcasecmp(v->name, "cid_number")) {
17829 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17830 } else if (!strcasecmp(v->name, "cid_tag")) {
17831 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17832 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17833 confp->chan.dahditrcallerid = ast_true(v->value);
17834 } else if (!strcasecmp(v->name, "restrictcid")) {
17835 confp->chan.restrictcid = ast_true(v->value);
17836 } else if (!strcasecmp(v->name, "usecallingpres")) {
17837 confp->chan.use_callingpres = ast_true(v->value);
17838 } else if (!strcasecmp(v->name, "accountcode")) {
17839 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17840 } else if (!strcasecmp(v->name, "amaflags")) {
17841 y = ast_cdr_amaflags2int(v->value);
17842 if (y < 0)
17843 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17844 else
17845 confp->chan.amaflags = y;
17846 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17847 confp->chan.polarityonanswerdelay = atoi(v->value);
17848 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17849 confp->chan.answeronpolarityswitch = ast_true(v->value);
17850 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17851 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17852 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17853 confp->chan.sendcalleridafter = atoi(v->value);
17854 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17855 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17856 } else if (ast_cc_is_config_param(v->name)) {
17857 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17858 } else if (!strcasecmp(v->name, "mwisendtype")) {
17859 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17860 if (!strcasecmp(v->value, "rpas")) {
17861 mwisend_rpas = 1;
17862 } else {
17863 mwisend_rpas = 0;
17864 }
17865 #else
17866
17867 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17868 if (strcasestr(v->value, "nofsk")) {
17869 confp->chan.mwisend_fsk = 0;
17870 } else {
17871 confp->chan.mwisend_fsk = 1;
17872 }
17873 if (strcasestr(v->value, "rpas")) {
17874 confp->chan.mwisend_rpas = 1;
17875 } else {
17876 confp->chan.mwisend_rpas = 0;
17877 }
17878 if (strcasestr(v->value, "lrev")) {
17879 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17880 }
17881 if (strcasestr(v->value, "hvdc")) {
17882 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17883 }
17884 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17885 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17886 }
17887 #endif
17888 } else if (reload != 1) {
17889 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17890 int orig_radio = confp->chan.radio;
17891 int orig_outsigmod = confp->chan.outsigmod;
17892 int orig_auto = confp->is_sig_auto;
17893
17894 confp->chan.radio = 0;
17895 confp->chan.outsigmod = -1;
17896 confp->is_sig_auto = 0;
17897 if (!strcasecmp(v->value, "em")) {
17898 confp->chan.sig = SIG_EM;
17899 } else if (!strcasecmp(v->value, "em_e1")) {
17900 confp->chan.sig = SIG_EM_E1;
17901 } else if (!strcasecmp(v->value, "em_w")) {
17902 confp->chan.sig = SIG_EMWINK;
17903 } else if (!strcasecmp(v->value, "fxs_ls")) {
17904 confp->chan.sig = SIG_FXSLS;
17905 } else if (!strcasecmp(v->value, "fxs_gs")) {
17906 confp->chan.sig = SIG_FXSGS;
17907 } else if (!strcasecmp(v->value, "fxs_ks")) {
17908 confp->chan.sig = SIG_FXSKS;
17909 } else if (!strcasecmp(v->value, "fxo_ls")) {
17910 confp->chan.sig = SIG_FXOLS;
17911 } else if (!strcasecmp(v->value, "fxo_gs")) {
17912 confp->chan.sig = SIG_FXOGS;
17913 } else if (!strcasecmp(v->value, "fxo_ks")) {
17914 confp->chan.sig = SIG_FXOKS;
17915 } else if (!strcasecmp(v->value, "fxs_rx")) {
17916 confp->chan.sig = SIG_FXSKS;
17917 confp->chan.radio = 1;
17918 } else if (!strcasecmp(v->value, "fxo_rx")) {
17919 confp->chan.sig = SIG_FXOLS;
17920 confp->chan.radio = 1;
17921 } else if (!strcasecmp(v->value, "fxs_tx")) {
17922 confp->chan.sig = SIG_FXSLS;
17923 confp->chan.radio = 1;
17924 } else if (!strcasecmp(v->value, "fxo_tx")) {
17925 confp->chan.sig = SIG_FXOGS;
17926 confp->chan.radio = 1;
17927 } else if (!strcasecmp(v->value, "em_rx")) {
17928 confp->chan.sig = SIG_EM;
17929 confp->chan.radio = 1;
17930 } else if (!strcasecmp(v->value, "em_tx")) {
17931 confp->chan.sig = SIG_EM;
17932 confp->chan.radio = 1;
17933 } else if (!strcasecmp(v->value, "em_rxtx")) {
17934 confp->chan.sig = SIG_EM;
17935 confp->chan.radio = 2;
17936 } else if (!strcasecmp(v->value, "em_txrx")) {
17937 confp->chan.sig = SIG_EM;
17938 confp->chan.radio = 2;
17939 } else if (!strcasecmp(v->value, "sf")) {
17940 confp->chan.sig = SIG_SF;
17941 } else if (!strcasecmp(v->value, "sf_w")) {
17942 confp->chan.sig = SIG_SFWINK;
17943 } else if (!strcasecmp(v->value, "sf_featd")) {
17944 confp->chan.sig = SIG_FEATD;
17945 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17946 confp->chan.sig = SIG_FEATDMF;
17947 } else if (!strcasecmp(v->value, "sf_featb")) {
17948 confp->chan.sig = SIG_SF_FEATB;
17949 } else if (!strcasecmp(v->value, "sf")) {
17950 confp->chan.sig = SIG_SF;
17951 } else if (!strcasecmp(v->value, "sf_rx")) {
17952 confp->chan.sig = SIG_SF;
17953 confp->chan.radio = 1;
17954 } else if (!strcasecmp(v->value, "sf_tx")) {
17955 confp->chan.sig = SIG_SF;
17956 confp->chan.radio = 1;
17957 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17958 confp->chan.sig = SIG_SF;
17959 confp->chan.radio = 2;
17960 } else if (!strcasecmp(v->value, "sf_txrx")) {
17961 confp->chan.sig = SIG_SF;
17962 confp->chan.radio = 2;
17963 } else if (!strcasecmp(v->value, "featd")) {
17964 confp->chan.sig = SIG_FEATD;
17965 } else if (!strcasecmp(v->value, "featdmf")) {
17966 confp->chan.sig = SIG_FEATDMF;
17967 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17968 confp->chan.sig = SIG_FEATDMF_TA;
17969 } else if (!strcasecmp(v->value, "e911")) {
17970 confp->chan.sig = SIG_E911;
17971 } else if (!strcasecmp(v->value, "fgccama")) {
17972 confp->chan.sig = SIG_FGC_CAMA;
17973 } else if (!strcasecmp(v->value, "fgccamamf")) {
17974 confp->chan.sig = SIG_FGC_CAMAMF;
17975 } else if (!strcasecmp(v->value, "featb")) {
17976 confp->chan.sig = SIG_FEATB;
17977 #ifdef HAVE_PRI
17978 } else if (!strcasecmp(v->value, "pri_net")) {
17979 confp->chan.sig = SIG_PRI;
17980 confp->pri.pri.nodetype = PRI_NETWORK;
17981 } else if (!strcasecmp(v->value, "pri_cpe")) {
17982 confp->chan.sig = SIG_PRI;
17983 confp->pri.pri.nodetype = PRI_CPE;
17984 } else if (!strcasecmp(v->value, "bri_cpe")) {
17985 confp->chan.sig = SIG_BRI;
17986 confp->pri.pri.nodetype = PRI_CPE;
17987 } else if (!strcasecmp(v->value, "bri_net")) {
17988 confp->chan.sig = SIG_BRI;
17989 confp->pri.pri.nodetype = PRI_NETWORK;
17990 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17991 confp->chan.sig = SIG_BRI_PTMP;
17992 confp->pri.pri.nodetype = PRI_CPE;
17993 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17994 #if defined(HAVE_PRI_CALL_HOLD)
17995 confp->chan.sig = SIG_BRI_PTMP;
17996 confp->pri.pri.nodetype = PRI_NETWORK;
17997 #else
17998 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17999 #endif
18000 #endif
18001 #if defined(HAVE_SS7)
18002 } else if (!strcasecmp(v->value, "ss7")) {
18003 confp->chan.sig = SIG_SS7;
18004 #endif
18005 #ifdef HAVE_OPENR2
18006 } else if (!strcasecmp(v->value, "mfcr2")) {
18007 confp->chan.sig = SIG_MFCR2;
18008 #endif
18009 } else if (!strcasecmp(v->value, "auto")) {
18010 confp->is_sig_auto = 1;
18011 } else {
18012 confp->chan.outsigmod = orig_outsigmod;
18013 confp->chan.radio = orig_radio;
18014 confp->is_sig_auto = orig_auto;
18015 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18016 }
18017 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
18018 if (!strcasecmp(v->value, "em")) {
18019 confp->chan.outsigmod = SIG_EM;
18020 } else if (!strcasecmp(v->value, "em_e1")) {
18021 confp->chan.outsigmod = SIG_EM_E1;
18022 } else if (!strcasecmp(v->value, "em_w")) {
18023 confp->chan.outsigmod = SIG_EMWINK;
18024 } else if (!strcasecmp(v->value, "sf")) {
18025 confp->chan.outsigmod = SIG_SF;
18026 } else if (!strcasecmp(v->value, "sf_w")) {
18027 confp->chan.outsigmod = SIG_SFWINK;
18028 } else if (!strcasecmp(v->value, "sf_featd")) {
18029 confp->chan.outsigmod = SIG_FEATD;
18030 } else if (!strcasecmp(v->value, "sf_featdmf")) {
18031 confp->chan.outsigmod = SIG_FEATDMF;
18032 } else if (!strcasecmp(v->value, "sf_featb")) {
18033 confp->chan.outsigmod = SIG_SF_FEATB;
18034 } else if (!strcasecmp(v->value, "sf")) {
18035 confp->chan.outsigmod = SIG_SF;
18036 } else if (!strcasecmp(v->value, "featd")) {
18037 confp->chan.outsigmod = SIG_FEATD;
18038 } else if (!strcasecmp(v->value, "featdmf")) {
18039 confp->chan.outsigmod = SIG_FEATDMF;
18040 } else if (!strcasecmp(v->value, "featdmf_ta")) {
18041 confp->chan.outsigmod = SIG_FEATDMF_TA;
18042 } else if (!strcasecmp(v->value, "e911")) {
18043 confp->chan.outsigmod = SIG_E911;
18044 } else if (!strcasecmp(v->value, "fgccama")) {
18045 confp->chan.outsigmod = SIG_FGC_CAMA;
18046 } else if (!strcasecmp(v->value, "fgccamamf")) {
18047 confp->chan.outsigmod = SIG_FGC_CAMAMF;
18048 } else if (!strcasecmp(v->value, "featb")) {
18049 confp->chan.outsigmod = SIG_FEATB;
18050 } else {
18051 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
18052 }
18053 #ifdef HAVE_PRI
18054 } else if (!strcasecmp(v->name, "pridialplan")) {
18055 if (!strcasecmp(v->value, "national")) {
18056 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
18057 } else if (!strcasecmp(v->value, "unknown")) {
18058 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
18059 } else if (!strcasecmp(v->value, "private")) {
18060 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
18061 } else if (!strcasecmp(v->value, "international")) {
18062 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
18063 } else if (!strcasecmp(v->value, "local")) {
18064 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
18065 } else if (!strcasecmp(v->value, "dynamic")) {
18066 confp->pri.pri.dialplan = -1;
18067 } else if (!strcasecmp(v->value, "redundant")) {
18068 confp->pri.pri.dialplan = -2;
18069 } else {
18070 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
18071 }
18072 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
18073 if (!strcasecmp(v->value, "national")) {
18074 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
18075 } else if (!strcasecmp(v->value, "unknown")) {
18076 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
18077 } else if (!strcasecmp(v->value, "private")) {
18078 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
18079 } else if (!strcasecmp(v->value, "international")) {
18080 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
18081 } else if (!strcasecmp(v->value, "local")) {
18082 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
18083 } else if (!strcasecmp(v->value, "from_channel")) {
18084 confp->pri.pri.localdialplan = 0;
18085 } else if (!strcasecmp(v->value, "dynamic")) {
18086 confp->pri.pri.localdialplan = -1;
18087 } else if (!strcasecmp(v->value, "redundant")) {
18088 confp->pri.pri.localdialplan = -2;
18089 } else {
18090 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
18091 }
18092 } else if (!strcasecmp(v->name, "pricpndialplan")) {
18093 if (!strcasecmp(v->value, "national")) {
18094 confp->pri.pri.cpndialplan = PRI_NATIONAL_ISDN + 1;
18095 } else if (!strcasecmp(v->value, "unknown")) {
18096 confp->pri.pri.cpndialplan = PRI_UNKNOWN + 1;
18097 } else if (!strcasecmp(v->value, "private")) {
18098 confp->pri.pri.cpndialplan = PRI_PRIVATE + 1;
18099 } else if (!strcasecmp(v->value, "international")) {
18100 confp->pri.pri.cpndialplan = PRI_INTERNATIONAL_ISDN + 1;
18101 } else if (!strcasecmp(v->value, "local")) {
18102 confp->pri.pri.cpndialplan = PRI_LOCAL_ISDN + 1;
18103 } else if (!strcasecmp(v->value, "from_channel")) {
18104 confp->pri.pri.cpndialplan = 0;
18105 } else if (!strcasecmp(v->value, "dynamic")) {
18106 confp->pri.pri.cpndialplan = -1;
18107 } else if (!strcasecmp(v->value, "redundant")) {
18108 confp->pri.pri.cpndialplan = -2;
18109 } else {
18110 ast_log(LOG_WARNING, "Unknown PRI cpndialplan '%s' at line %d.\n", v->value, v->lineno);
18111 }
18112 } else if (!strcasecmp(v->name, "switchtype")) {
18113 if (!strcasecmp(v->value, "national"))
18114 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
18115 else if (!strcasecmp(v->value, "ni1"))
18116 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
18117 else if (!strcasecmp(v->value, "dms100"))
18118 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
18119 else if (!strcasecmp(v->value, "4ess"))
18120 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
18121 else if (!strcasecmp(v->value, "5ess"))
18122 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
18123 else if (!strcasecmp(v->value, "euroisdn"))
18124 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
18125 else if (!strcasecmp(v->value, "qsig"))
18126 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
18127 else {
18128 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
18129 return -1;
18130 }
18131 } else if (!strcasecmp(v->name, "msn")) {
18132 ast_copy_string(confp->pri.pri.msn_list, v->value,
18133 sizeof(confp->pri.pri.msn_list));
18134 } else if (!strcasecmp(v->name, "nsf")) {
18135 if (!strcasecmp(v->value, "sdn"))
18136 confp->pri.pri.nsf = PRI_NSF_SDN;
18137 else if (!strcasecmp(v->value, "megacom"))
18138 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
18139 else if (!strcasecmp(v->value, "tollfreemegacom"))
18140 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
18141 else if (!strcasecmp(v->value, "accunet"))
18142 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
18143 else if (!strcasecmp(v->value, "none"))
18144 confp->pri.pri.nsf = PRI_NSF_NONE;
18145 else {
18146 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
18147 confp->pri.pri.nsf = PRI_NSF_NONE;
18148 }
18149 } else if (!strcasecmp(v->name, "priindication")) {
18150 if (!strcasecmp(v->value, "outofband"))
18151 confp->chan.priindication_oob = 1;
18152 else if (!strcasecmp(v->value, "inband"))
18153 confp->chan.priindication_oob = 0;
18154 else
18155 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
18156 v->value, v->lineno);
18157 } else if (!strcasecmp(v->name, "priexclusive")) {
18158 confp->chan.priexclusive = ast_true(v->value);
18159 } else if (!strcasecmp(v->name, "internationalprefix")) {
18160 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
18161 } else if (!strcasecmp(v->name, "nationalprefix")) {
18162 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
18163 } else if (!strcasecmp(v->name, "localprefix")) {
18164 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
18165 } else if (!strcasecmp(v->name, "privateprefix")) {
18166 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
18167 } else if (!strcasecmp(v->name, "unknownprefix")) {
18168 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
18169 } else if (!strcasecmp(v->name, "resetinterval")) {
18170 if (!strcasecmp(v->value, "never"))
18171 confp->pri.pri.resetinterval = -1;
18172 else if (atoi(v->value) >= 60)
18173 confp->pri.pri.resetinterval = atoi(v->value);
18174 else
18175 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
18176 v->value, v->lineno);
18177 } else if (!strcasecmp(v->name, "minunused")) {
18178 confp->pri.pri.minunused = atoi(v->value);
18179 } else if (!strcasecmp(v->name, "minidle")) {
18180 confp->pri.pri.minidle = atoi(v->value);
18181 } else if (!strcasecmp(v->name, "idleext")) {
18182 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
18183 } else if (!strcasecmp(v->name, "idledial")) {
18184 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
18185 } else if (!strcasecmp(v->name, "overlapdial")) {
18186 if (ast_true(v->value)) {
18187 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18188 } else if (!strcasecmp(v->value, "incoming")) {
18189 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
18190 } else if (!strcasecmp(v->value, "outgoing")) {
18191 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
18192 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
18193 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
18194 } else {
18195 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
18196 }
18197 #ifdef HAVE_PRI_PROG_W_CAUSE
18198 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
18199 if (!strcasecmp(v->value, "logical")) {
18200 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
18201 } else if (!strcasecmp(v->value, "physical")) {
18202 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18203 } else {
18204 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
18205 }
18206 #endif
18207 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
18208 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
18209 #if defined(HAVE_PRI_SERVICE_MESSAGES)
18210 } else if (!strcasecmp(v->name, "service_message_support")) {
18211
18212 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
18213 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
18214 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
18215 confp->pri.pri.enable_service_message_support = 1;
18216 } else {
18217 confp->pri.pri.enable_service_message_support = 0;
18218 }
18219 #endif
18220 #ifdef HAVE_PRI_INBANDDISCONNECT
18221 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
18222 confp->pri.pri.inbanddisconnect = ast_true(v->value);
18223 #endif
18224 } else if (!strcasecmp(v->name, "pritimer")) {
18225 #ifdef PRI_GETSET_TIMERS
18226 char tmp[20];
18227 char *timerc;
18228 char *c;
18229 int timer;
18230 int timeridx;
18231
18232 ast_copy_string(tmp, v->value, sizeof(tmp));
18233 c = tmp;
18234 timerc = strsep(&c, ",");
18235 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
18236 timeridx = pri_timer2idx(timerc);
18237 timer = atoi(c);
18238 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
18239 ast_log(LOG_WARNING,
18240 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
18241 v->lineno);
18242 } else if (!timer) {
18243 ast_log(LOG_WARNING,
18244 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
18245 c, timerc, v->lineno);
18246 } else {
18247 confp->pri.pri.pritimers[timeridx] = timer;
18248 }
18249 } else {
18250 ast_log(LOG_WARNING,
18251 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
18252 v->value, v->lineno);
18253 }
18254 #endif
18255 } else if (!strcasecmp(v->name, "facilityenable")) {
18256 confp->pri.pri.facilityenable = ast_true(v->value);
18257 #if defined(HAVE_PRI_AOC_EVENTS)
18258 } else if (!strcasecmp(v->name, "aoc_enable")) {
18259 confp->pri.pri.aoc_passthrough_flag = 0;
18260 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
18261 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
18262 }
18263 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
18264 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
18265 }
18266 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
18267 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
18268 }
18269 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
18270 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
18271 #endif
18272 #if defined(HAVE_PRI_CALL_HOLD)
18273 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
18274 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
18275 #endif
18276 } else if (!strcasecmp(v->name, "moh_signaling")
18277 || !strcasecmp(v->name, "moh_signalling")) {
18278 if (!strcasecmp(v->value, "moh")) {
18279 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18280 } else if (!strcasecmp(v->value, "notify")) {
18281 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_NOTIFY;
18282 #if defined(HAVE_PRI_CALL_HOLD)
18283 } else if (!strcasecmp(v->value, "hold")) {
18284 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_HOLD;
18285 #endif
18286 } else {
18287 confp->pri.pri.moh_signaling = SIG_PRI_MOH_SIGNALING_MOH;
18288 }
18289 #if defined(HAVE_PRI_CCSS)
18290 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
18291 if (!strcasecmp(v->value, "global")) {
18292 confp->pri.pri.cc_ptmp_recall_mode = 0;
18293 } else if (!strcasecmp(v->value, "specific")) {
18294 confp->pri.pri.cc_ptmp_recall_mode = 1;
18295 } else {
18296 confp->pri.pri.cc_ptmp_recall_mode = 1;
18297 }
18298 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
18299 if (!strcasecmp(v->value, "release")) {
18300 confp->pri.pri.cc_qsig_signaling_link_req = 0;
18301 } else if (!strcasecmp(v->value, "retain")) {
18302 confp->pri.pri.cc_qsig_signaling_link_req = 1;
18303 } else if (!strcasecmp(v->value, "do_not_care")) {
18304 confp->pri.pri.cc_qsig_signaling_link_req = 2;
18305 } else {
18306 confp->pri.pri.cc_qsig_signaling_link_req = 1;
18307 }
18308 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
18309 if (!strcasecmp(v->value, "release")) {
18310 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
18311 } else if (!strcasecmp(v->value, "retain")) {
18312 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
18313 } else {
18314 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
18315 }
18316 #endif
18317 #if defined(HAVE_PRI_CALL_WAITING)
18318 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
18319 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
18320 if (confp->pri.pri.max_call_waiting_calls < 0) {
18321
18322 confp->pri.pri.max_call_waiting_calls = 0;
18323 }
18324 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
18325 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
18326 #endif
18327 #if defined(HAVE_PRI_MWI)
18328 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
18329 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
18330 sizeof(confp->pri.pri.mwi_mailboxes));
18331 } else if (!strcasecmp(v->name, "mwi_vm_numbers")) {
18332 ast_copy_string(confp->pri.pri.mwi_vm_numbers, v->value,
18333 sizeof(confp->pri.pri.mwi_vm_numbers));
18334 #endif
18335 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
18336 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
18337 } else if (!strcasecmp(v->name, "inband_on_proceeding")) {
18338 confp->pri.pri.inband_on_proceeding = ast_true(v->value);
18339 #if defined(HAVE_PRI_DISPLAY_TEXT)
18340 } else if (!strcasecmp(v->name, "display_send")) {
18341 confp->pri.pri.display_flags_send = dahdi_display_text_option(v->value);
18342 } else if (!strcasecmp(v->name, "display_receive")) {
18343 confp->pri.pri.display_flags_receive = dahdi_display_text_option(v->value);
18344 #endif
18345 #if defined(HAVE_PRI_MCID)
18346 } else if (!strcasecmp(v->name, "mcid_send")) {
18347 confp->pri.pri.mcid_send = ast_true(v->value);
18348 #endif
18349 #if defined(HAVE_PRI_DATETIME_SEND)
18350 } else if (!strcasecmp(v->name, "datetime_send")) {
18351 confp->pri.pri.datetime_send = dahdi_datetime_send_option(v->value);
18352 #endif
18353 } else if (!strcasecmp(v->name, "layer1_presence")) {
18354 if (!strcasecmp(v->value, "required")) {
18355 confp->pri.pri.layer1_ignored = 0;
18356 } else if (!strcasecmp(v->value, "ignore")) {
18357 confp->pri.pri.layer1_ignored = 1;
18358 } else {
18359
18360 confp->pri.pri.layer1_ignored = 0;
18361 }
18362 #if defined(HAVE_PRI_L2_PERSISTENCE)
18363 } else if (!strcasecmp(v->name, "layer2_persistence")) {
18364 if (!strcasecmp(v->value, "keep_up")) {
18365 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
18366 } else if (!strcasecmp(v->value, "leave_down")) {
18367 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
18368 } else {
18369 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
18370 }
18371 #endif
18372 } else if (!strcasecmp(v->name, "colp_send")) {
18373 if (!strcasecmp(v->value, "block")) {
18374 confp->pri.pri.colp_send = SIG_PRI_COLP_BLOCK;
18375 } else if (!strcasecmp(v->value, "connect")) {
18376 confp->pri.pri.colp_send = SIG_PRI_COLP_CONNECT;
18377 } else if (!strcasecmp(v->value, "update")) {
18378 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18379 } else {
18380 confp->pri.pri.colp_send = SIG_PRI_COLP_UPDATE;
18381 }
18382 #endif
18383 #if defined(HAVE_SS7)
18384 } else if (!strcasecmp(v->name, "ss7type")) {
18385 if (!strcasecmp(v->value, "itu")) {
18386 cur_ss7type = SS7_ITU;
18387 } else if (!strcasecmp(v->value, "ansi")) {
18388 cur_ss7type = SS7_ANSI;
18389 } else
18390 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
18391 } else if (!strcasecmp(v->name, "linkset")) {
18392 cur_linkset = atoi(v->value);
18393 } else if (!strcasecmp(v->name, "pointcode")) {
18394 cur_pointcode = parse_pointcode(v->value);
18395 } else if (!strcasecmp(v->name, "adjpointcode")) {
18396 cur_adjpointcode = parse_pointcode(v->value);
18397 } else if (!strcasecmp(v->name, "defaultdpc")) {
18398 cur_defaultdpc = parse_pointcode(v->value);
18399 } else if (!strcasecmp(v->name, "cicbeginswith")) {
18400 cur_cicbeginswith = atoi(v->value);
18401 } else if (!strcasecmp(v->name, "networkindicator")) {
18402 if (!strcasecmp(v->value, "national"))
18403 cur_networkindicator = SS7_NI_NAT;
18404 else if (!strcasecmp(v->value, "national_spare"))
18405 cur_networkindicator = SS7_NI_NAT_SPARE;
18406 else if (!strcasecmp(v->value, "international"))
18407 cur_networkindicator = SS7_NI_INT;
18408 else if (!strcasecmp(v->value, "international_spare"))
18409 cur_networkindicator = SS7_NI_INT_SPARE;
18410 else
18411 cur_networkindicator = -1;
18412 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
18413 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
18414 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
18415 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
18416 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
18417 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
18418 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
18419 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
18420 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
18421 if (!strcasecmp(v->value, "national")) {
18422 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
18423 } else if (!strcasecmp(v->value, "international")) {
18424 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
18425 } else if (!strcasecmp(v->value, "subscriber")) {
18426 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
18427 } else if (!strcasecmp(v->value, "unknown")) {
18428 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
18429 } else if (!strcasecmp(v->value, "dynamic")) {
18430 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
18431 } else {
18432 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
18433 }
18434 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
18435 if (!strcasecmp(v->value, "national")) {
18436 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
18437 } else if (!strcasecmp(v->value, "international")) {
18438 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
18439 } else if (!strcasecmp(v->value, "subscriber")) {
18440 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
18441 } else if (!strcasecmp(v->value, "unknown")) {
18442 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
18443 } else if (!strcasecmp(v->value, "dynamic")) {
18444 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
18445 } else {
18446 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
18447 }
18448 } else if (!strcasecmp(v->name, "sigchan")) {
18449 int sigchan, res;
18450 sigchan = atoi(v->value);
18451 res = linkset_addsigchan(sigchan);
18452 if (res < 0)
18453 return -1;
18454
18455 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
18456 struct dahdi_ss7 *link;
18457 link = ss7_resolve_linkset(cur_linkset);
18458 if (!link) {
18459 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
18460 return -1;
18461 }
18462 if (ast_true(v->value))
18463 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
18464 #endif
18465 #ifdef HAVE_OPENR2
18466 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
18467 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
18468 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);
18469 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
18470 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
18471 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
18472 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
18473 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
18474 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
18475 confp->mfcr2.variant = OR2_VAR_ITU;
18476 }
18477 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
18478 confp->mfcr2.mfback_timeout = atoi(v->value);
18479 if (!confp->mfcr2.mfback_timeout) {
18480 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
18481 confp->mfcr2.mfback_timeout = -1;
18482 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
18483 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
18484 }
18485 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
18486 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
18487 if (confp->mfcr2.metering_pulse_timeout > 500) {
18488 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
18489 }
18490 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 2
18491 } else if (!strcasecmp(v->name, "mfcr2_dtmf_detection")) {
18492 confp->mfcr2.dtmf_detection = ast_true(v->value) ? 1 : 0;
18493 } else if (!strcasecmp(v->name, "mfcr2_dtmf_dialing")) {
18494 confp->mfcr2.dtmf_dialing = ast_true(v->value) ? 1 : 0;
18495 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_on")) {
18496 confp->mfcr2.dtmf_time_on = atoi(v->value);
18497 } else if (!strcasecmp(v->name, "mfcr2_dtmf_time_off")) {
18498 confp->mfcr2.dtmf_time_off = atoi(v->value);
18499 #endif
18500 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 3
18501 } else if (!strcasecmp(v->name, "mfcr2_dtmf_end_timeout")) {
18502 confp->mfcr2.dtmf_end_timeout = atoi(v->value);
18503 #endif
18504 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
18505 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
18506 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
18507 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
18508 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
18509 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
18510 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
18511 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
18512 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
18513 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
18514 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
18515 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
18516 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
18517 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
18518 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
18519 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
18520 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
18521 #endif
18522 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
18523 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
18524 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
18525 confp->mfcr2.max_ani = atoi(v->value);
18526 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
18527 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
18528 }
18529 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
18530 confp->mfcr2.max_dnis = atoi(v->value);
18531 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
18532 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
18533 }
18534 } else if (!strcasecmp(v->name, "mfcr2_category")) {
18535 confp->mfcr2.category = openr2_proto_get_category(v->value);
18536 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
18537 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
18538 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
18539 v->value, v->lineno);
18540 }
18541 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
18542 openr2_log_level_t tmplevel;
18543 char *clevel;
18544 char *logval = ast_strdupa(v->value);
18545 while (logval) {
18546 clevel = strsep(&logval,",");
18547 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
18548 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
18549 continue;
18550 }
18551 confp->mfcr2.loglevel |= tmplevel;
18552 }
18553 #endif
18554 } else if (!strcasecmp(v->name, "cadence")) {
18555
18556 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
18557 int i;
18558 struct dahdi_ring_cadence new_cadence;
18559 int cid_location = -1;
18560 int firstcadencepos = 0;
18561 char original_args[80];
18562 int cadence_is_ok = 1;
18563
18564 ast_copy_string(original_args, v->value, sizeof(original_args));
18565
18566 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]);
18567
18568
18569 if (element_count % 2 == 1) {
18570 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
18571 cadence_is_ok = 0;
18572 }
18573
18574
18575 for (i = 0; i < element_count; i++) {
18576 if (c[i] == 0) {
18577 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
18578 cadence_is_ok = 0;
18579 break;
18580 } else if (c[i] < 0) {
18581 if (i % 2 == 1) {
18582
18583 if (cid_location == -1) {
18584 cid_location = i;
18585 c[i] *= -1;
18586 } else {
18587 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
18588 cadence_is_ok = 0;
18589 break;
18590 }
18591 } else {
18592 if (firstcadencepos == 0) {
18593 firstcadencepos = i;
18594
18595 } else {
18596 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
18597 cadence_is_ok = 0;
18598 break;
18599 }
18600 }
18601 }
18602 }
18603
18604
18605 for (i = 0; i < 16; i++) {
18606 new_cadence.ringcadence[i] = c[i];
18607 }
18608
18609 if (cadence_is_ok) {
18610
18611 if (element_count < 2) {
18612 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
18613 } else {
18614 if (cid_location == -1) {
18615
18616 cid_location = 1;
18617 } else {
18618
18619 cid_location = (cid_location + 1) / 2;
18620 }
18621
18622 if (!user_has_defined_cadences++)
18623
18624 num_cadence = 0;
18625 if ((num_cadence+1) >= NUM_CADENCE_MAX)
18626 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
18627 else {
18628 cadences[num_cadence] = new_cadence;
18629 cidrings[num_cadence++] = cid_location;
18630 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
18631 }
18632 }
18633 }
18634 } else if (!strcasecmp(v->name, "ringtimeout")) {
18635 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
18636 } else if (!strcasecmp(v->name, "prewink")) {
18637 confp->timing.prewinktime = atoi(v->value);
18638 } else if (!strcasecmp(v->name, "preflash")) {
18639 confp->timing.preflashtime = atoi(v->value);
18640 } else if (!strcasecmp(v->name, "wink")) {
18641 confp->timing.winktime = atoi(v->value);
18642 } else if (!strcasecmp(v->name, "flash")) {
18643 confp->timing.flashtime = atoi(v->value);
18644 } else if (!strcasecmp(v->name, "start")) {
18645 confp->timing.starttime = atoi(v->value);
18646 } else if (!strcasecmp(v->name, "rxwink")) {
18647 confp->timing.rxwinktime = atoi(v->value);
18648 } else if (!strcasecmp(v->name, "rxflash")) {
18649 confp->timing.rxflashtime = atoi(v->value);
18650 } else if (!strcasecmp(v->name, "debounce")) {
18651 confp->timing.debouncetime = atoi(v->value);
18652 } else if (!strcasecmp(v->name, "toneduration")) {
18653 int toneduration;
18654 int ctlfd;
18655 int res;
18656 struct dahdi_dialparams dps;
18657
18658 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18659 if (ctlfd == -1) {
18660 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18661 return -1;
18662 }
18663
18664 toneduration = atoi(v->value);
18665 if (toneduration > -1) {
18666 memset(&dps, 0, sizeof(dps));
18667
18668 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18669 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18670 if (res < 0) {
18671 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18672 close(ctlfd);
18673 return -1;
18674 }
18675 }
18676 close(ctlfd);
18677 } else if (!strcasecmp(v->name, "defaultcic")) {
18678 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18679 } else if (!strcasecmp(v->name, "defaultozz")) {
18680 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18681 } else if (!strcasecmp(v->name, "mwilevel")) {
18682 mwilevel = atoi(v->value);
18683 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18684 dtmfcid_level = atoi(v->value);
18685 } else if (!strcasecmp(v->name, "reportalarms")) {
18686 if (!strcasecmp(v->value, "all"))
18687 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18688 if (!strcasecmp(v->value, "none"))
18689 report_alarms = 0;
18690 else if (!strcasecmp(v->value, "channels"))
18691 report_alarms = REPORT_CHANNEL_ALARMS;
18692 else if (!strcasecmp(v->value, "spans"))
18693 report_alarms = REPORT_SPAN_ALARMS;
18694 }
18695 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18696 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18697 }
18698
18699
18700 if (confp->chan.vars) {
18701 ast_variables_destroy(confp->chan.vars);
18702 confp->chan.vars = NULL;
18703 }
18704
18705 if (dahdichan) {
18706
18707 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18708 &found_pseudo)) {
18709 if (confp->ignore_failed_channels) {
18710 ast_log(LOG_WARNING,
18711 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18712 dahdichan->value);
18713 } else {
18714 return -1;
18715 }
18716 }
18717 }
18718
18719
18720 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18721 if (!tmp->destroy && tmp->span != y) {
18722 tmp->manages_span_alarms = 1;
18723 y = tmp->span;
18724 } else {
18725 tmp->manages_span_alarms = 0;
18726 }
18727 }
18728
18729
18730
18731 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18732
18733
18734
18735
18736 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18737
18738 if (conf.chan.cc_params) {
18739 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18740 } else {
18741 tmp = NULL;
18742 }
18743 if (tmp) {
18744 ast_verb(3, "Automatically generated pseudo channel\n");
18745 } else {
18746 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18747 }
18748 ast_cc_config_params_destroy(conf.chan.cc_params);
18749 }
18750
18751
18752 confp->chan.named_callgroups = ast_unref_namedgroups(confp->chan.named_callgroups);
18753 confp->chan.named_pickupgroups = ast_unref_namedgroups(confp->chan.named_pickupgroups);
18754
18755 return 0;
18756 }
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18769 {
18770 struct ast_cc_config_params *cc_params;
18771
18772 cc_params = dest->chan.cc_params;
18773 *dest = *src;
18774 dest->chan.cc_params = cc_params;
18775 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18776 }
18777
18778
18779
18780
18781
18782
18783
18784
18785
18786
18787
18788
18789
18790 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18791 {
18792 struct ast_config *cfg;
18793 struct ast_config *ucfg;
18794 struct ast_variable *v;
18795 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18796 const char *chans;
18797 const char *cat;
18798 int res;
18799
18800 #ifdef HAVE_PRI
18801 char *c;
18802 int spanno;
18803 int i;
18804 int logicalspan;
18805 int trunkgroup;
18806 int dchannels[SIG_PRI_NUM_DCHANS];
18807 #endif
18808 int have_cfg_now;
18809 static int had_cfg_before = 1;
18810
18811 cfg = ast_config_load(config, config_flags);
18812 have_cfg_now = !!cfg;
18813 if (!cfg) {
18814
18815 if (had_cfg_before) {
18816 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18817 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18818 }
18819 cfg = ast_config_new();
18820 if (!cfg) {
18821 return 0;
18822 }
18823 ucfg = ast_config_load("users.conf", config_flags);
18824 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18825 ast_config_destroy(cfg);
18826 return 0;
18827 }
18828 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18829 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18830 ast_config_destroy(cfg);
18831 return 0;
18832 }
18833 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18834 ucfg = ast_config_load("users.conf", config_flags);
18835 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18836 return 0;
18837 }
18838 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18839 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18840 return 0;
18841 }
18842 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18843 cfg = ast_config_load(config, config_flags);
18844 have_cfg_now = !!cfg;
18845 if (!cfg) {
18846 if (had_cfg_before) {
18847
18848 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18849 ast_config_destroy(ucfg);
18850 return 0;
18851 }
18852 cfg = ast_config_new();
18853 if (!cfg) {
18854 ast_config_destroy(ucfg);
18855 return 0;
18856 }
18857 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18858 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18859 ast_config_destroy(ucfg);
18860 return 0;
18861 }
18862 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18863 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18864 return 0;
18865 } else {
18866 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18867 ucfg = ast_config_load("users.conf", config_flags);
18868 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18869 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18870 ast_config_destroy(cfg);
18871 return 0;
18872 }
18873 }
18874 had_cfg_before = have_cfg_now;
18875
18876
18877 ast_mutex_lock(&iflock);
18878 #ifdef HAVE_PRI
18879 if (reload != 1) {
18880
18881 v = ast_variable_browse(cfg, "trunkgroups");
18882 while (v) {
18883 if (!strcasecmp(v->name, "trunkgroup")) {
18884 trunkgroup = atoi(v->value);
18885 if (trunkgroup > 0) {
18886 if ((c = strchr(v->value, ','))) {
18887 i = 0;
18888 memset(dchannels, 0, sizeof(dchannels));
18889 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18890 dchannels[i] = atoi(c + 1);
18891 if (dchannels[i] < 0) {
18892 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);
18893 } else
18894 i++;
18895 c = strchr(c + 1, ',');
18896 }
18897 if (i) {
18898 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18899 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);
18900 } else
18901 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");
18902 } else
18903 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18904 } else
18905 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18906 } else
18907 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18908 } else if (!strcasecmp(v->name, "spanmap")) {
18909 spanno = atoi(v->value);
18910 if (spanno > 0) {
18911 if ((c = strchr(v->value, ','))) {
18912 trunkgroup = atoi(c + 1);
18913 if (trunkgroup > 0) {
18914 if ((c = strchr(c + 1, ',')))
18915 logicalspan = atoi(c + 1);
18916 else
18917 logicalspan = 0;
18918 if (logicalspan >= 0) {
18919 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18920 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18921 } else
18922 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18923 } else
18924 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);
18925 } else
18926 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18927 } else
18928 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18929 } else
18930 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18931 } else {
18932 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18933 }
18934 v = v->next;
18935 }
18936 }
18937 #endif
18938
18939
18940 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18941
18942 mwimonitornotify[0] = '\0';
18943
18944 v = ast_variable_browse(cfg, "channels");
18945 if ((res = process_dahdi(base_conf,
18946 "" ,
18947 v, reload, 0))) {
18948 ast_mutex_unlock(&iflock);
18949 ast_config_destroy(cfg);
18950 if (ucfg) {
18951 ast_config_destroy(ucfg);
18952 }
18953 return res;
18954 }
18955
18956
18957 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18958
18959
18960
18961 if (!strcasecmp(cat, "general") ||
18962 !strcasecmp(cat, "trunkgroups") ||
18963 !strcasecmp(cat, "globals") ||
18964 !strcasecmp(cat, "channels")) {
18965 continue;
18966 }
18967
18968 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18969 if (ast_strlen_zero(chans)) {
18970
18971 continue;
18972 }
18973
18974
18975 deep_copy_dahdi_chan_conf(conf, base_conf);
18976
18977 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18978 ast_mutex_unlock(&iflock);
18979 ast_config_destroy(cfg);
18980 if (ucfg) {
18981 ast_config_destroy(ucfg);
18982 }
18983 return res;
18984 }
18985 }
18986
18987 ast_config_destroy(cfg);
18988
18989 if (ucfg) {
18990
18991 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18992 process_dahdi(base_conf,
18993 "" ,
18994 ast_variable_browse(ucfg, "general"), 1, 0);
18995
18996 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18997 if (!strcasecmp(cat, "general")) {
18998 continue;
18999 }
19000
19001 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
19002 if (ast_strlen_zero(chans)) {
19003
19004 continue;
19005 }
19006
19007
19008 deep_copy_dahdi_chan_conf(conf, base_conf);
19009
19010 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
19011 ast_config_destroy(ucfg);
19012 ast_mutex_unlock(&iflock);
19013 return res;
19014 }
19015 }
19016 ast_config_destroy(ucfg);
19017 }
19018 ast_mutex_unlock(&iflock);
19019
19020 #ifdef HAVE_PRI
19021 if (reload != 1) {
19022 int x;
19023 for (x = 0; x < NUM_SPANS; x++) {
19024 if (pris[x].pri.pvts[0]) {
19025 prepare_pri(pris + x);
19026 if (sig_pri_start_pri(&pris[x].pri)) {
19027 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
19028 return -1;
19029 } else
19030 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
19031 }
19032 }
19033 }
19034 #endif
19035 #if defined(HAVE_SS7)
19036 if (reload != 1) {
19037 int x;
19038 for (x = 0; x < NUM_SPANS; x++) {
19039 if (linksets[x].ss7.ss7) {
19040 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
19041 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
19042 return -1;
19043 } else
19044 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
19045 }
19046 }
19047 }
19048 #endif
19049 #ifdef HAVE_OPENR2
19050 if (reload != 1) {
19051 int x;
19052 for (x = 0; x < r2links_count; x++) {
19053 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
19054 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
19055 return -1;
19056 } else {
19057 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
19058 }
19059 }
19060 }
19061 #endif
19062
19063 restart_monitor();
19064 return 0;
19065 }
19066
19067
19068
19069
19070
19071
19072
19073
19074
19075
19076 static int setup_dahdi(int reload)
19077 {
19078 int res;
19079 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
19080 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
19081 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
19082
19083 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
19084 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
19085 } else {
19086 res = -1;
19087 }
19088 ast_cc_config_params_destroy(default_conf.chan.cc_params);
19089 ast_cc_config_params_destroy(base_conf.chan.cc_params);
19090 ast_cc_config_params_destroy(conf.chan.cc_params);
19091
19092 return res;
19093 }
19094
19095
19096
19097
19098
19099
19100
19101
19102 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
19103 struct ast_data *data_root)
19104 {
19105 int ctl, res, span;
19106 struct ast_data *data_span, *data_alarms;
19107 struct dahdi_spaninfo s;
19108
19109 ctl = open("/dev/dahdi/ctl", O_RDWR);
19110 if (ctl < 0) {
19111 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
19112 return -1;
19113 }
19114 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
19115 s.spanno = span;
19116 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
19117 if (res) {
19118 continue;
19119 }
19120
19121 data_span = ast_data_add_node(data_root, "span");
19122 if (!data_span) {
19123 continue;
19124 }
19125 ast_data_add_str(data_span, "description", s.desc);
19126
19127
19128 data_alarms = ast_data_add_node(data_span, "alarms");
19129 if (!data_alarms) {
19130 continue;
19131 }
19132
19133 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
19134 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
19135 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
19136 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
19137 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
19138 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
19139
19140 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
19141 ast_data_add_int(data_span, "bpviol", s.bpvcount);
19142 ast_data_add_int(data_span, "crc4", s.crc4count);
19143 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
19144 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
19145 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
19146 "CAS");
19147 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
19148 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
19149 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
19150 "Unknown");
19151 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
19152 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
19153 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
19154 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
19155
19156
19157 if (!ast_data_search_match(search, data_span)) {
19158 ast_data_remove_node(data_root, data_span);
19159 }
19160 }
19161 close(ctl);
19162
19163 return 0;
19164 }
19165
19166
19167
19168
19169
19170
19171
19172
19173 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
19174 struct ast_data *data_root)
19175 {
19176 struct dahdi_pvt *tmp;
19177 struct ast_data *data_channel;
19178
19179 ast_mutex_lock(&iflock);
19180 for (tmp = iflist; tmp; tmp = tmp->next) {
19181 data_channel = ast_data_add_node(data_root, "channel");
19182 if (!data_channel) {
19183 continue;
19184 }
19185
19186 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
19187
19188
19189 if (!ast_data_search_match(search, data_channel)) {
19190 ast_data_remove_node(data_root, data_channel);
19191 }
19192 }
19193 ast_mutex_unlock(&iflock);
19194
19195 return 0;
19196 }
19197
19198
19199
19200
19201
19202
19203
19204
19205 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
19206 struct ast_data *data_root)
19207 {
19208 int pseudo_fd = -1;
19209 struct dahdi_versioninfo vi = {
19210 .version = "Unknown",
19211 .echo_canceller = "Unknown"
19212 };
19213
19214 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
19215 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
19216 return -1;
19217 }
19218
19219 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
19220 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
19221 }
19222
19223 close(pseudo_fd);
19224
19225 ast_data_add_str(data_root, "value", vi.version);
19226 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
19227
19228 return 0;
19229 }
19230
19231 static const struct ast_data_handler dahdi_status_data_provider = {
19232 .version = AST_DATA_HANDLER_VERSION,
19233 .get = dahdi_status_data_provider_get
19234 };
19235
19236 static const struct ast_data_handler dahdi_channels_data_provider = {
19237 .version = AST_DATA_HANDLER_VERSION,
19238 .get = dahdi_channels_data_provider_get
19239 };
19240
19241 static const struct ast_data_handler dahdi_version_data_provider = {
19242 .version = AST_DATA_HANDLER_VERSION,
19243 .get = dahdi_version_data_provider_get
19244 };
19245
19246 static const struct ast_data_entry dahdi_data_providers[] = {
19247 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
19248 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
19249 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
19250 };
19251
19252 static int load_module(void)
19253 {
19254 int res;
19255 struct ast_format tmpfmt;
19256 #if defined(HAVE_PRI) || defined(HAVE_SS7)
19257 int y;
19258 #endif
19259
19260 if (!(dahdi_tech.capabilities = ast_format_cap_alloc())) {
19261 return AST_MODULE_LOAD_FAILURE;
19262 }
19263 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
19264 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
19265 ast_format_cap_add(dahdi_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
19266
19267 #ifdef HAVE_PRI
19268 memset(pris, 0, sizeof(pris));
19269 for (y = 0; y < NUM_SPANS; y++) {
19270 sig_pri_init_pri(&pris[y].pri);
19271 }
19272 pri_set_error(dahdi_pri_error);
19273 pri_set_message(dahdi_pri_message);
19274 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
19275 #ifdef HAVE_PRI_PROG_W_CAUSE
19276 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
19277 #endif
19278 #if defined(HAVE_PRI_CCSS)
19279 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
19280 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
19281 __unload_module();
19282 return AST_MODULE_LOAD_FAILURE;
19283 }
19284 #endif
19285 if (sig_pri_load(
19286 #if defined(HAVE_PRI_CCSS)
19287 dahdi_pri_cc_type
19288 #else
19289 NULL
19290 #endif
19291 )) {
19292 __unload_module();
19293 return AST_MODULE_LOAD_FAILURE;
19294 }
19295 #endif
19296 #if defined(HAVE_SS7)
19297 memset(linksets, 0, sizeof(linksets));
19298 for (y = 0; y < NUM_SPANS; y++) {
19299 sig_ss7_init_linkset(&linksets[y].ss7);
19300 }
19301 ss7_set_error(dahdi_ss7_error);
19302 ss7_set_message(dahdi_ss7_message);
19303 #endif
19304 res = setup_dahdi(0);
19305
19306 if (res)
19307 return AST_MODULE_LOAD_DECLINE;
19308 if (ast_channel_register(&dahdi_tech)) {
19309 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
19310 __unload_module();
19311 return AST_MODULE_LOAD_FAILURE;
19312 }
19313 #ifdef HAVE_PRI
19314 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
19315 #endif
19316 #if defined(HAVE_SS7)
19317 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
19318 #endif
19319 #ifdef HAVE_OPENR2
19320 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
19321 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
19322 #endif
19323
19324 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
19325
19326 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
19327 memset(round_robin, 0, sizeof(round_robin));
19328 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
19329 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
19330 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
19331 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
19332 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
19333 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
19334 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
19335 #if defined(HAVE_PRI)
19336 ast_manager_register_xml("PRIShowSpans", 0, action_prishowspans);
19337 #endif
19338
19339 ast_cond_init(&ss_thread_complete, NULL);
19340
19341 return res;
19342 }
19343
19344 static int dahdi_sendtext(struct ast_channel *c, const char *text)
19345 {
19346 #define END_SILENCE_LEN 400
19347 #define HEADER_MS 50
19348 #define TRAILER_MS 5
19349 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
19350 #define ASCII_BYTES_PER_CHAR 80
19351
19352 unsigned char *buf,*mybuf;
19353 struct dahdi_pvt *p = ast_channel_tech_pvt(c);
19354 struct pollfd fds[1];
19355 int size,res,fd,len,x;
19356 int bytes=0;
19357 int idx;
19358
19359
19360
19361
19362
19363
19364
19365 float cr = 1.0;
19366 float ci = 0.0;
19367 float scont = 0.0;
19368
19369 if (!text[0]) {
19370 return(0);
19371 }
19372 idx = dahdi_get_index(c, p, 0);
19373 if (idx < 0) {
19374 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
19375 return -1;
19376 }
19377 if ((!p->tdd) && (!p->mate)) {
19378 #if defined(HAVE_PRI)
19379 #if defined(HAVE_PRI_DISPLAY_TEXT)
19380 ast_mutex_lock(&p->lock);
19381 if (dahdi_sig_pri_lib_handles(p->sig)) {
19382 sig_pri_sendtext(p->sig_pvt, text);
19383 }
19384 ast_mutex_unlock(&p->lock);
19385 #endif
19386 #endif
19387 return(0);
19388 }
19389 if (p->mate)
19390 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
19391 else
19392 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
19393 if (!buf)
19394 return -1;
19395 mybuf = buf;
19396 if (p->mate) {
19397 struct ast_format tmp;
19398
19399 struct ast_format *codec = &tmp;
19400 ast_format_set(codec, AST_LAW(p), 0);
19401 for (x = 0; x < HEADER_MS; x++) {
19402 PUT_CLID_MARKMS;
19403 }
19404
19405 for (x = 0; text[x]; x++) {
19406 PUT_CLID(text[x]);
19407 }
19408 for (x = 0; x < TRAILER_MS; x++) {
19409 PUT_CLID_MARKMS;
19410 }
19411 len = bytes;
19412 buf = mybuf;
19413 } else {
19414 len = tdd_generate(p->tdd, buf, text);
19415 if (len < 1) {
19416 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
19417 ast_free(mybuf);
19418 return -1;
19419 }
19420 }
19421 memset(buf + len, 0x7f, END_SILENCE_LEN);
19422 len += END_SILENCE_LEN;
19423 fd = p->subs[idx].dfd;
19424 while (len) {
19425 if (ast_check_hangup(c)) {
19426 ast_free(mybuf);
19427 return -1;
19428 }
19429 size = len;
19430 if (size > READ_SIZE)
19431 size = READ_SIZE;
19432 fds[0].fd = fd;
19433 fds[0].events = POLLOUT | POLLPRI;
19434 fds[0].revents = 0;
19435 res = poll(fds, 1, -1);
19436 if (!res) {
19437 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
19438 continue;
19439 }
19440
19441 if (fds[0].revents & POLLPRI) {
19442 ast_free(mybuf);
19443 return -1;
19444 }
19445 if (!(fds[0].revents & POLLOUT)) {
19446 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
19447 continue;
19448 }
19449 res = write(fd, buf, size);
19450 if (res != size) {
19451 if (res == -1) {
19452 ast_free(mybuf);
19453 return -1;
19454 }
19455 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
19456 break;
19457 }
19458 len -= size;
19459 buf += size;
19460 }
19461 ast_free(mybuf);
19462 return(0);
19463 }
19464
19465
19466 static int reload(void)
19467 {
19468 int res = 0;
19469
19470 res = setup_dahdi(1);
19471 if (res) {
19472 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
19473 return -1;
19474 }
19475 return 0;
19476 }
19477
19478
19479
19480
19481
19482 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
19483 .load = load_module,
19484 .unload = unload_module,
19485 .reload = reload,
19486 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
19487 .nonoptreq = "res_smdi",
19488 );