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: 380572 $")
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 #define SMDI_MD_WAIT_TIMEOUT 1500
00282
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293
00294
00295
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298 .flags = 0,
00299 .max_size = 200,
00300 .resync_threshold = 1000,
00301 .impl = "fixed",
00302 .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 #define DEFAULT_CIDRINGS 1
00319
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321
00322
00323
00324 #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))
00325
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328 " w/"
00329 #if defined(HAVE_PRI)
00330 "PRI"
00331 #endif
00332 #if defined(HAVE_SS7)
00333 #if defined(HAVE_PRI)
00334 " & "
00335 #endif
00336 "SS7"
00337 #endif
00338 #if defined(HAVE_OPENR2)
00339 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340 " & "
00341 #endif
00342 "MFC/R2"
00343 #endif
00344 #endif
00345 ;
00346
00347 static const char config[] = "chan_dahdi.conf";
00348
00349 #define SIG_EM DAHDI_SIG_EM
00350 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00354 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00357 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI DAHDI_SIG_CLEAR
00365 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2 DAHDI_SIG_CAS
00369 #define SIG_SF DAHDI_SIG_SF
00370 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS 32
00380 #endif
00381
00382 #define CHAN_PSEUDO -2
00383
00384 #define CALLPROGRESS_PROGRESS 1
00385 #define CALLPROGRESS_FAX_OUTGOING 2
00386 #define CALLPROGRESS_FAX_INCOMING 4
00387 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394 { { 125, 125, 2000, 4000 } },
00395 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00396 { { 125, 125, 125, 125, 125, 4000 } },
00397 { { 1000, 500, 2500, 5000 } },
00398 };
00399
00400
00401
00402
00403
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405 2,
00406 4,
00407 3,
00408 2,
00409 };
00410
00411
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00419
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422
00423
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int mwisend_rpas = 0;
00427 #endif
00428
00429 static char progzone[10] = "";
00430
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433
00434 static int numbufs = 4;
00435
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS 2
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447
00448
00449 static int firstdigittimeout = 16000;
00450
00451
00452 static int gendigittimeout = 8000;
00453
00454
00455 static int matchdigittimeout = 3000;
00456
00457
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459
00460
00461 static int ifcount = 0;
00462
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466
00467
00468
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470
00471
00472
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479
00480 static int restart_monitor(void);
00481
00482 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);
00483
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488
00489
00490
00491
00492 }
00493
00494
00495 static inline int dahdi_get_event(int fd)
00496 {
00497 int j;
00498 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499 return -1;
00500 return j;
00501 }
00502
00503
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506 int i, j = 0;
00507 i = DAHDI_IOMUX_SIGEVENT;
00508 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509 return -1;
00510 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511 return -1;
00512 return j;
00513 }
00514
00515
00516 #define READ_SIZE 160
00517
00518 #define MASK_AVAIL (1 << 0)
00519 #define MASK_INUSE (1 << 1)
00520
00521 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00522 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00523 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00524 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00525 #define MIN_MS_SINCE_FLASH ((2000) )
00526 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00527
00528 struct dahdi_pvt;
00529
00530
00531
00532
00533
00534 static int ringt_base = DEFAULT_RINGT;
00535
00536 #if defined(HAVE_SS7)
00537
00538 struct dahdi_ss7 {
00539 struct sig_ss7_linkset ss7;
00540 };
00541
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif
00552
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2 {
00555 pthread_t r2master;
00556 openr2_context_t *protocol_context;
00557 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00558 int numchans;
00559 int monitored_count;
00560 };
00561
00562 struct dahdi_mfcr2_conf {
00563 openr2_variant_t variant;
00564 int mfback_timeout;
00565 int metering_pulse_timeout;
00566 int max_ani;
00567 int max_dnis;
00568 signed int get_ani_first:2;
00569 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00570 signed int skip_category_request:2;
00571 #endif
00572 unsigned int call_files:1;
00573 unsigned int allow_collect_calls:1;
00574 unsigned int charge_calls:1;
00575 unsigned int accept_on_offer:1;
00576 unsigned int forced_release:1;
00577 unsigned int double_answer:1;
00578 signed int immediate_accept:2;
00579 char logdir[OR2_MAX_PATH];
00580 char r2proto_file[OR2_MAX_PATH];
00581 openr2_log_level_t loglevel;
00582 openr2_calling_party_category_t category;
00583 };
00584
00585
00586 static struct dahdi_mfcr2 **r2links;
00587
00588 static int r2links_count = 0;
00589
00590 #endif
00591
00592 #ifdef HAVE_PRI
00593
00594 struct dahdi_pri {
00595 int dchannels[SIG_PRI_NUM_DCHANS];
00596 int mastertrunkgroup;
00597 int prilogicalspan;
00598 struct sig_pri_span pri;
00599 };
00600
00601 static struct dahdi_pri pris[NUM_SPANS];
00602
00603 #if defined(HAVE_PRI_CCSS)
00604
00605 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00606 #endif
00607
00608 #else
00609
00610 struct dahdi_pri;
00611 #endif
00612
00613 #define SUB_REAL 0
00614 #define SUB_CALLWAIT 1
00615 #define SUB_THREEWAY 2
00616
00617
00618 #define POLARITY_IDLE 0
00619 #define POLARITY_REV 1
00620
00621
00622 struct distRingData {
00623 int ring[3];
00624 int range;
00625 };
00626 struct ringContextData {
00627 char contextData[AST_MAX_CONTEXT];
00628 };
00629 struct dahdi_distRings {
00630 struct distRingData ringnum[3];
00631 struct ringContextData ringContext[3];
00632 };
00633
00634 static const char * const subnames[] = {
00635 "Real",
00636 "Callwait",
00637 "Threeway"
00638 };
00639
00640 struct dahdi_subchannel {
00641 int dfd;
00642 struct ast_channel *owner;
00643 int chan;
00644 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00645 struct ast_frame f;
00646 unsigned int needringing:1;
00647 unsigned int needbusy:1;
00648 unsigned int needcongestion:1;
00649 unsigned int needanswer:1;
00650 unsigned int needflash:1;
00651 unsigned int needhold:1;
00652 unsigned int needunhold:1;
00653 unsigned int linear:1;
00654 unsigned int inthreeway:1;
00655 struct dahdi_confinfo curconf;
00656 };
00657
00658 #define CONF_USER_REAL (1 << 0)
00659 #define CONF_USER_THIRDCALL (1 << 1)
00660
00661 #define MAX_SLAVES 4
00662
00663
00664
00665
00666 typedef enum {
00667 MWI_SEND_NULL = 0,
00668 MWI_SEND_SA,
00669 MWI_SEND_SA_WAIT,
00670 MWI_SEND_PAUSE,
00671 MWI_SEND_SPILL,
00672 MWI_SEND_CLEANUP,
00673 MWI_SEND_DONE,
00674 } mwisend_states;
00675
00676 struct mwisend_info {
00677 struct timeval pause;
00678 mwisend_states mwisend_current;
00679 };
00680
00681
00682 enum DAHDI_IFLIST {
00683 DAHDI_IFLIST_NONE,
00684 DAHDI_IFLIST_MAIN,
00685 #if defined(HAVE_PRI)
00686 DAHDI_IFLIST_NO_B_CHAN,
00687 #endif
00688 };
00689
00690 struct dahdi_pvt {
00691 ast_mutex_t lock;
00692 struct callerid_state *cs;
00693 struct ast_channel *owner;
00694
00695
00696 struct dahdi_subchannel sub_unused;
00697 struct dahdi_subchannel subs[3];
00698 struct dahdi_confinfo saveconf;
00699
00700 struct dahdi_pvt *slaves[MAX_SLAVES];
00701 struct dahdi_pvt *master;
00702 int inconference;
00703
00704 int bufsize;
00705 int buf_no;
00706 int buf_policy;
00707 int faxbuf_no;
00708 int faxbuf_policy;
00709 int sig;
00710
00711
00712
00713
00714 int radio;
00715 int outsigmod;
00716 int oprmode;
00717 struct dahdi_pvt *oprpeer;
00718
00719 float cid_rxgain;
00720
00721 float rxgain;
00722
00723 float txgain;
00724
00725 float txdrc;
00726 float rxdrc;
00727
00728 int tonezone;
00729 enum DAHDI_IFLIST which_iflist;
00730 struct dahdi_pvt *next;
00731 struct dahdi_pvt *prev;
00732
00733
00734
00735
00736
00737
00738
00739 unsigned int adsi:1;
00740
00741
00742
00743
00744
00745 unsigned int answeronpolarityswitch:1;
00746
00747
00748
00749
00750
00751 unsigned int busydetect:1;
00752
00753
00754
00755
00756
00757 unsigned int callreturn:1;
00758
00759
00760
00761
00762
00763
00764 unsigned int callwaiting:1;
00765
00766
00767
00768
00769 unsigned int callwaitingcallerid:1;
00770
00771
00772
00773
00774
00775
00776 unsigned int cancallforward:1;
00777
00778
00779
00780
00781 unsigned int canpark:1;
00782
00783 unsigned int confirmanswer:1;
00784
00785
00786
00787
00788 unsigned int destroy:1;
00789 unsigned int didtdd:1;
00790
00791 unsigned int dialednone:1;
00792
00793
00794
00795
00796 unsigned int dialing:1;
00797
00798 unsigned int digital:1;
00799
00800 unsigned int dnd:1;
00801
00802 unsigned int echobreak:1;
00803
00804
00805
00806
00807
00808 unsigned int echocanbridged:1;
00809
00810 unsigned int echocanon:1;
00811
00812 unsigned int faxhandled:1;
00813
00814 unsigned int usefaxbuffers:1;
00815
00816 unsigned int bufferoverrideinuse:1;
00817
00818 unsigned int firstradio:1;
00819
00820
00821
00822
00823 unsigned int hanguponpolarityswitch:1;
00824
00825 unsigned int hardwaredtmf:1;
00826
00827
00828
00829
00830
00831
00832 unsigned int hidecallerid:1;
00833
00834
00835
00836
00837
00838 unsigned int hidecalleridname:1;
00839
00840 unsigned int ignoredtmf:1;
00841
00842
00843
00844
00845
00846 unsigned int immediate:1;
00847
00848 unsigned int inalarm:1;
00849
00850 unsigned int mate:1;
00851
00852 unsigned int outgoing:1;
00853
00854
00855
00856
00857
00858
00859 unsigned int permcallwaiting:1;
00860
00861
00862
00863
00864 unsigned int permhidecallerid:1;
00865
00866
00867
00868
00869 unsigned int priindication_oob:1;
00870
00871
00872
00873
00874 unsigned int priexclusive:1;
00875
00876
00877
00878
00879 unsigned int pulse:1;
00880
00881 unsigned int pulsedial:1;
00882 unsigned int restartpending:1;
00883
00884
00885
00886
00887
00888 unsigned int restrictcid:1;
00889
00890
00891
00892
00893 unsigned int threewaycalling:1;
00894
00895
00896
00897
00898
00899
00900
00901
00902 unsigned int transfer:1;
00903
00904
00905
00906
00907
00908
00909
00910 unsigned int use_callerid:1;
00911
00912
00913
00914
00915
00916
00917 unsigned int use_callingpres:1;
00918
00919
00920
00921
00922
00923 unsigned int usedistinctiveringdetection:1;
00924
00925
00926
00927
00928 unsigned int dahditrcallerid:1;
00929
00930
00931
00932
00933 unsigned int transfertobusy:1;
00934
00935
00936
00937
00938 unsigned int mwimonitor_neon:1;
00939
00940
00941
00942
00943 unsigned int mwimonitor_fsk:1;
00944
00945
00946
00947
00948
00949 unsigned int mwimonitor_rpas:1;
00950
00951 unsigned int mwimonitoractive:1;
00952
00953 unsigned int mwisendactive:1;
00954
00955
00956
00957
00958 unsigned int inservice:1;
00959
00960
00961
00962
00963 unsigned int locallyblocked:1;
00964
00965
00966
00967
00968 unsigned int remotelyblocked:1;
00969
00970
00971
00972
00973 unsigned int manages_span_alarms:1;
00974
00975 #if defined(HAVE_PRI)
00976 struct sig_pri_span *pri;
00977 int logicalspan;
00978 #endif
00979
00980
00981
00982
00983 unsigned int use_smdi:1;
00984 struct mwisend_info mwisend_data;
00985
00986 struct ast_smdi_interface *smdi_iface;
00987
00988
00989 struct dahdi_distRings drings;
00990
00991
00992
00993
00994
00995 char context[AST_MAX_CONTEXT];
00996
00997
00998
00999 char defcontext[AST_MAX_CONTEXT];
01000
01001 char exten[AST_MAX_EXTENSION];
01002
01003
01004
01005
01006 char language[MAX_LANGUAGE];
01007
01008
01009
01010
01011 char mohinterpret[MAX_MUSICCLASS];
01012
01013
01014
01015
01016 char mohsuggest[MAX_MUSICCLASS];
01017 char parkinglot[AST_MAX_EXTENSION];
01018 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01019
01020 char cid_ani[AST_MAX_EXTENSION];
01021 #endif
01022
01023 int cid_ani2;
01024
01025 char cid_num[AST_MAX_EXTENSION];
01026
01027
01028
01029
01030 char cid_tag[AST_MAX_EXTENSION];
01031
01032 int cid_ton;
01033
01034 char cid_name[AST_MAX_EXTENSION];
01035
01036 char cid_subaddr[AST_MAX_EXTENSION];
01037 char *origcid_num;
01038 char *origcid_name;
01039
01040 char callwait_num[AST_MAX_EXTENSION];
01041
01042 char callwait_name[AST_MAX_EXTENSION];
01043
01044 char rdnis[AST_MAX_EXTENSION];
01045
01046 char dnid[AST_MAX_EXTENSION];
01047
01048
01049
01050
01051 ast_group_t group;
01052
01053 int law_default;
01054
01055 int law;
01056 int confno;
01057 int confusers;
01058 int propconfno;
01059
01060
01061
01062
01063 ast_group_t callgroup;
01064
01065
01066
01067
01068 ast_group_t pickupgroup;
01069
01070
01071
01072
01073 struct ast_variable *vars;
01074 int channel;
01075 int span;
01076 time_t guardtime;
01077 int cid_signalling;
01078 int cid_start;
01079 int dtmfcid_holdoff_state;
01080 struct timeval dtmfcid_delay;
01081 int callingpres;
01082 int callwaitingrepeat;
01083 int cidcwexpire;
01084 int cid_suppress_expire;
01085
01086 unsigned char *cidspill;
01087
01088 int cidpos;
01089
01090 int cidlen;
01091
01092 int ringt;
01093
01094
01095
01096
01097 int ringt_base;
01098
01099
01100
01101
01102
01103
01104 int stripmsd;
01105
01106
01107
01108
01109
01110
01111 int callwaitcas;
01112
01113 int callwaitrings;
01114
01115 struct {
01116 struct dahdi_echocanparams head;
01117 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01118 } echocancel;
01119
01120
01121
01122
01123 int echotraining;
01124
01125 char echorest[20];
01126
01127
01128
01129
01130 int busycount;
01131
01132
01133
01134
01135 int busycompare;
01136
01137
01138
01139
01140 int busytonelength;
01141
01142
01143
01144
01145 int busyquietlength;
01146
01147
01148
01149
01150 int busyfuzziness;
01151
01152
01153
01154
01155 int silencethreshold;
01156
01157
01158
01159
01160 int callprogress;
01161
01162
01163
01164
01165 int waitfordialtone;
01166 struct timeval waitingfordt;
01167 struct timeval flashtime;
01168
01169 struct ast_dsp *dsp;
01170
01171 struct dahdi_dialoperation dop;
01172 int whichwink;
01173
01174 char finaldial[64];
01175 char accountcode[AST_MAX_ACCOUNT_CODE];
01176 int amaflags;
01177 struct tdd_state *tdd;
01178
01179 char call_forward[AST_MAX_EXTENSION];
01180
01181
01182
01183
01184 char mailbox[AST_MAX_EXTENSION];
01185
01186 struct ast_event_sub *mwi_event_sub;
01187
01188 char dialdest[256];
01189 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01190 struct dahdi_vmwi_info mwisend_setting;
01191 unsigned int mwisend_fsk: 1;
01192 unsigned int mwisend_rpas:1;
01193 #endif
01194 int distinctivering;
01195 int dtmfrelax;
01196
01197 int fake_event;
01198
01199
01200
01201
01202 int polarityonanswerdelay;
01203
01204 struct timeval polaritydelaytv;
01205
01206
01207
01208
01209 int sendcalleridafter;
01210
01211 int polarity;
01212
01213 int dsp_features;
01214 #if defined(HAVE_SS7)
01215
01216 struct sig_ss7_linkset *ss7;
01217 #endif
01218 #ifdef HAVE_OPENR2
01219 struct dahdi_mfcr2 *mfcr2;
01220 openr2_chan_t *r2chan;
01221 openr2_calling_party_category_t mfcr2_recvd_category;
01222 openr2_calling_party_category_t mfcr2_category;
01223 int mfcr2_dnis_index;
01224 int mfcr2_ani_index;
01225 int mfcr2call:1;
01226 int mfcr2_answer_pending:1;
01227 int mfcr2_charge_calls:1;
01228 int mfcr2_allow_collect_calls:1;
01229 int mfcr2_forced_release:1;
01230 int mfcr2_dnis_matched:1;
01231 int mfcr2_call_accepted:1;
01232 int mfcr2_progress:1;
01233 int mfcr2_accept_on_offer:1;
01234 #endif
01235
01236 char begindigit;
01237
01238 int muting;
01239 void *sig_pvt;
01240 struct ast_cc_config_params *cc_params;
01241
01242
01243
01244
01245
01246
01247 char dialstring[AST_CHANNEL_NAME];
01248 };
01249
01250 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01251 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01252 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01253 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01254 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01255 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01256 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01297 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01298 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01299 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01300 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01301 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01302 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01303 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01304 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01305 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01306 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01307 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01308 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01309 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01310 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01311 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01312 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01313 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01314 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01315 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01316 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01317 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01318
01319 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01320
01321 static struct dahdi_pvt *iflist = NULL;
01322 static struct dahdi_pvt *ifend = NULL;
01323
01324 #if defined(HAVE_PRI)
01325 static struct dahdi_parms_pseudo {
01326 int buf_no;
01327 int buf_policy;
01328 int faxbuf_no;
01329 int faxbuf_policy;
01330 } dahdi_pseudo_parms;
01331 #endif
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343 struct dahdi_chan_conf {
01344 struct dahdi_pvt chan;
01345 #ifdef HAVE_PRI
01346 struct dahdi_pri pri;
01347 #endif
01348
01349 #if defined(HAVE_SS7)
01350 struct dahdi_ss7 ss7;
01351 #endif
01352
01353 #ifdef HAVE_OPENR2
01354 struct dahdi_mfcr2_conf mfcr2;
01355 #endif
01356 struct dahdi_params timing;
01357 int is_sig_auto;
01358
01359 int ignore_failed_channels;
01360
01361
01362
01363
01364
01365 char smdi_port[SMDI_MAX_FILENAME_LEN];
01366 };
01367
01368
01369 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01370 {
01371
01372
01373
01374 struct dahdi_chan_conf conf = {
01375 #ifdef HAVE_PRI
01376 .pri.pri = {
01377 .nsf = PRI_NSF_NONE,
01378 .switchtype = PRI_SWITCH_NI2,
01379 .dialplan = PRI_UNKNOWN + 1,
01380 .localdialplan = PRI_NATIONAL_ISDN + 1,
01381 .nodetype = PRI_CPE,
01382 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01383
01384 #if defined(HAVE_PRI_CCSS)
01385 .cc_ptmp_recall_mode = 1,
01386 .cc_qsig_signaling_link_req = 1,
01387 .cc_qsig_signaling_link_rsp = 1,
01388 #endif
01389
01390 .minunused = 2,
01391 .idleext = "",
01392 .idledial = "",
01393 .internationalprefix = "",
01394 .nationalprefix = "",
01395 .localprefix = "",
01396 .privateprefix = "",
01397 .unknownprefix = "",
01398 .resetinterval = -1,
01399 },
01400 #endif
01401 #if defined(HAVE_SS7)
01402 .ss7.ss7 = {
01403 .called_nai = SS7_NAI_NATIONAL,
01404 .calling_nai = SS7_NAI_NATIONAL,
01405 .internationalprefix = "",
01406 .nationalprefix = "",
01407 .subscriberprefix = "",
01408 .unknownprefix = ""
01409 },
01410 #endif
01411 #ifdef HAVE_OPENR2
01412 .mfcr2 = {
01413 .variant = OR2_VAR_ITU,
01414 .mfback_timeout = -1,
01415 .metering_pulse_timeout = -1,
01416 .max_ani = 10,
01417 .max_dnis = 4,
01418 .get_ani_first = -1,
01419 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01420 .skip_category_request = -1,
01421 #endif
01422 .call_files = 0,
01423 .allow_collect_calls = 0,
01424 .charge_calls = 1,
01425 .accept_on_offer = 1,
01426 .forced_release = 0,
01427 .double_answer = 0,
01428 .immediate_accept = -1,
01429 .logdir = "",
01430 .r2proto_file = "",
01431 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01432 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01433 },
01434 #endif
01435 .chan = {
01436 .context = "default",
01437 .cid_num = "",
01438 .cid_name = "",
01439 .cid_tag = "",
01440 .mohinterpret = "default",
01441 .mohsuggest = "",
01442 .parkinglot = "",
01443 .transfertobusy = 1,
01444
01445 .cid_signalling = CID_SIG_BELL,
01446 .cid_start = CID_START_RING,
01447 .dahditrcallerid = 0,
01448 .use_callerid = 1,
01449 .sig = -1,
01450 .outsigmod = -1,
01451
01452 .cid_rxgain = +5.0,
01453
01454 .tonezone = -1,
01455
01456 .echocancel.head.tap_length = 1,
01457
01458 .busycount = 3,
01459 .busycompare = 0,
01460 .busytonelength = 0,
01461 .busyquietlength = 0,
01462 .busyfuzziness = 0,
01463 .silencethreshold = 0,
01464
01465 .accountcode = "",
01466
01467 .mailbox = "",
01468
01469 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01470 .mwisend_fsk = 1,
01471 #endif
01472 .polarityonanswerdelay = 600,
01473
01474 .sendcalleridafter = DEFAULT_CIDRINGS,
01475
01476 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01477 .buf_no = numbufs,
01478 .usefaxbuffers = 0,
01479 .cc_params = ast_cc_config_params_init(),
01480 },
01481 .timing = {
01482 .prewinktime = -1,
01483 .preflashtime = -1,
01484 .winktime = -1,
01485 .flashtime = -1,
01486 .starttime = -1,
01487 .rxwinktime = -1,
01488 .rxflashtime = -1,
01489 .debouncetime = -1
01490 },
01491 .is_sig_auto = 1,
01492 .smdi_port = "/dev/ttyS0",
01493 };
01494
01495 return conf;
01496 }
01497
01498
01499 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01500 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01501 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01502 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01503 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01504 static int dahdi_hangup(struct ast_channel *ast);
01505 static int dahdi_answer(struct ast_channel *ast);
01506 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01507 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01508 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01509 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01510 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01511 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01512 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01513 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01514 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01515 static int dahdi_devicestate(void *data);
01516 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01517
01518 static const struct ast_channel_tech dahdi_tech = {
01519 .type = "DAHDI",
01520 .description = tdesc,
01521 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01522 .requester = dahdi_request,
01523 .send_digit_begin = dahdi_digit_begin,
01524 .send_digit_end = dahdi_digit_end,
01525 .send_text = dahdi_sendtext,
01526 .call = dahdi_call,
01527 .hangup = dahdi_hangup,
01528 .answer = dahdi_answer,
01529 .read = dahdi_read,
01530 .write = dahdi_write,
01531 .bridge = dahdi_bridge,
01532 .exception = dahdi_exception,
01533 .indicate = dahdi_indicate,
01534 .fixup = dahdi_fixup,
01535 .setoption = dahdi_setoption,
01536 .queryoption = dahdi_queryoption,
01537 .func_channel_read = dahdi_func_read,
01538 .func_channel_write = dahdi_func_write,
01539 .devicestate = dahdi_devicestate,
01540 .cc_callback = dahdi_cc_callback,
01541 };
01542
01543 #define GET_CHANNEL(p) ((p)->channel)
01544
01545 #define SIG_PRI_LIB_HANDLE_CASES \
01546 SIG_PRI: \
01547 case SIG_BRI: \
01548 case SIG_BRI_PTMP
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559 static inline int dahdi_sig_pri_lib_handles(int signaling)
01560 {
01561 int handles;
01562
01563 switch (signaling) {
01564 case SIG_PRI_LIB_HANDLE_CASES:
01565 handles = 1;
01566 break;
01567 default:
01568 handles = 0;
01569 break;
01570 }
01571
01572 return handles;
01573 }
01574
01575 static int analog_lib_handles(int signalling, int radio, int oprmode)
01576 {
01577 switch (signalling) {
01578 case SIG_FXOLS:
01579 case SIG_FXOGS:
01580 case SIG_FXOKS:
01581 case SIG_FXSLS:
01582 case SIG_FXSGS:
01583 case SIG_FXSKS:
01584 case SIG_EMWINK:
01585 case SIG_EM:
01586 case SIG_EM_E1:
01587 case SIG_FEATD:
01588 case SIG_FEATDMF:
01589 case SIG_E911:
01590 case SIG_FGC_CAMA:
01591 case SIG_FGC_CAMAMF:
01592 case SIG_FEATB:
01593 case SIG_SFWINK:
01594 case SIG_SF:
01595 case SIG_SF_FEATD:
01596 case SIG_SF_FEATDMF:
01597 case SIG_FEATDMF_TA:
01598 case SIG_SF_FEATB:
01599 break;
01600 default:
01601
01602 return 0;
01603 }
01604
01605 if (radio) {
01606 return 0;
01607 }
01608
01609 if (oprmode) {
01610 return 0;
01611 }
01612
01613 return 1;
01614 }
01615
01616 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01617 {
01618 switch (sig) {
01619 case SIG_FXOLS:
01620 return ANALOG_SIG_FXOLS;
01621 case SIG_FXOGS:
01622 return ANALOG_SIG_FXOGS;
01623 case SIG_FXOKS:
01624 return ANALOG_SIG_FXOKS;
01625 case SIG_FXSLS:
01626 return ANALOG_SIG_FXSLS;
01627 case SIG_FXSGS:
01628 return ANALOG_SIG_FXSGS;
01629 case SIG_FXSKS:
01630 return ANALOG_SIG_FXSKS;
01631 case SIG_EMWINK:
01632 return ANALOG_SIG_EMWINK;
01633 case SIG_EM:
01634 return ANALOG_SIG_EM;
01635 case SIG_EM_E1:
01636 return ANALOG_SIG_EM_E1;
01637 case SIG_FEATD:
01638 return ANALOG_SIG_FEATD;
01639 case SIG_FEATDMF:
01640 return ANALOG_SIG_FEATDMF;
01641 case SIG_E911:
01642 return SIG_E911;
01643 case SIG_FGC_CAMA:
01644 return ANALOG_SIG_FGC_CAMA;
01645 case SIG_FGC_CAMAMF:
01646 return ANALOG_SIG_FGC_CAMAMF;
01647 case SIG_FEATB:
01648 return ANALOG_SIG_FEATB;
01649 case SIG_SFWINK:
01650 return ANALOG_SIG_SFWINK;
01651 case SIG_SF:
01652 return ANALOG_SIG_SF;
01653 case SIG_SF_FEATD:
01654 return ANALOG_SIG_SF_FEATD;
01655 case SIG_SF_FEATDMF:
01656 return ANALOG_SIG_SF_FEATDMF;
01657 case SIG_FEATDMF_TA:
01658 return ANALOG_SIG_FEATDMF_TA;
01659 case SIG_SF_FEATB:
01660 return ANALOG_SIG_FEATB;
01661 default:
01662 return -1;
01663 }
01664 }
01665
01666
01667 static int analog_tone_to_dahditone(enum analog_tone tone)
01668 {
01669 switch (tone) {
01670 case ANALOG_TONE_RINGTONE:
01671 return DAHDI_TONE_RINGTONE;
01672 case ANALOG_TONE_STUTTER:
01673 return DAHDI_TONE_STUTTER;
01674 case ANALOG_TONE_CONGESTION:
01675 return DAHDI_TONE_CONGESTION;
01676 case ANALOG_TONE_DIALTONE:
01677 return DAHDI_TONE_DIALTONE;
01678 case ANALOG_TONE_DIALRECALL:
01679 return DAHDI_TONE_DIALRECALL;
01680 case ANALOG_TONE_INFO:
01681 return DAHDI_TONE_INFO;
01682 default:
01683 return -1;
01684 }
01685 }
01686
01687 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01688 {
01689 int index;
01690
01691 switch (analogsub) {
01692 case ANALOG_SUB_REAL:
01693 index = SUB_REAL;
01694 break;
01695 case ANALOG_SUB_CALLWAIT:
01696 index = SUB_CALLWAIT;
01697 break;
01698 case ANALOG_SUB_THREEWAY:
01699 index = SUB_THREEWAY;
01700 break;
01701 default:
01702 ast_log(LOG_ERROR, "Unidentified sub!\n");
01703 index = SUB_REAL;
01704 }
01705
01706 return index;
01707 }
01708
01709 static enum analog_event dahdievent_to_analogevent(int event);
01710 static int bump_gains(struct dahdi_pvt *p);
01711 static int dahdi_setlinear(int dfd, int linear);
01712
01713 static int my_start_cid_detect(void *pvt, int cid_signalling)
01714 {
01715 struct dahdi_pvt *p = pvt;
01716 int index = SUB_REAL;
01717 p->cs = callerid_new(cid_signalling);
01718 if (!p->cs) {
01719 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01720 return -1;
01721 }
01722 bump_gains(p);
01723 dahdi_setlinear(p->subs[index].dfd, 0);
01724
01725 return 0;
01726 }
01727
01728 static int my_stop_cid_detect(void *pvt)
01729 {
01730 struct dahdi_pvt *p = pvt;
01731 int index = SUB_REAL;
01732 if (p->cs)
01733 callerid_free(p->cs);
01734 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01735 return 0;
01736 }
01737
01738 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01739 {
01740 struct dahdi_pvt *p = pvt;
01741 struct analog_pvt *analog_p = p->sig_pvt;
01742 struct pollfd poller;
01743 char *name, *num;
01744 int index = SUB_REAL;
01745 int res;
01746 unsigned char buf[256];
01747 int flags;
01748
01749 poller.fd = p->subs[SUB_REAL].dfd;
01750 poller.events = POLLPRI | POLLIN;
01751 poller.revents = 0;
01752
01753 res = poll(&poller, 1, timeout);
01754
01755 if (poller.revents & POLLPRI) {
01756 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01757 return 1;
01758 }
01759
01760 if (poller.revents & POLLIN) {
01761
01762
01763
01764
01765
01766 res = read(p->subs[index].dfd, buf, sizeof(buf));
01767 if (res < 0) {
01768 if (errno != ELAST) {
01769 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01770 callerid_free(p->cs);
01771 return -1;
01772 }
01773 }
01774
01775 if (analog_p->ringt > 0) {
01776 if (!(--analog_p->ringt)) {
01777
01778 return -1;
01779 }
01780 }
01781
01782 if (p->cid_signalling == CID_SIG_V23_JP) {
01783 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01784 } else {
01785 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01786 }
01787 if (res < 0) {
01788
01789
01790
01791
01792 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01793 return -1;
01794 }
01795
01796 if (res == 1) {
01797 callerid_get(p->cs, &name, &num, &flags);
01798 if (name)
01799 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01800 if (num)
01801 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01802
01803 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01804 return 0;
01805 }
01806 }
01807
01808 *ev = ANALOG_EVENT_NONE;
01809 return 2;
01810 }
01811
01812 static const char *event2str(int event);
01813 static int restore_gains(struct dahdi_pvt *p);
01814
01815 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01816 {
01817 unsigned char buf[256];
01818 int distMatches;
01819 int curRingData[RING_PATTERNS];
01820 int receivedRingT;
01821 int counter1;
01822 int counter;
01823 int i;
01824 int res;
01825 int checkaftercid = 0;
01826
01827 struct dahdi_pvt *p = pvt;
01828 struct analog_pvt *analog_p = p->sig_pvt;
01829
01830 if (ringdata == NULL) {
01831 ringdata = curRingData;
01832 } else {
01833 checkaftercid = 1;
01834 }
01835
01836
01837
01838 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01839
01840 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01841 ringdata[receivedRingT] = 0;
01842 receivedRingT = 0;
01843 if (checkaftercid && distinctiveringaftercid)
01844 ast_verb(3, "Detecting post-CID distinctive ring\n");
01845
01846 else if (strcmp(p->context,p->defcontext) != 0) {
01847 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01848 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01849 }
01850
01851 for (;;) {
01852 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01853 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01854 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01855 ast_hangup(chan);
01856 return 1;
01857 }
01858 if (i & DAHDI_IOMUX_SIGEVENT) {
01859 res = dahdi_get_event(p->subs[idx].dfd);
01860 if (res == DAHDI_EVENT_NOALARM) {
01861 p->inalarm = 0;
01862 analog_p->inalarm = 0;
01863 }
01864 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01865 res = 0;
01866
01867
01868 ringdata[receivedRingT] = analog_p->ringt;
01869
01870 if (analog_p->ringt < analog_p->ringt_base/2)
01871 break;
01872
01873
01874 if (++receivedRingT == RING_PATTERNS)
01875 break;
01876 } else if (i & DAHDI_IOMUX_READ) {
01877 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01878 if (res < 0) {
01879 if (errno != ELAST) {
01880 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01881 ast_hangup(chan);
01882 return 1;
01883 }
01884 break;
01885 }
01886 if (analog_p->ringt > 0) {
01887 if (!(--analog_p->ringt)) {
01888 res = -1;
01889 break;
01890 }
01891 }
01892 }
01893 }
01894 }
01895 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01896
01897 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01898 for (counter = 0; counter < 3; counter++) {
01899
01900 distMatches = 0;
01901
01902 ast_verb(3, "Checking %d,%d,%d\n",
01903 p->drings.ringnum[counter].ring[0],
01904 p->drings.ringnum[counter].ring[1],
01905 p->drings.ringnum[counter].ring[2]);
01906 for (counter1 = 0; counter1 < 3; counter1++) {
01907 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01908 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01909 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01910 ringdata[counter1]);
01911 distMatches++;
01912 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01913 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01914 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01915 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01916 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01917 distMatches++;
01918 }
01919 }
01920
01921 if (distMatches == 3) {
01922
01923 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01924 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01925 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01926 break;
01927 }
01928 }
01929 }
01930
01931 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01932 restore_gains(p);
01933
01934 return 0;
01935 }
01936
01937 static int my_stop_callwait(void *pvt)
01938 {
01939 struct dahdi_pvt *p = pvt;
01940 p->callwaitingrepeat = 0;
01941 p->cidcwexpire = 0;
01942 p->cid_suppress_expire = 0;
01943
01944 return 0;
01945 }
01946
01947 static int send_callerid(struct dahdi_pvt *p);
01948 static int save_conference(struct dahdi_pvt *p);
01949 static int restore_conference(struct dahdi_pvt *p);
01950
01951 static int my_callwait(void *pvt)
01952 {
01953 struct dahdi_pvt *p = pvt;
01954 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01955 if (p->cidspill) {
01956 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01957 ast_free(p->cidspill);
01958 }
01959
01960
01961
01962
01963
01964 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01965 return -1;
01966 save_conference(p);
01967
01968 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01969 if (!p->callwaitrings && p->callwaitingcallerid) {
01970 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01971 p->callwaitcas = 1;
01972 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01973 } else {
01974 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01975 p->callwaitcas = 0;
01976 p->cidlen = 2400 + READ_SIZE * 4;
01977 }
01978 p->cidpos = 0;
01979 send_callerid(p);
01980
01981 return 0;
01982 }
01983
01984 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01985 {
01986 struct dahdi_pvt *p = pvt;
01987
01988 ast_debug(2, "Starting cid spill\n");
01989
01990 if (p->cidspill) {
01991 ast_log(LOG_WARNING, "cidspill already exists??\n");
01992 ast_free(p->cidspill);
01993 }
01994
01995 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01996 if (cwcid == 0) {
01997 p->cidlen = ast_callerid_generate(p->cidspill,
01998 caller->id.name.str,
01999 caller->id.number.str,
02000 AST_LAW(p));
02001 } else {
02002 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
02003 caller->id.name.str, caller->id.number.str);
02004 p->callwaitcas = 0;
02005 p->cidcwexpire = 0;
02006 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
02007 caller->id.name.str,
02008 caller->id.number.str,
02009 AST_LAW(p));
02010 p->cidlen += READ_SIZE * 4;
02011 }
02012 p->cidpos = 0;
02013 p->cid_suppress_expire = 0;
02014 send_callerid(p);
02015 }
02016 return 0;
02017 }
02018
02019 static int my_dsp_reset_and_flush_digits(void *pvt)
02020 {
02021 struct dahdi_pvt *p = pvt;
02022 if (p->dsp)
02023 ast_dsp_digitreset(p->dsp);
02024
02025 return 0;
02026 }
02027
02028 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02029 {
02030 struct dahdi_pvt *p = pvt;
02031
02032 if (p->channel == CHAN_PSEUDO)
02033 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02034
02035 if (mode == ANALOG_DIGITMODE_DTMF) {
02036
02037 if (p->hardwaredtmf) {
02038 if (p->dsp) {
02039 ast_dsp_free(p->dsp);
02040 p->dsp = NULL;
02041 }
02042 return 0;
02043 }
02044
02045 if (!p->dsp) {
02046 p->dsp = ast_dsp_new();
02047 if (!p->dsp) {
02048 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02049 return -1;
02050 }
02051 }
02052
02053 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02054 } else if (mode == ANALOG_DIGITMODE_MF) {
02055 if (!p->dsp) {
02056 p->dsp = ast_dsp_new();
02057 if (!p->dsp) {
02058 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02059 return -1;
02060 }
02061 }
02062 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02063 }
02064 return 0;
02065 }
02066
02067 static int dahdi_wink(struct dahdi_pvt *p, int index);
02068
02069 static int my_wink(void *pvt, enum analog_sub sub)
02070 {
02071 struct dahdi_pvt *p = pvt;
02072 int index = analogsub_to_dahdisub(sub);
02073 if (index != SUB_REAL) {
02074 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02075 }
02076 return dahdi_wink(p, index);
02077 }
02078
02079 static void wakeup_sub(struct dahdi_pvt *p, int a);
02080
02081 static int reset_conf(struct dahdi_pvt *p);
02082
02083 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02084
02085 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02086 {
02087 struct ast_frame *f = *dest;
02088 struct dahdi_pvt *p = pvt;
02089 int idx = analogsub_to_dahdisub(analog_index);
02090
02091 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02092 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02093 f->subclass.integer, f->subclass.integer, ast->name);
02094
02095 if (f->subclass.integer == 'f') {
02096 if (f->frametype == AST_FRAME_DTMF_END) {
02097
02098 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02099
02100 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02101 struct dahdi_bufferinfo bi = {
02102 .txbufpolicy = p->faxbuf_policy,
02103 .bufsize = p->bufsize,
02104 .numbufs = p->faxbuf_no
02105 };
02106 int res;
02107
02108 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02109 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02110 } else {
02111 p->bufferoverrideinuse = 1;
02112 }
02113 }
02114 p->faxhandled = 1;
02115 if (p->dsp) {
02116 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02117 ast_dsp_set_features(p->dsp, p->dsp_features);
02118 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02119 }
02120 if (strcmp(ast->exten, "fax")) {
02121 const char *target_context = S_OR(ast->macrocontext, ast->context);
02122
02123
02124
02125
02126
02127 ast_mutex_unlock(&p->lock);
02128 ast_channel_unlock(ast);
02129 if (ast_exists_extension(ast, target_context, "fax", 1,
02130 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02131 ast_channel_lock(ast);
02132 ast_mutex_lock(&p->lock);
02133 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02134
02135 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02136 if (ast_async_goto(ast, target_context, "fax", 1))
02137 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02138 } else {
02139 ast_channel_lock(ast);
02140 ast_mutex_lock(&p->lock);
02141 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02142 }
02143 } else {
02144 ast_debug(1, "Already in a fax extension, not redirecting\n");
02145 }
02146 } else {
02147 ast_debug(1, "Fax already handled\n");
02148 }
02149 dahdi_confmute(p, 0);
02150 }
02151 p->subs[idx].f.frametype = AST_FRAME_NULL;
02152 p->subs[idx].f.subclass.integer = 0;
02153 *dest = &p->subs[idx].f;
02154 }
02155 }
02156
02157 static void my_lock_private(void *pvt)
02158 {
02159 struct dahdi_pvt *p = pvt;
02160 ast_mutex_lock(&p->lock);
02161 }
02162
02163 static void my_unlock_private(void *pvt)
02164 {
02165 struct dahdi_pvt *p = pvt;
02166 ast_mutex_unlock(&p->lock);
02167 }
02168
02169 static void my_deadlock_avoidance_private(void *pvt)
02170 {
02171 struct dahdi_pvt *p = pvt;
02172
02173 DEADLOCK_AVOIDANCE(&p->lock);
02174 }
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02187 {
02188 char ch_name[20];
02189
02190 if (p->channel < CHAN_PSEUDO) {
02191
02192 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02193 } else if (p->channel == CHAN_PSEUDO) {
02194
02195 strcpy(ch_name, "pseudo");
02196 } else {
02197
02198 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02199 }
02200 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02201 "Channel: %s\r\n"
02202 "Uniqueid: %s\r\n"
02203 "DAHDISpan: %d\r\n"
02204 "DAHDIChannel: %s\r\n",
02205 chan->name,
02206 chan->uniqueid,
02207 p->span,
02208 ch_name);
02209 }
02210
02211 #ifdef HAVE_PRI
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02223 {
02224 struct dahdi_pvt *p = pvt;
02225
02226 dahdi_ami_channel_event(p, chan);
02227 }
02228 #endif
02229
02230
02231
02232
02233 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02234 {
02235 struct dahdi_pvt *p = pvt;
02236 int oldval;
02237 int idx = analogsub_to_dahdisub(sub);
02238
02239 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02240 oldval = p->subs[idx].linear;
02241 p->subs[idx].linear = linear_mode ? 1 : 0;
02242 return oldval;
02243 }
02244
02245 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02246 {
02247 struct dahdi_pvt *p = pvt;
02248 int idx = analogsub_to_dahdisub(sub);
02249
02250 p->subs[idx].inthreeway = inthreeway;
02251 }
02252
02253 static int get_alarms(struct dahdi_pvt *p);
02254 static void handle_alarms(struct dahdi_pvt *p, int alms);
02255 static void my_get_and_handle_alarms(void *pvt)
02256 {
02257 int res;
02258 struct dahdi_pvt *p = pvt;
02259
02260 res = get_alarms(p);
02261 handle_alarms(p, res);
02262 }
02263
02264 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02265 {
02266 struct ast_channel *bridged = ast_bridged_channel(chan);
02267
02268 if (bridged && bridged->tech == &dahdi_tech) {
02269 struct dahdi_pvt *p = bridged->tech_pvt;
02270
02271 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02272 return p->sig_pvt;
02273 }
02274 }
02275 return NULL;
02276 }
02277
02278 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02279 {
02280 struct dahdi_pvt *p = pvt;
02281 int dahdi_sub = analogsub_to_dahdisub(sub);
02282 return p->subs[dahdi_sub].dfd;
02283 }
02284
02285 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02286 {
02287 struct dahdi_pvt *p = pvt;
02288
02289
02290 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02291 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02292 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02293 *cid_rings = cidrings[p->distinctivering - 1];
02294 } else {
02295 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02296 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02297 *cid_rings = p->sendcalleridafter;
02298 }
02299 }
02300
02301 static void my_set_alarm(void *pvt, int in_alarm)
02302 {
02303 struct dahdi_pvt *p = pvt;
02304
02305 p->inalarm = in_alarm;
02306 }
02307
02308 static void my_set_dialing(void *pvt, int is_dialing)
02309 {
02310 struct dahdi_pvt *p = pvt;
02311
02312 p->dialing = is_dialing;
02313 }
02314
02315 static void my_set_outgoing(void *pvt, int is_outgoing)
02316 {
02317 struct dahdi_pvt *p = pvt;
02318
02319 p->outgoing = is_outgoing;
02320 }
02321
02322 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02323 static void my_set_digital(void *pvt, int is_digital)
02324 {
02325 struct dahdi_pvt *p = pvt;
02326
02327 p->digital = is_digital;
02328 }
02329 #endif
02330
02331 #if defined(HAVE_SS7)
02332 static void my_set_inservice(void *pvt, int is_inservice)
02333 {
02334 struct dahdi_pvt *p = pvt;
02335
02336 p->inservice = is_inservice;
02337 }
02338 #endif
02339
02340 #if defined(HAVE_SS7)
02341 static void my_set_locallyblocked(void *pvt, int is_blocked)
02342 {
02343 struct dahdi_pvt *p = pvt;
02344
02345 p->locallyblocked = is_blocked;
02346 }
02347 #endif
02348
02349 #if defined(HAVE_SS7)
02350 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02351 {
02352 struct dahdi_pvt *p = pvt;
02353
02354 p->remotelyblocked = is_blocked;
02355 }
02356 #endif
02357
02358 static void my_set_ringtimeout(void *pvt, int ringt)
02359 {
02360 struct dahdi_pvt *p = pvt;
02361 p->ringt = ringt;
02362 }
02363
02364 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02365 {
02366 struct dahdi_pvt *p = pvt;
02367
02368 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02369 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02370 gettimeofday(&p->waitingfordt, NULL);
02371 ast_setstate(ast, AST_STATE_OFFHOOK);
02372 }
02373 }
02374
02375 static int my_check_waitingfordt(void *pvt)
02376 {
02377 struct dahdi_pvt *p = pvt;
02378
02379 if (p->waitingfordt.tv_usec) {
02380 return 1;
02381 }
02382
02383 return 0;
02384 }
02385
02386 static void my_set_confirmanswer(void *pvt, int flag)
02387 {
02388 struct dahdi_pvt *p = pvt;
02389 p->confirmanswer = flag;
02390 }
02391
02392 static int my_check_confirmanswer(void *pvt)
02393 {
02394 struct dahdi_pvt *p = pvt;
02395 if (p->confirmanswer) {
02396 return 1;
02397 }
02398
02399 return 0;
02400 }
02401
02402 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02403 {
02404 struct dahdi_pvt *p = pvt;
02405
02406 p->callwaiting = callwaiting_enable;
02407 }
02408
02409 static void my_cancel_cidspill(void *pvt)
02410 {
02411 struct dahdi_pvt *p = pvt;
02412
02413 ast_free(p->cidspill);
02414 p->cidspill = NULL;
02415 restore_conference(p);
02416 }
02417
02418 static int my_confmute(void *pvt, int mute)
02419 {
02420 struct dahdi_pvt *p = pvt;
02421 return dahdi_confmute(p, mute);
02422 }
02423
02424 static void my_set_pulsedial(void *pvt, int flag)
02425 {
02426 struct dahdi_pvt *p = pvt;
02427 p->pulsedial = flag;
02428 }
02429
02430 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02431 {
02432 struct dahdi_pvt *p = pvt;
02433
02434 p->owner = new_owner;
02435 }
02436
02437 static const char *my_get_orig_dialstring(void *pvt)
02438 {
02439 struct dahdi_pvt *p = pvt;
02440
02441 return p->dialstring;
02442 }
02443
02444 static void my_increase_ss_count(void)
02445 {
02446 ast_mutex_lock(&ss_thread_lock);
02447 ss_thread_count++;
02448 ast_mutex_unlock(&ss_thread_lock);
02449 }
02450
02451 static void my_decrease_ss_count(void)
02452 {
02453 ast_mutex_lock(&ss_thread_lock);
02454 ss_thread_count--;
02455 ast_cond_signal(&ss_thread_complete);
02456 ast_mutex_unlock(&ss_thread_lock);
02457 }
02458
02459 static void my_all_subchannels_hungup(void *pvt)
02460 {
02461 struct dahdi_pvt *p = pvt;
02462 int res, law;
02463
02464 p->faxhandled = 0;
02465 p->didtdd = 0;
02466
02467 if (p->dsp) {
02468 ast_dsp_free(p->dsp);
02469 p->dsp = NULL;
02470 }
02471
02472 p->law = p->law_default;
02473 law = p->law_default;
02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02475 if (res < 0)
02476 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02477
02478 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02479
02480 #if 1
02481 {
02482 int i;
02483 p->owner = NULL;
02484
02485 for (i = 0; i < 3; i++) {
02486 p->subs[i].owner = NULL;
02487 }
02488 }
02489 #endif
02490
02491 reset_conf(p);
02492 if (num_restart_pending == 0) {
02493 restart_monitor();
02494 }
02495 }
02496
02497 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02498
02499 static int my_conf_del(void *pvt, enum analog_sub sub)
02500 {
02501 struct dahdi_pvt *p = pvt;
02502 int x = analogsub_to_dahdisub(sub);
02503
02504 return conf_del(p, &p->subs[x], x);
02505 }
02506
02507 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02508
02509 static int my_conf_add(void *pvt, enum analog_sub sub)
02510 {
02511 struct dahdi_pvt *p = pvt;
02512 int x = analogsub_to_dahdisub(sub);
02513
02514 return conf_add(p, &p->subs[x], x, 0);
02515 }
02516
02517 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02518
02519 static int my_complete_conference_update(void *pvt, int needconference)
02520 {
02521 struct dahdi_pvt *p = pvt;
02522 int needconf = needconference;
02523 int x;
02524 int useslavenative;
02525 struct dahdi_pvt *slave = NULL;
02526
02527 useslavenative = isslavenative(p, &slave);
02528
02529
02530
02531 for (x = 0; x < MAX_SLAVES; x++) {
02532 if (p->slaves[x]) {
02533 if (useslavenative)
02534 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02535 else {
02536 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02537 needconf++;
02538 }
02539 }
02540 }
02541
02542 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02543 if (useslavenative)
02544 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02545 else {
02546 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02547 needconf++;
02548 }
02549 }
02550
02551 if (p->master) {
02552 if (isslavenative(p->master, NULL)) {
02553 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02554 } else {
02555 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02556 }
02557 }
02558 if (!needconf) {
02559
02560
02561 p->confno = -1;
02562 }
02563
02564 return 0;
02565 }
02566
02567 static int check_for_conference(struct dahdi_pvt *p);
02568
02569 static int my_check_for_conference(void *pvt)
02570 {
02571 struct dahdi_pvt *p = pvt;
02572 return check_for_conference(p);
02573 }
02574
02575 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)
02576 {
02577 struct dahdi_pvt *p = pvt;
02578 int da, db;
02579 int tchan;
02580 int tinthreeway;
02581
02582 da = analogsub_to_dahdisub(a);
02583 db = analogsub_to_dahdisub(b);
02584
02585 tchan = p->subs[da].chan;
02586 p->subs[da].chan = p->subs[db].chan;
02587 p->subs[db].chan = tchan;
02588
02589 tinthreeway = p->subs[da].inthreeway;
02590 p->subs[da].inthreeway = p->subs[db].inthreeway;
02591 p->subs[db].inthreeway = tinthreeway;
02592
02593 p->subs[da].owner = ast_a;
02594 p->subs[db].owner = ast_b;
02595
02596 if (ast_a)
02597 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02598 if (ast_b)
02599 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02600
02601 wakeup_sub(p, a);
02602 wakeup_sub(p, b);
02603
02604 return;
02605 }
02606
02607 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02608
02609 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02610 {
02611 struct dahdi_pvt *p = pvt;
02612 int dsub = analogsub_to_dahdisub(sub);
02613
02614 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02615 }
02616
02617 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02618 static int dahdi_setlaw(int dfd, int law)
02619 {
02620 int res;
02621 res = ioctl(dfd, DAHDI_SETLAW, &law);
02622 if (res)
02623 return res;
02624 return 0;
02625 }
02626 #endif
02627
02628 #if defined(HAVE_PRI)
02629 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)
02630 {
02631 struct dahdi_pvt *p = pvt;
02632 int audio;
02633 int newlaw = -1;
02634
02635 switch (p->sig) {
02636 case SIG_PRI_LIB_HANDLE_CASES:
02637 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02638
02639 break;
02640 }
02641
02642 default:
02643
02644 audio = 1;
02645 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02646 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02647 p->channel, audio, strerror(errno));
02648 }
02649 break;
02650 }
02651
02652 if (law != SIG_PRI_DEFLAW) {
02653 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02654 }
02655
02656 ast_copy_string(p->exten, exten, sizeof(p->exten));
02657
02658 switch (law) {
02659 case SIG_PRI_DEFLAW:
02660 newlaw = 0;
02661 break;
02662 case SIG_PRI_ALAW:
02663 newlaw = DAHDI_LAW_ALAW;
02664 break;
02665 case SIG_PRI_ULAW:
02666 newlaw = DAHDI_LAW_MULAW;
02667 break;
02668 }
02669 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02670 }
02671 #endif
02672
02673 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02674
02675 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685 static void my_pri_ss7_open_media(void *p)
02686 {
02687 struct dahdi_pvt *pvt = p;
02688 int res;
02689 int dfd;
02690 int set_val;
02691
02692 dfd = pvt->subs[SUB_REAL].dfd;
02693
02694
02695 set_val = 1;
02696 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02697 if (res < 0) {
02698 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02699 pvt->channel, strerror(errno));
02700 }
02701
02702
02703 res = dahdi_setlaw(dfd, pvt->law);
02704 if (res < 0) {
02705 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02706 }
02707
02708
02709 if (pvt->digital) {
02710 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02711 } else {
02712 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02713 pvt->law);
02714 }
02715 if (res < 0) {
02716 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02717 }
02718
02719 if (pvt->dsp_features && pvt->dsp) {
02720 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02721 pvt->dsp_features = 0;
02722 }
02723 }
02724 #endif
02725
02726 #if defined(HAVE_PRI)
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739 static void my_pri_dial_digits(void *p, const char *dial_string)
02740 {
02741 struct dahdi_dialoperation zo = {
02742 .op = DAHDI_DIAL_OP_APPEND,
02743 };
02744 struct dahdi_pvt *pvt = p;
02745 int res;
02746
02747 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02748 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02749 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02750 if (res) {
02751 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02752 pvt->channel, dial_string, strerror(errno));
02753 } else {
02754 pvt->dialing = 1;
02755 }
02756 }
02757 #endif
02758
02759 static int unalloc_sub(struct dahdi_pvt *p, int x);
02760
02761 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02762 {
02763 struct dahdi_pvt *p = pvt;
02764
02765 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02766 }
02767
02768 static int alloc_sub(struct dahdi_pvt *p, int x);
02769
02770 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02771 {
02772 struct dahdi_pvt *p = pvt;
02773
02774 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02775 }
02776
02777 static int has_voicemail(struct dahdi_pvt *p);
02778
02779 static int my_has_voicemail(void *pvt)
02780 {
02781 struct dahdi_pvt *p = pvt;
02782
02783 return has_voicemail(p);
02784 }
02785
02786 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02787 {
02788 struct dahdi_pvt *p = pvt;
02789 int index;
02790
02791 index = analogsub_to_dahdisub(sub);
02792
02793 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02794 }
02795
02796 static enum analog_event dahdievent_to_analogevent(int event)
02797 {
02798 enum analog_event res;
02799
02800 switch (event) {
02801 case DAHDI_EVENT_ONHOOK:
02802 res = ANALOG_EVENT_ONHOOK;
02803 break;
02804 case DAHDI_EVENT_RINGOFFHOOK:
02805 res = ANALOG_EVENT_RINGOFFHOOK;
02806 break;
02807 case DAHDI_EVENT_WINKFLASH:
02808 res = ANALOG_EVENT_WINKFLASH;
02809 break;
02810 case DAHDI_EVENT_ALARM:
02811 res = ANALOG_EVENT_ALARM;
02812 break;
02813 case DAHDI_EVENT_NOALARM:
02814 res = ANALOG_EVENT_NOALARM;
02815 break;
02816 case DAHDI_EVENT_DIALCOMPLETE:
02817 res = ANALOG_EVENT_DIALCOMPLETE;
02818 break;
02819 case DAHDI_EVENT_RINGERON:
02820 res = ANALOG_EVENT_RINGERON;
02821 break;
02822 case DAHDI_EVENT_RINGEROFF:
02823 res = ANALOG_EVENT_RINGEROFF;
02824 break;
02825 case DAHDI_EVENT_HOOKCOMPLETE:
02826 res = ANALOG_EVENT_HOOKCOMPLETE;
02827 break;
02828 case DAHDI_EVENT_PULSE_START:
02829 res = ANALOG_EVENT_PULSE_START;
02830 break;
02831 case DAHDI_EVENT_POLARITY:
02832 res = ANALOG_EVENT_POLARITY;
02833 break;
02834 case DAHDI_EVENT_RINGBEGIN:
02835 res = ANALOG_EVENT_RINGBEGIN;
02836 break;
02837 case DAHDI_EVENT_EC_DISABLED:
02838 res = ANALOG_EVENT_EC_DISABLED;
02839 break;
02840 case DAHDI_EVENT_REMOVED:
02841 res = ANALOG_EVENT_REMOVED;
02842 break;
02843 case DAHDI_EVENT_NEONMWI_ACTIVE:
02844 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02845 break;
02846 case DAHDI_EVENT_NEONMWI_INACTIVE:
02847 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02848 break;
02849 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02850 case DAHDI_EVENT_TX_CED_DETECTED:
02851 res = ANALOG_EVENT_TX_CED_DETECTED;
02852 break;
02853 case DAHDI_EVENT_RX_CED_DETECTED:
02854 res = ANALOG_EVENT_RX_CED_DETECTED;
02855 break;
02856 case DAHDI_EVENT_EC_NLP_DISABLED:
02857 res = ANALOG_EVENT_EC_NLP_DISABLED;
02858 break;
02859 case DAHDI_EVENT_EC_NLP_ENABLED:
02860 res = ANALOG_EVENT_EC_NLP_ENABLED;
02861 break;
02862 #endif
02863 case DAHDI_EVENT_PULSEDIGIT:
02864 res = ANALOG_EVENT_PULSEDIGIT;
02865 break;
02866 case DAHDI_EVENT_DTMFDOWN:
02867 res = ANALOG_EVENT_DTMFDOWN;
02868 break;
02869 case DAHDI_EVENT_DTMFUP:
02870 res = ANALOG_EVENT_DTMFUP;
02871 break;
02872 default:
02873 switch(event & 0xFFFF0000) {
02874 case DAHDI_EVENT_PULSEDIGIT:
02875 case DAHDI_EVENT_DTMFDOWN:
02876 case DAHDI_EVENT_DTMFUP:
02877
02878
02879
02880
02881 return event;
02882 }
02883
02884 res = ANALOG_EVENT_ERROR;
02885 break;
02886 }
02887
02888 return res;
02889 }
02890
02891 static inline int dahdi_wait_event(int fd);
02892
02893 static int my_wait_event(void *pvt)
02894 {
02895 struct dahdi_pvt *p = pvt;
02896
02897 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02898 }
02899
02900 static int my_get_event(void *pvt)
02901 {
02902 struct dahdi_pvt *p = pvt;
02903 int res;
02904
02905 if (p->fake_event) {
02906 res = p->fake_event;
02907 p->fake_event = 0;
02908 } else
02909 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02910
02911 return dahdievent_to_analogevent(res);
02912 }
02913
02914 static int my_is_off_hook(void *pvt)
02915 {
02916 struct dahdi_pvt *p = pvt;
02917 int res;
02918 struct dahdi_params par;
02919
02920 memset(&par, 0, sizeof(par));
02921
02922 if (p->subs[SUB_REAL].dfd > -1)
02923 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02924 else {
02925
02926 res = 0;
02927 par.rxisoffhook = 0;
02928 }
02929 if (res) {
02930 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02931 }
02932
02933 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02934
02935
02936
02937 return (par.rxbits > -1) || par.rxisoffhook;
02938 }
02939
02940 return par.rxisoffhook;
02941 }
02942
02943 static void dahdi_enable_ec(struct dahdi_pvt *p);
02944 static void dahdi_disable_ec(struct dahdi_pvt *p);
02945
02946 static int my_set_echocanceller(void *pvt, int enable)
02947 {
02948 struct dahdi_pvt *p = pvt;
02949
02950 if (enable)
02951 dahdi_enable_ec(p);
02952 else
02953 dahdi_disable_ec(p);
02954
02955 return 0;
02956 }
02957
02958 static int dahdi_ring_phone(struct dahdi_pvt *p);
02959
02960 static int my_ring(void *pvt)
02961 {
02962 struct dahdi_pvt *p = pvt;
02963
02964 return dahdi_ring_phone(p);
02965 }
02966
02967 static int my_flash(void *pvt)
02968 {
02969 struct dahdi_pvt *p = pvt;
02970 int func = DAHDI_FLASH;
02971 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02972 }
02973
02974 static inline int dahdi_set_hook(int fd, int hs);
02975
02976 static int my_off_hook(void *pvt)
02977 {
02978 struct dahdi_pvt *p = pvt;
02979 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02980 }
02981
02982 static void my_set_needringing(void *pvt, int value)
02983 {
02984 struct dahdi_pvt *p = pvt;
02985 p->subs[SUB_REAL].needringing = value;
02986 }
02987
02988 static void my_set_polarity(void *pvt, int value)
02989 {
02990 struct dahdi_pvt *p = pvt;
02991
02992 if (p->channel == CHAN_PSEUDO) {
02993 return;
02994 }
02995 p->polarity = value;
02996 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02997 }
02998
02999 static void my_start_polarityswitch(void *pvt)
03000 {
03001 struct dahdi_pvt *p = pvt;
03002
03003 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03004 my_set_polarity(pvt, 0);
03005 }
03006 }
03007
03008 static void my_answer_polarityswitch(void *pvt)
03009 {
03010 struct dahdi_pvt *p = pvt;
03011
03012 if (!p->answeronpolarityswitch) {
03013 return;
03014 }
03015
03016 my_set_polarity(pvt, 1);
03017 }
03018
03019 static void my_hangup_polarityswitch(void *pvt)
03020 {
03021 struct dahdi_pvt *p = pvt;
03022
03023 if (!p->hanguponpolarityswitch) {
03024 return;
03025 }
03026
03027 if (p->answeronpolarityswitch) {
03028 my_set_polarity(pvt, 0);
03029 } else {
03030 my_set_polarity(pvt, 1);
03031 }
03032 }
03033
03034 static int my_start(void *pvt)
03035 {
03036 struct dahdi_pvt *p = pvt;
03037 int x = DAHDI_START;
03038
03039 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03040 }
03041
03042 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03043 {
03044 int index = analogsub_to_dahdisub(sub);
03045 int res;
03046 struct dahdi_pvt *p = pvt;
03047 struct dahdi_dialoperation ddop;
03048
03049 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03050 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03051 return -1;
03052 }
03053
03054 if (sub != ANALOG_SUB_REAL) {
03055 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03056 dop->dialstr, p->channel, sub);
03057 return -1;
03058 }
03059
03060 ddop.op = DAHDI_DIAL_OP_REPLACE;
03061 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03062
03063 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03064
03065 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03066 if (res == -1) {
03067 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03068 }
03069
03070 return res;
03071 }
03072
03073 static void dahdi_train_ec(struct dahdi_pvt *p);
03074
03075 static int my_train_echocanceller(void *pvt)
03076 {
03077 struct dahdi_pvt *p = pvt;
03078
03079 dahdi_train_ec(p);
03080
03081 return 0;
03082 }
03083
03084 static int my_is_dialing(void *pvt, enum analog_sub sub)
03085 {
03086 struct dahdi_pvt *p = pvt;
03087 int index;
03088 int x;
03089
03090 index = analogsub_to_dahdisub(sub);
03091
03092 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03093 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03094 return -1;
03095 }
03096
03097 return x;
03098 }
03099
03100 static int my_on_hook(void *pvt)
03101 {
03102 struct dahdi_pvt *p = pvt;
03103 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03104 }
03105
03106 #if defined(HAVE_PRI)
03107 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03108 {
03109 struct dahdi_pvt *old_chan = chan_old;
03110 struct dahdi_pvt *new_chan = chan_new;
03111
03112 new_chan->owner = old_chan->owner;
03113 old_chan->owner = NULL;
03114 if (new_chan->owner) {
03115 new_chan->owner->tech_pvt = new_chan;
03116 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03117 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03118 old_chan->subs[SUB_REAL].owner = NULL;
03119 }
03120
03121 new_chan->dsp = old_chan->dsp;
03122 new_chan->dsp_features = old_chan->dsp_features;
03123 old_chan->dsp = NULL;
03124 old_chan->dsp_features = 0;
03125
03126
03127 new_chan->dialing = old_chan->dialing;
03128 new_chan->digital = old_chan->digital;
03129 new_chan->outgoing = old_chan->outgoing;
03130 old_chan->dialing = 0;
03131 old_chan->digital = 0;
03132 old_chan->outgoing = 0;
03133
03134
03135 new_chan->law = old_chan->law;
03136 strcpy(new_chan->dialstring, old_chan->dialstring);
03137 }
03138 #endif
03139
03140 #if defined(HAVE_PRI)
03141 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03142 {
03143 switch (tone) {
03144 case SIG_PRI_TONE_RINGTONE:
03145 return DAHDI_TONE_RINGTONE;
03146 case SIG_PRI_TONE_STUTTER:
03147 return DAHDI_TONE_STUTTER;
03148 case SIG_PRI_TONE_CONGESTION:
03149 return DAHDI_TONE_CONGESTION;
03150 case SIG_PRI_TONE_DIALTONE:
03151 return DAHDI_TONE_DIALTONE;
03152 case SIG_PRI_TONE_DIALRECALL:
03153 return DAHDI_TONE_DIALRECALL;
03154 case SIG_PRI_TONE_INFO:
03155 return DAHDI_TONE_INFO;
03156 case SIG_PRI_TONE_BUSY:
03157 return DAHDI_TONE_BUSY;
03158 default:
03159 return -1;
03160 }
03161 }
03162 #endif
03163
03164 #if defined(HAVE_PRI)
03165 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03166 {
03167 int x;
03168
03169 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03170 switch (x) {
03171 case DAHDI_EVENT_NONE:
03172 break;
03173 case DAHDI_EVENT_ALARM:
03174 case DAHDI_EVENT_NOALARM:
03175 if (sig_pri_is_alarm_ignored(pri)) {
03176 break;
03177 }
03178
03179 default:
03180 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03181 event2str(x), x, pri->span);
03182 break;
03183 }
03184
03185 switch (x) {
03186 case DAHDI_EVENT_ALARM:
03187 pri_event_alarm(pri, index, 0);
03188 break;
03189 case DAHDI_EVENT_NOALARM:
03190 pri_event_noalarm(pri, index, 0);
03191 break;
03192 default:
03193 break;
03194 }
03195 }
03196 #endif
03197
03198 #if defined(HAVE_PRI)
03199 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03200 {
03201 struct dahdi_pvt *p = pvt;
03202
03203 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03204 }
03205 #endif
03206
03207 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03219 {
03220 struct dahdi_pvt *p = pvt;
03221
03222 ast_copy_string(p->cid_num,
03223 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03224 sizeof(p->cid_num));
03225 ast_copy_string(p->cid_name,
03226 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03227 sizeof(p->cid_name));
03228 ast_copy_string(p->cid_subaddr,
03229 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03230 sizeof(p->cid_subaddr));
03231 p->cid_ton = caller->id.number.plan;
03232 p->callingpres = ast_party_id_presentation(&caller->id);
03233 if (caller->id.tag) {
03234 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03235 }
03236 ast_copy_string(p->cid_ani,
03237 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03238 sizeof(p->cid_ani));
03239 p->cid_ani2 = caller->ani2;
03240 }
03241 #endif
03242
03243 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254 static void my_set_dnid(void *pvt, const char *dnid)
03255 {
03256 struct dahdi_pvt *p = pvt;
03257
03258 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03259 }
03260 #endif
03261
03262 #if defined(HAVE_PRI)
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273 static void my_set_rdnis(void *pvt, const char *rdnis)
03274 {
03275 struct dahdi_pvt *p = pvt;
03276
03277 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03278 }
03279 #endif
03280
03281 #if defined(HAVE_PRI)
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03307 {
03308 char *dial;
03309 struct dahdi_pvt *pvt;
03310 AST_DECLARE_APP_ARGS(args,
03311 AST_APP_ARG(tech);
03312 AST_APP_ARG(group);
03313
03314
03315
03316 );
03317
03318 pvt = priv;
03319 dial = ast_strdupa(pvt->dialstring);
03320 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03321 if (!args.tech) {
03322 ast_copy_string(buf, pvt->dialstring, buf_size);
03323 return;
03324 }
03325 if (!args.group) {
03326
03327 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03328 return;
03329 }
03330 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03331
03332
03333 ast_copy_string(buf, pvt->dialstring, buf_size);
03334 return;
03335 }
03336
03337 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03338 }
03339 #endif
03340
03341 #if defined(HAVE_PRI)
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03354 {
03355 unsigned idx;
03356 unsigned num_b_chans;
03357 unsigned in_use;
03358 unsigned in_alarm;
03359 enum ast_device_state new_state;
03360
03361
03362 num_b_chans = 0;
03363 in_use = 0;
03364 in_alarm = 1;
03365 for (idx = pri->numchans; idx--;) {
03366 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03367
03368 ++num_b_chans;
03369 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03370 ++in_use;
03371 }
03372 if (!pri->pvts[idx]->inalarm) {
03373
03374 in_alarm = 0;
03375 }
03376 }
03377 }
03378
03379
03380 if (in_alarm) {
03381 new_state = AST_DEVICE_UNAVAILABLE;
03382 } else {
03383 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03384 }
03385 if (pri->congestion_devstate != new_state) {
03386 pri->congestion_devstate = new_state;
03387 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span);
03388 }
03389 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03390
03391 if (in_alarm) {
03392 new_state = AST_DEVICE_UNAVAILABLE;
03393 } else if (!in_use) {
03394 new_state = AST_DEVICE_NOT_INUSE;
03395 } else if (!pri->user_busy_threshold) {
03396 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03397 } else {
03398 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03399 : AST_DEVICE_BUSY;
03400 }
03401 if (pri->threshold_devstate != new_state) {
03402 pri->threshold_devstate = new_state;
03403 ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span);
03404 }
03405 #endif
03406 }
03407 #endif
03408
03409 #if defined(HAVE_PRI)
03410
03411
03412
03413
03414
03415
03416
03417 static void my_module_ref(void)
03418 {
03419 ast_module_ref(ast_module_info->self);
03420 }
03421 #endif
03422
03423 #if defined(HAVE_PRI)
03424
03425
03426
03427
03428
03429
03430
03431 static void my_module_unref(void)
03432 {
03433 ast_module_unref(ast_module_info->self);
03434 }
03435 #endif
03436
03437 #if defined(HAVE_PRI)
03438 #if defined(HAVE_PRI_CALL_WAITING)
03439 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03440 #endif
03441 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03442
03443 static struct sig_pri_callback dahdi_pri_callbacks =
03444 {
03445 .handle_dchan_exception = my_handle_dchan_exception,
03446 .play_tone = my_pri_play_tone,
03447 .set_echocanceller = my_set_echocanceller,
03448 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03449 .lock_private = my_lock_private,
03450 .unlock_private = my_unlock_private,
03451 .new_ast_channel = my_new_pri_ast_channel,
03452 .fixup_chans = my_pri_fixup_chans,
03453 .set_alarm = my_set_alarm,
03454 .set_dialing = my_set_dialing,
03455 .set_outgoing = my_set_outgoing,
03456 .set_digital = my_set_digital,
03457 .set_callerid = my_set_callerid,
03458 .set_dnid = my_set_dnid,
03459 .set_rdnis = my_set_rdnis,
03460 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03461 #if defined(HAVE_PRI_CALL_WAITING)
03462 .init_config = my_pri_init_config,
03463 #endif
03464 .get_orig_dialstring = my_get_orig_dialstring,
03465 .make_cc_dialstring = my_pri_make_cc_dialstring,
03466 .update_span_devstate = dahdi_pri_update_span_devstate,
03467 .module_ref = my_module_ref,
03468 .module_unref = my_module_unref,
03469 .dial_digits = my_pri_dial_digits,
03470 .open_media = my_pri_ss7_open_media,
03471 .ami_channel_event = my_ami_channel_event,
03472 };
03473 #endif
03474
03475 #if defined(HAVE_SS7)
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03487 {
03488 int event;
03489
03490 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03491 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03492 linkset->span, which);
03493 return;
03494 }
03495 switch (event) {
03496 case DAHDI_EVENT_NONE:
03497 break;
03498 case DAHDI_EVENT_ALARM:
03499 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03500 event2str(event), event, linkset->span, which);
03501 sig_ss7_link_alarm(linkset, which);
03502 break;
03503 case DAHDI_EVENT_NOALARM:
03504 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03505 event2str(event), event, linkset->span, which);
03506 sig_ss7_link_noalarm(linkset, which);
03507 break;
03508 default:
03509 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03510 event2str(event), event, linkset->span, which);
03511 break;
03512 }
03513 }
03514 #endif
03515
03516 #if defined(HAVE_SS7)
03517 static void my_ss7_set_loopback(void *pvt, int enable)
03518 {
03519 struct dahdi_pvt *p = pvt;
03520
03521 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03522 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03523 strerror(errno));
03524 }
03525 }
03526 #endif
03527
03528 #if defined(HAVE_SS7)
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543 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)
03544 {
03545 struct dahdi_pvt *p = pvt;
03546 int audio;
03547 int newlaw;
03548
03549
03550 audio = 1;
03551 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03552 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03553 p->channel, audio, strerror(errno));
03554
03555 if (law != SIG_SS7_DEFLAW) {
03556 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03557 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03558 }
03559
03560 ast_copy_string(p->exten, exten, sizeof(p->exten));
03561
03562 newlaw = -1;
03563 switch (law) {
03564 case SIG_SS7_DEFLAW:
03565 newlaw = 0;
03566 break;
03567 case SIG_SS7_ALAW:
03568 newlaw = DAHDI_LAW_ALAW;
03569 break;
03570 case SIG_SS7_ULAW:
03571 newlaw = DAHDI_LAW_MULAW;
03572 break;
03573 }
03574 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03575 }
03576 #endif
03577
03578 #if defined(HAVE_SS7)
03579 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03580 {
03581 switch (tone) {
03582 case SIG_SS7_TONE_RINGTONE:
03583 return DAHDI_TONE_RINGTONE;
03584 case SIG_SS7_TONE_STUTTER:
03585 return DAHDI_TONE_STUTTER;
03586 case SIG_SS7_TONE_CONGESTION:
03587 return DAHDI_TONE_CONGESTION;
03588 case SIG_SS7_TONE_DIALTONE:
03589 return DAHDI_TONE_DIALTONE;
03590 case SIG_SS7_TONE_DIALRECALL:
03591 return DAHDI_TONE_DIALRECALL;
03592 case SIG_SS7_TONE_INFO:
03593 return DAHDI_TONE_INFO;
03594 case SIG_SS7_TONE_BUSY:
03595 return DAHDI_TONE_BUSY;
03596 default:
03597 return -1;
03598 }
03599 }
03600 #endif
03601
03602 #if defined(HAVE_SS7)
03603 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03604 {
03605 struct dahdi_pvt *p = pvt;
03606
03607 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03608 }
03609 #endif
03610
03611 #if defined(HAVE_SS7)
03612 static struct sig_ss7_callback dahdi_ss7_callbacks =
03613 {
03614 .lock_private = my_lock_private,
03615 .unlock_private = my_unlock_private,
03616
03617 .set_echocanceller = my_set_echocanceller,
03618 .set_loopback = my_ss7_set_loopback,
03619
03620 .new_ast_channel = my_new_ss7_ast_channel,
03621 .play_tone = my_ss7_play_tone,
03622
03623 .handle_link_exception = my_handle_link_exception,
03624 .set_alarm = my_set_alarm,
03625 .set_dialing = my_set_dialing,
03626 .set_outgoing = my_set_outgoing,
03627 .set_digital = my_set_digital,
03628 .set_inservice = my_set_inservice,
03629 .set_locallyblocked = my_set_locallyblocked,
03630 .set_remotelyblocked = my_set_remotelyblocked,
03631 .set_callerid = my_set_callerid,
03632 .set_dnid = my_set_dnid,
03633 .open_media = my_pri_ss7_open_media,
03634 };
03635 #endif
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654
03655 static void notify_message(char *mailbox_full, int thereornot)
03656 {
03657 char s[sizeof(mwimonitornotify) + 80];
03658 struct ast_event *event;
03659 char *mailbox, *context;
03660
03661
03662 context = mailbox = ast_strdupa(mailbox_full);
03663 strsep(&context, "@");
03664 if (ast_strlen_zero(context))
03665 context = "default";
03666
03667 if (!(event = ast_event_new(AST_EVENT_MWI,
03668 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03669 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03670 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03671 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03672 AST_EVENT_IE_END))) {
03673 return;
03674 }
03675
03676 ast_event_queue_and_cache(event);
03677
03678 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03679 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03680 ast_safe_system(s);
03681 }
03682 }
03683
03684 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03685 {
03686 struct dahdi_pvt *p = pvt;
03687
03688 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03689 return;
03690
03691 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03692 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03693 notify_message(p->mailbox, 1);
03694 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03695 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03696 notify_message(p->mailbox, 0);
03697 }
03698
03699
03700 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03701 ast_hangup(chan);
03702 return;
03703 }
03704 }
03705
03706 static int my_have_progressdetect(void *pvt)
03707 {
03708 struct dahdi_pvt *p = pvt;
03709
03710 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03711 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03712 return 1;
03713 } else {
03714
03715 return 0;
03716 }
03717 }
03718
03719 static struct analog_callback dahdi_analog_callbacks =
03720 {
03721 .play_tone = my_play_tone,
03722 .get_event = my_get_event,
03723 .wait_event = my_wait_event,
03724 .is_off_hook = my_is_off_hook,
03725 .set_echocanceller = my_set_echocanceller,
03726 .ring = my_ring,
03727 .flash = my_flash,
03728 .off_hook = my_off_hook,
03729 .dial_digits = my_dial_digits,
03730 .train_echocanceller = my_train_echocanceller,
03731 .on_hook = my_on_hook,
03732 .is_dialing = my_is_dialing,
03733 .allocate_sub = my_allocate_sub,
03734 .unallocate_sub = my_unallocate_sub,
03735 .swap_subs = my_swap_subchannels,
03736 .has_voicemail = my_has_voicemail,
03737 .check_for_conference = my_check_for_conference,
03738 .conf_add = my_conf_add,
03739 .conf_del = my_conf_del,
03740 .complete_conference_update = my_complete_conference_update,
03741 .start = my_start,
03742 .all_subchannels_hungup = my_all_subchannels_hungup,
03743 .lock_private = my_lock_private,
03744 .unlock_private = my_unlock_private,
03745 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03746 .handle_dtmf = my_handle_dtmf,
03747 .wink = my_wink,
03748 .new_ast_channel = my_new_analog_ast_channel,
03749 .dsp_set_digitmode = my_dsp_set_digitmode,
03750 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03751 .send_callerid = my_send_callerid,
03752 .callwait = my_callwait,
03753 .stop_callwait = my_stop_callwait,
03754 .get_callerid = my_get_callerid,
03755 .start_cid_detect = my_start_cid_detect,
03756 .stop_cid_detect = my_stop_cid_detect,
03757 .handle_notify_message = my_handle_notify_message,
03758 .increase_ss_count = my_increase_ss_count,
03759 .decrease_ss_count = my_decrease_ss_count,
03760 .distinctive_ring = my_distinctive_ring,
03761 .set_linear_mode = my_set_linear_mode,
03762 .set_inthreeway = my_set_inthreeway,
03763 .get_and_handle_alarms = my_get_and_handle_alarms,
03764 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03765 .get_sub_fd = my_get_sub_fd,
03766 .set_cadence = my_set_cadence,
03767 .set_alarm = my_set_alarm,
03768 .set_dialing = my_set_dialing,
03769 .set_outgoing = my_set_outgoing,
03770 .set_ringtimeout = my_set_ringtimeout,
03771 .set_waitingfordt = my_set_waitingfordt,
03772 .check_waitingfordt = my_check_waitingfordt,
03773 .set_confirmanswer = my_set_confirmanswer,
03774 .check_confirmanswer = my_check_confirmanswer,
03775 .set_callwaiting = my_set_callwaiting,
03776 .cancel_cidspill = my_cancel_cidspill,
03777 .confmute = my_confmute,
03778 .set_pulsedial = my_set_pulsedial,
03779 .set_new_owner = my_set_new_owner,
03780 .get_orig_dialstring = my_get_orig_dialstring,
03781 .set_needringing = my_set_needringing,
03782 .set_polarity = my_set_polarity,
03783 .start_polarityswitch = my_start_polarityswitch,
03784 .answer_polarityswitch = my_answer_polarityswitch,
03785 .hangup_polarityswitch = my_hangup_polarityswitch,
03786 .have_progressdetect = my_have_progressdetect,
03787 };
03788
03789
03790 static struct dahdi_pvt *round_robin[32];
03791
03792 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03793 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03794 {
03795 int res;
03796 if (p->subs[SUB_REAL].owner == ast)
03797 res = 0;
03798 else if (p->subs[SUB_CALLWAIT].owner == ast)
03799 res = 1;
03800 else if (p->subs[SUB_THREEWAY].owner == ast)
03801 res = 2;
03802 else {
03803 res = -1;
03804 if (!nullok)
03805 ast_log(LOG_WARNING,
03806 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03807 ast ? ast->name : "", p->channel, fname, line);
03808 }
03809 return res;
03810 }
03811
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03828 {
03829 for (;;) {
03830 if (!pvt->subs[sub_idx].owner) {
03831
03832 break;
03833 }
03834 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03835
03836 break;
03837 }
03838
03839 DEADLOCK_AVOIDANCE(&pvt->lock);
03840 }
03841 }
03842
03843 static void wakeup_sub(struct dahdi_pvt *p, int a)
03844 {
03845 dahdi_lock_sub_owner(p, a);
03846 if (p->subs[a].owner) {
03847 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03848 ast_channel_unlock(p->subs[a].owner);
03849 }
03850 }
03851
03852 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03853 {
03854 for (;;) {
03855 if (p->owner) {
03856 if (ast_channel_trylock(p->owner)) {
03857 DEADLOCK_AVOIDANCE(&p->lock);
03858 } else {
03859 ast_queue_frame(p->owner, f);
03860 ast_channel_unlock(p->owner);
03861 break;
03862 }
03863 } else
03864 break;
03865 }
03866 }
03867
03868 static void handle_clear_alarms(struct dahdi_pvt *p)
03869 {
03870 #if defined(HAVE_PRI)
03871 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03872 return;
03873 }
03874 #endif
03875
03876 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03877 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03878 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03879 }
03880 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03881 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03882 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03883 }
03884 }
03885
03886 #ifdef HAVE_OPENR2
03887
03888 static int dahdi_r2_answer(struct dahdi_pvt *p)
03889 {
03890 int res = 0;
03891
03892
03893
03894 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03895 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03896 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03897 if (!double_answer) {
03898
03899
03900 res = openr2_chan_answer_call(p->r2chan);
03901 } else if (wants_double_answer) {
03902 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03903 } else {
03904 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03905 }
03906 #else
03907 res = openr2_chan_answer_call(p->r2chan);
03908 #endif
03909 return res;
03910 }
03911
03912
03913
03914
03915 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03916 {
03917 openr2_calling_party_category_t cat;
03918 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03919 struct dahdi_pvt *p = c->tech_pvt;
03920 if (ast_strlen_zero(catstr)) {
03921 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03922 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03923 return p->mfcr2_category;
03924 }
03925 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03926 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03927 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03928 return p->mfcr2_category;
03929 }
03930 ast_debug(1, "Using category %s\n", catstr);
03931 return cat;
03932 }
03933
03934 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03935 {
03936 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03937 ast_mutex_lock(&p->lock);
03938 if (p->mfcr2call) {
03939 ast_mutex_unlock(&p->lock);
03940
03941
03942
03943
03944
03945 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03946 return;
03947 }
03948 p->mfcr2call = 1;
03949
03950 p->cid_name[0] = '\0';
03951 p->cid_num[0] = '\0';
03952 p->cid_subaddr[0] = '\0';
03953 p->rdnis[0] = '\0';
03954 p->exten[0] = '\0';
03955 p->mfcr2_ani_index = '\0';
03956 p->mfcr2_dnis_index = '\0';
03957 p->mfcr2_dnis_matched = 0;
03958 p->mfcr2_answer_pending = 0;
03959 p->mfcr2_call_accepted = 0;
03960 ast_mutex_unlock(&p->lock);
03961 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03962 }
03963
03964 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03965 {
03966 int res;
03967 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03968 ast_mutex_lock(&p->lock);
03969 p->inalarm = alarm ? 1 : 0;
03970 if (p->inalarm) {
03971 res = get_alarms(p);
03972 handle_alarms(p, res);
03973 } else {
03974 handle_clear_alarms(p);
03975 }
03976 ast_mutex_unlock(&p->lock);
03977 }
03978
03979 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03980 {
03981 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03982 }
03983
03984 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03985 {
03986 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03987 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03988 if (p->owner) {
03989 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03990 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03991 }
03992 ast_mutex_lock(&p->lock);
03993 p->mfcr2call = 0;
03994 ast_mutex_unlock(&p->lock);
03995 }
03996
03997 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03998 {
03999 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
04000 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
04001 p->channel, openr2_proto_get_disconnect_string(cause));
04002
04003 openr2_chan_set_idle(p->r2chan);
04004 ast_mutex_lock(&p->lock);
04005 p->mfcr2call = 0;
04006 ast_mutex_unlock(&p->lock);
04007 }
04008 }
04009
04010 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
04011 {
04012 struct dahdi_pvt *p;
04013 struct ast_channel *c;
04014 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
04015 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
04016 openr2_proto_get_category_string(category));
04017 p = openr2_chan_get_client_data(r2chan);
04018
04019 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04020 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04021 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04022 return;
04023 }
04024 ast_mutex_lock(&p->lock);
04025 p->mfcr2_recvd_category = category;
04026
04027 if (!p->use_callerid) {
04028 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04029 p->cid_num[0] = 0;
04030 p->cid_name[0] = 0;
04031 }
04032
04033 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04034 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04035 p->exten[0] = 's';
04036 p->exten[1] = 0;
04037 }
04038 ast_mutex_unlock(&p->lock);
04039 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04040 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04041 p->channel, p->exten, p->context);
04042 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04043 return;
04044 }
04045 if (!p->mfcr2_accept_on_offer) {
04046
04047 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04048 if (c) {
04049
04050
04051
04052 return;
04053 }
04054 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04055 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04056 } else if (p->mfcr2_charge_calls) {
04057 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04058 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04059 } else {
04060 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04061 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04062 }
04063 }
04064
04065 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04066 {
04067 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04068 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04069 ast_mutex_lock(&p->lock);
04070 p->mfcr2call = 0;
04071 ast_mutex_unlock(&p->lock);
04072 }
04073
04074 static void dahdi_enable_ec(struct dahdi_pvt *p);
04075 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04076 {
04077 struct dahdi_pvt *p = NULL;
04078 struct ast_channel *c = NULL;
04079 p = openr2_chan_get_client_data(r2chan);
04080 dahdi_enable_ec(p);
04081 p->mfcr2_call_accepted = 1;
04082
04083 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04084 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04085
04086
04087
04088
04089 if (!p->mfcr2_accept_on_offer) {
04090 openr2_chan_disable_read(r2chan);
04091 if (p->mfcr2_answer_pending) {
04092 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04093 dahdi_r2_answer(p);
04094 }
04095 return;
04096 }
04097 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04098 if (c) {
04099
04100
04101 openr2_chan_disable_read(r2chan);
04102 return;
04103 }
04104 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04105
04106 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04107 return;
04108 }
04109
04110 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04111 p->subs[SUB_REAL].needringing = 1;
04112 p->dialing = 0;
04113
04114 openr2_chan_disable_read(r2chan);
04115 }
04116
04117 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04118 {
04119 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04120 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04121 p->subs[SUB_REAL].needanswer = 1;
04122 }
04123
04124 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04125 {
04126
04127 }
04128
04129 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04130 {
04131 switch (cause) {
04132 case OR2_CAUSE_BUSY_NUMBER:
04133 return AST_CAUSE_BUSY;
04134 case OR2_CAUSE_NETWORK_CONGESTION:
04135 return AST_CAUSE_CONGESTION;
04136 case OR2_CAUSE_OUT_OF_ORDER:
04137 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04138 case OR2_CAUSE_UNALLOCATED_NUMBER:
04139 return AST_CAUSE_UNREGISTERED;
04140 case OR2_CAUSE_NO_ANSWER:
04141 return AST_CAUSE_NO_ANSWER;
04142 case OR2_CAUSE_NORMAL_CLEARING:
04143 return AST_CAUSE_NORMAL_CLEARING;
04144 case OR2_CAUSE_UNSPECIFIED:
04145 default:
04146 return AST_CAUSE_NOTDEFINED;
04147 }
04148 }
04149
04150 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04151 {
04152 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04153 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04154 ast_mutex_lock(&p->lock);
04155 if (!p->owner) {
04156 ast_mutex_unlock(&p->lock);
04157
04158 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04159 return;
04160 }
04161
04162
04163 if (p->owner->_state == AST_STATE_UP) {
04164 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04165 ast_mutex_unlock(&p->lock);
04166 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04167
04168 switch (cause) {
04169 case OR2_CAUSE_BUSY_NUMBER:
04170 p->subs[SUB_REAL].needbusy = 1;
04171 break;
04172 case OR2_CAUSE_NETWORK_CONGESTION:
04173 case OR2_CAUSE_OUT_OF_ORDER:
04174 case OR2_CAUSE_UNALLOCATED_NUMBER:
04175 case OR2_CAUSE_NO_ANSWER:
04176 case OR2_CAUSE_UNSPECIFIED:
04177 case OR2_CAUSE_NORMAL_CLEARING:
04178 p->subs[SUB_REAL].needcongestion = 1;
04179 break;
04180 default:
04181 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04182 }
04183 ast_mutex_unlock(&p->lock);
04184 } else {
04185 ast_mutex_unlock(&p->lock);
04186
04187
04188 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04189 }
04190 }
04191
04192 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04193 {
04194 switch (level) {
04195 case OR2_LOG_NOTICE:
04196 ast_verbose("%s", logmessage);
04197 break;
04198 case OR2_LOG_WARNING:
04199 ast_log(LOG_WARNING, "%s", logmessage);
04200 break;
04201 case OR2_LOG_ERROR:
04202 ast_log(LOG_ERROR, "%s", logmessage);
04203 break;
04204 case OR2_LOG_STACK_TRACE:
04205 case OR2_LOG_MF_TRACE:
04206 case OR2_LOG_CAS_TRACE:
04207 case OR2_LOG_DEBUG:
04208 case OR2_LOG_EX_DEBUG:
04209 ast_log(LOG_DEBUG, "%s", logmessage);
04210 break;
04211 default:
04212 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04213 ast_log(LOG_DEBUG, "%s", logmessage);
04214 break;
04215 }
04216 }
04217
04218 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04219 {
04220 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04221 ast_mutex_lock(&p->lock);
04222 p->remotelyblocked = 1;
04223 ast_mutex_unlock(&p->lock);
04224 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04225 }
04226
04227 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04228 {
04229 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04230 ast_mutex_lock(&p->lock);
04231 p->remotelyblocked = 0;
04232 ast_mutex_unlock(&p->lock);
04233 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04234 }
04235
04236 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04237 __attribute__((format (printf, 3, 0)));
04238 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04239 {
04240 #define CONTEXT_TAG "Context - "
04241 char logmsg[256];
04242 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04243 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04244 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04245 dahdi_r2_write_log(level, completemsg);
04246 #undef CONTEXT_TAG
04247 }
04248
04249 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04250 __attribute__((format (printf, 3, 0)));
04251 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04252 {
04253 #define CHAN_TAG "Chan "
04254 char logmsg[256];
04255 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04256 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04257 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04258 dahdi_r2_write_log(level, completemsg);
04259 }
04260
04261 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04262 {
04263 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04264
04265 if (p->immediate) {
04266 return 0;
04267 }
04268 p->exten[p->mfcr2_dnis_index] = digit;
04269 p->rdnis[p->mfcr2_dnis_index] = digit;
04270 p->mfcr2_dnis_index++;
04271 p->exten[p->mfcr2_dnis_index] = 0;
04272 p->rdnis[p->mfcr2_dnis_index] = 0;
04273
04274 if ((p->mfcr2_dnis_matched ||
04275 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04276 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04277 return 0;
04278 }
04279
04280 return 1;
04281 }
04282
04283 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04284 {
04285 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04286 p->cid_num[p->mfcr2_ani_index] = digit;
04287 p->cid_name[p->mfcr2_ani_index] = digit;
04288 p->mfcr2_ani_index++;
04289 p->cid_num[p->mfcr2_ani_index] = 0;
04290 p->cid_name[p->mfcr2_ani_index] = 0;
04291 }
04292
04293 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04294 {
04295 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04296 }
04297
04298 static openr2_event_interface_t dahdi_r2_event_iface = {
04299 .on_call_init = dahdi_r2_on_call_init,
04300 .on_call_offered = dahdi_r2_on_call_offered,
04301 .on_call_accepted = dahdi_r2_on_call_accepted,
04302 .on_call_answered = dahdi_r2_on_call_answered,
04303 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04304 .on_call_end = dahdi_r2_on_call_end,
04305 .on_call_read = dahdi_r2_on_call_read,
04306 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04307 .on_os_error = dahdi_r2_on_os_error,
04308 .on_protocol_error = dahdi_r2_on_protocol_error,
04309 .on_line_blocked = dahdi_r2_on_line_blocked,
04310 .on_line_idle = dahdi_r2_on_line_idle,
04311
04312 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04313 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04314 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04315
04316 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04317 };
04318
04319 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04320 {
04321 return AST_ALAW(sample);
04322 }
04323
04324 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04325 {
04326 return AST_LIN2A(sample);
04327 }
04328
04329 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04330 dahdi_r2_alaw_to_linear,
04331 dahdi_r2_linear_to_alaw
04332 };
04333
04334 #endif
04335
04336 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04337 {
04338 int tchan;
04339 int tinthreeway;
04340 struct ast_channel *towner;
04341
04342 ast_debug(1, "Swapping %d and %d\n", a, b);
04343
04344 tchan = p->subs[a].chan;
04345 towner = p->subs[a].owner;
04346 tinthreeway = p->subs[a].inthreeway;
04347
04348 p->subs[a].chan = p->subs[b].chan;
04349 p->subs[a].owner = p->subs[b].owner;
04350 p->subs[a].inthreeway = p->subs[b].inthreeway;
04351
04352 p->subs[b].chan = tchan;
04353 p->subs[b].owner = towner;
04354 p->subs[b].inthreeway = tinthreeway;
04355
04356 if (p->subs[a].owner)
04357 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04358 if (p->subs[b].owner)
04359 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04360 wakeup_sub(p, a);
04361 wakeup_sub(p, b);
04362 }
04363
04364 static int dahdi_open(char *fn)
04365 {
04366 int fd;
04367 int isnum;
04368 int chan = 0;
04369 int bs;
04370 int x;
04371 isnum = 1;
04372 for (x = 0; x < strlen(fn); x++) {
04373 if (!isdigit(fn[x])) {
04374 isnum = 0;
04375 break;
04376 }
04377 }
04378 if (isnum) {
04379 chan = atoi(fn);
04380 if (chan < 1) {
04381 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04382 return -1;
04383 }
04384 fn = "/dev/dahdi/channel";
04385 }
04386 fd = open(fn, O_RDWR | O_NONBLOCK);
04387 if (fd < 0) {
04388 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04389 return -1;
04390 }
04391 if (chan) {
04392 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04393 x = errno;
04394 close(fd);
04395 errno = x;
04396 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04397 return -1;
04398 }
04399 }
04400 bs = READ_SIZE;
04401 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04402 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04403 x = errno;
04404 close(fd);
04405 errno = x;
04406 return -1;
04407 }
04408 return fd;
04409 }
04410
04411 static void dahdi_close(int fd)
04412 {
04413 if (fd > 0)
04414 close(fd);
04415 }
04416
04417 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04418 {
04419 dahdi_close(chan_pvt->subs[sub_num].dfd);
04420 chan_pvt->subs[sub_num].dfd = -1;
04421 }
04422
04423 #if defined(HAVE_PRI)
04424 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04425 {
04426 dahdi_close(pri->pri.fds[fd_num]);
04427 pri->pri.fds[fd_num] = -1;
04428 }
04429 #endif
04430
04431 #if defined(HAVE_SS7)
04432 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04433 {
04434 dahdi_close(ss7->ss7.fds[fd_num]);
04435 ss7->ss7.fds[fd_num] = -1;
04436 }
04437 #endif
04438
04439 static int dahdi_setlinear(int dfd, int linear)
04440 {
04441 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04442 }
04443
04444
04445 static int alloc_sub(struct dahdi_pvt *p, int x)
04446 {
04447 struct dahdi_bufferinfo bi;
04448 int res;
04449 if (p->subs[x].dfd >= 0) {
04450 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04451 return -1;
04452 }
04453
04454 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04455 if (p->subs[x].dfd <= -1) {
04456 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04457 return -1;
04458 }
04459
04460 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04461 if (!res) {
04462 bi.txbufpolicy = p->buf_policy;
04463 bi.rxbufpolicy = p->buf_policy;
04464 bi.numbufs = p->buf_no;
04465 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04466 if (res < 0) {
04467 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04468 }
04469 } else
04470 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04471
04472 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04473 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04474 dahdi_close_sub(p, x);
04475 p->subs[x].dfd = -1;
04476 return -1;
04477 }
04478 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04479 return 0;
04480 }
04481
04482 static int unalloc_sub(struct dahdi_pvt *p, int x)
04483 {
04484 if (!x) {
04485 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04486 return -1;
04487 }
04488 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04489 dahdi_close_sub(p, x);
04490 p->subs[x].linear = 0;
04491 p->subs[x].chan = 0;
04492 p->subs[x].owner = NULL;
04493 p->subs[x].inthreeway = 0;
04494 p->polarity = POLARITY_IDLE;
04495 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04496 return 0;
04497 }
04498
04499 static int digit_to_dtmfindex(char digit)
04500 {
04501 if (isdigit(digit))
04502 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04503 else if (digit >= 'A' && digit <= 'D')
04504 return DAHDI_TONE_DTMF_A + (digit - 'A');
04505 else if (digit >= 'a' && digit <= 'd')
04506 return DAHDI_TONE_DTMF_A + (digit - 'a');
04507 else if (digit == '*')
04508 return DAHDI_TONE_DTMF_s;
04509 else if (digit == '#')
04510 return DAHDI_TONE_DTMF_p;
04511 else
04512 return -1;
04513 }
04514
04515 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04516 {
04517 struct dahdi_pvt *pvt;
04518 int idx;
04519 int dtmf = -1;
04520 int res;
04521
04522 pvt = chan->tech_pvt;
04523
04524 ast_mutex_lock(&pvt->lock);
04525
04526 idx = dahdi_get_index(chan, pvt, 0);
04527
04528 if ((idx != SUB_REAL) || !pvt->owner)
04529 goto out;
04530
04531 #ifdef HAVE_PRI
04532 switch (pvt->sig) {
04533 case SIG_PRI_LIB_HANDLE_CASES:
04534 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04535 if (!res)
04536 goto out;
04537 break;
04538 default:
04539 break;
04540 }
04541 #endif
04542 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04543 goto out;
04544
04545 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04546 struct dahdi_dialoperation zo = {
04547 .op = DAHDI_DIAL_OP_APPEND,
04548 };
04549
04550 zo.dialstr[0] = 'T';
04551 zo.dialstr[1] = digit;
04552 zo.dialstr[2] = '\0';
04553 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04554 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04555 chan->name, digit, strerror(errno));
04556 else
04557 pvt->dialing = 1;
04558 } else {
04559 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04560 chan->name, digit);
04561 pvt->dialing = 1;
04562 pvt->begindigit = digit;
04563 }
04564
04565 out:
04566 ast_mutex_unlock(&pvt->lock);
04567
04568 return 0;
04569 }
04570
04571 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04572 {
04573 struct dahdi_pvt *pvt;
04574 int res = 0;
04575 int idx;
04576 int x;
04577
04578 pvt = chan->tech_pvt;
04579
04580 ast_mutex_lock(&pvt->lock);
04581
04582 idx = dahdi_get_index(chan, pvt, 0);
04583
04584 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04585 goto out;
04586
04587 #ifdef HAVE_PRI
04588
04589 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04590 goto out;
04591 }
04592 #endif
04593
04594 if (pvt->begindigit) {
04595 x = -1;
04596 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04597 chan->name, digit);
04598 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04599 pvt->dialing = 0;
04600 pvt->begindigit = 0;
04601 }
04602
04603 out:
04604 ast_mutex_unlock(&pvt->lock);
04605
04606 return res;
04607 }
04608
04609 static const char * const events[] = {
04610 "No event",
04611 "On hook",
04612 "Ring/Answered",
04613 "Wink/Flash",
04614 "Alarm",
04615 "No more alarm",
04616 "HDLC Abort",
04617 "HDLC Overrun",
04618 "HDLC Bad FCS",
04619 "Dial Complete",
04620 "Ringer On",
04621 "Ringer Off",
04622 "Hook Transition Complete",
04623 "Bits Changed",
04624 "Pulse Start",
04625 "Timer Expired",
04626 "Timer Ping",
04627 "Polarity Reversal",
04628 "Ring Begin",
04629 };
04630
04631 static struct {
04632 int alarm;
04633 char *name;
04634 } alarms[] = {
04635 { DAHDI_ALARM_RED, "Red Alarm" },
04636 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04637 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04638 { DAHDI_ALARM_RECOVER, "Recovering" },
04639 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04640 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04641 { DAHDI_ALARM_NONE, "None" },
04642 };
04643
04644 static char *alarm2str(int alm)
04645 {
04646 int x;
04647 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04648 if (alarms[x].alarm & alm)
04649 return alarms[x].name;
04650 }
04651 return alm ? "Unknown Alarm" : "No Alarm";
04652 }
04653
04654 static const char *event2str(int event)
04655 {
04656 static char buf[256];
04657 if ((event < (ARRAY_LEN(events))) && (event > -1))
04658 return events[event];
04659 sprintf(buf, "Event %d", event);
04660 return buf;
04661 }
04662
04663 static char *dahdi_sig2str(int sig)
04664 {
04665 static char buf[256];
04666 switch (sig) {
04667 case SIG_EM:
04668 return "E & M Immediate";
04669 case SIG_EMWINK:
04670 return "E & M Wink";
04671 case SIG_EM_E1:
04672 return "E & M E1";
04673 case SIG_FEATD:
04674 return "Feature Group D (DTMF)";
04675 case SIG_FEATDMF:
04676 return "Feature Group D (MF)";
04677 case SIG_FEATDMF_TA:
04678 return "Feature Groud D (MF) Tandem Access";
04679 case SIG_FEATB:
04680 return "Feature Group B (MF)";
04681 case SIG_E911:
04682 return "E911 (MF)";
04683 case SIG_FGC_CAMA:
04684 return "FGC/CAMA (Dialpulse)";
04685 case SIG_FGC_CAMAMF:
04686 return "FGC/CAMA (MF)";
04687 case SIG_FXSLS:
04688 return "FXS Loopstart";
04689 case SIG_FXSGS:
04690 return "FXS Groundstart";
04691 case SIG_FXSKS:
04692 return "FXS Kewlstart";
04693 case SIG_FXOLS:
04694 return "FXO Loopstart";
04695 case SIG_FXOGS:
04696 return "FXO Groundstart";
04697 case SIG_FXOKS:
04698 return "FXO Kewlstart";
04699 case SIG_PRI:
04700 return "ISDN PRI";
04701 case SIG_BRI:
04702 return "ISDN BRI Point to Point";
04703 case SIG_BRI_PTMP:
04704 return "ISDN BRI Point to MultiPoint";
04705 case SIG_SS7:
04706 return "SS7";
04707 case SIG_MFCR2:
04708 return "MFC/R2";
04709 case SIG_SF:
04710 return "SF (Tone) Immediate";
04711 case SIG_SFWINK:
04712 return "SF (Tone) Wink";
04713 case SIG_SF_FEATD:
04714 return "SF (Tone) with Feature Group D (DTMF)";
04715 case SIG_SF_FEATDMF:
04716 return "SF (Tone) with Feature Group D (MF)";
04717 case SIG_SF_FEATB:
04718 return "SF (Tone) with Feature Group B (MF)";
04719 case 0:
04720 return "Pseudo";
04721 default:
04722 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04723 return buf;
04724 }
04725 }
04726
04727 #define sig2str dahdi_sig2str
04728
04729 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04730 {
04731
04732
04733 struct dahdi_confinfo zi;
04734
04735 memset(&zi, 0, sizeof(zi));
04736 zi.chan = 0;
04737
04738 if (slavechannel > 0) {
04739
04740 zi.confmode = DAHDI_CONF_DIGITALMON;
04741 zi.confno = slavechannel;
04742 } else {
04743 if (!idx) {
04744
04745 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04746 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04747 } else
04748 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04749 zi.confno = p->confno;
04750 }
04751 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04752 return 0;
04753 if (c->dfd < 0)
04754 return 0;
04755 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04756 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04757 return -1;
04758 }
04759 if (slavechannel < 1) {
04760 p->confno = zi.confno;
04761 }
04762 c->curconf = zi;
04763 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04764 return 0;
04765 }
04766
04767 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04768 {
04769
04770 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04771 return 1;
04772
04773 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04774 return 1;
04775 return 0;
04776 }
04777
04778 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04779 {
04780 struct dahdi_confinfo zi;
04781 if (
04782 (c->dfd < 0) ||
04783
04784 !isourconf(p, c)
04785
04786 ) return 0;
04787 memset(&zi, 0, sizeof(zi));
04788 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04789 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04790 return -1;
04791 }
04792 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04793 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04794 return 0;
04795 }
04796
04797 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04798 {
04799 int x;
04800 int useslavenative;
04801 struct dahdi_pvt *slave = NULL;
04802
04803 useslavenative = 1;
04804
04805 for (x = 0; x < 3; x++) {
04806
04807
04808 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04809 useslavenative = 0;
04810 }
04811
04812
04813 if (useslavenative) {
04814 for (x = 0; x < MAX_SLAVES; x++) {
04815 if (p->slaves[x]) {
04816 if (slave) {
04817
04818
04819 slave = NULL;
04820 useslavenative = 0;
04821 break;
04822 } else {
04823
04824 slave = p->slaves[x];
04825 }
04826 }
04827 }
04828 }
04829
04830 if (!slave)
04831 useslavenative = 0;
04832 else if (slave->law != p->law) {
04833 useslavenative = 0;
04834 slave = NULL;
04835 }
04836 if (out)
04837 *out = slave;
04838 return useslavenative;
04839 }
04840
04841 static int reset_conf(struct dahdi_pvt *p)
04842 {
04843 p->confno = -1;
04844 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04845 if (p->subs[SUB_REAL].dfd > -1) {
04846 struct dahdi_confinfo zi;
04847
04848 memset(&zi, 0, sizeof(zi));
04849 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04850 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04851 }
04852 return 0;
04853 }
04854
04855 static int update_conf(struct dahdi_pvt *p)
04856 {
04857 int needconf = 0;
04858 int x;
04859 int useslavenative;
04860 struct dahdi_pvt *slave = NULL;
04861
04862 useslavenative = isslavenative(p, &slave);
04863
04864 for (x = 0; x < 3; x++) {
04865
04866 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04867 conf_add(p, &p->subs[x], x, 0);
04868 needconf++;
04869 } else {
04870 conf_del(p, &p->subs[x], x);
04871 }
04872 }
04873
04874
04875 for (x = 0; x < MAX_SLAVES; x++) {
04876 if (p->slaves[x]) {
04877 if (useslavenative)
04878 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04879 else {
04880 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04881 needconf++;
04882 }
04883 }
04884 }
04885
04886 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04887 if (useslavenative)
04888 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04889 else {
04890 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04891 needconf++;
04892 }
04893 }
04894
04895 if (p->master) {
04896 if (isslavenative(p->master, NULL)) {
04897 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04898 } else {
04899 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04900 }
04901 }
04902 if (!needconf) {
04903
04904
04905 p->confno = -1;
04906 }
04907 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04908 return 0;
04909 }
04910
04911 static void dahdi_enable_ec(struct dahdi_pvt *p)
04912 {
04913 int res;
04914 if (!p)
04915 return;
04916 if (p->echocanon) {
04917 ast_debug(1, "Echo cancellation already on\n");
04918 return;
04919 }
04920 if (p->digital) {
04921 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04922 return;
04923 }
04924 if (p->echocancel.head.tap_length) {
04925 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04926 switch (p->sig) {
04927 #if defined(HAVE_PRI)
04928 case SIG_PRI_LIB_HANDLE_CASES:
04929 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04930
04931
04932
04933
04934 return;
04935 }
04936
04937 #endif
04938 #if defined(HAVE_SS7)
04939 case SIG_SS7:
04940 #endif
04941 {
04942 int x = 1;
04943
04944 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04945 if (res)
04946 ast_log(LOG_WARNING,
04947 "Unable to enable audio mode on channel %d (%s)\n",
04948 p->channel, strerror(errno));
04949 }
04950 break;
04951 default:
04952 break;
04953 }
04954 #endif
04955 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04956 if (res) {
04957 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04958 } else {
04959 p->echocanon = 1;
04960 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04961 }
04962 } else
04963 ast_debug(1, "No echo cancellation requested\n");
04964 }
04965
04966 static void dahdi_train_ec(struct dahdi_pvt *p)
04967 {
04968 int x;
04969 int res;
04970
04971 if (p && p->echocanon && p->echotraining) {
04972 x = p->echotraining;
04973 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04974 if (res)
04975 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04976 else
04977 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04978 } else {
04979 ast_debug(1, "No echo training requested\n");
04980 }
04981 }
04982
04983 static void dahdi_disable_ec(struct dahdi_pvt *p)
04984 {
04985 int res;
04986
04987 if (p->echocanon) {
04988 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04989
04990 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04991
04992 if (res)
04993 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04994 else
04995 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04996 }
04997
04998 p->echocanon = 0;
04999 }
05000
05001
05002 static int drc_sample(int sample, float drc)
05003 {
05004 float neg;
05005 float shallow, steep;
05006 float max = SHRT_MAX;
05007
05008 neg = (sample < 0 ? -1 : 1);
05009 steep = drc*sample;
05010 shallow = neg*(max-max/drc)+(float)sample/drc;
05011 if (abs(steep) < abs(shallow)) {
05012 sample = steep;
05013 }
05014 else {
05015 sample = shallow;
05016 }
05017
05018 return sample;
05019 }
05020
05021
05022 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05023 {
05024 int j;
05025 int k;
05026
05027 float linear_gain = pow(10.0, gain / 20.0);
05028
05029 switch (law) {
05030 case DAHDI_LAW_ALAW:
05031 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05032 if (gain || drc) {
05033 k = AST_ALAW(j);
05034 if (drc) {
05035 k = drc_sample(k, drc);
05036 }
05037 k = (float)k*linear_gain;
05038 if (k > 32767) k = 32767;
05039 if (k < -32767) k = -32767;
05040 g->txgain[j] = AST_LIN2A(k);
05041 } else {
05042 g->txgain[j] = j;
05043 }
05044 }
05045 break;
05046 case DAHDI_LAW_MULAW:
05047 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05048 if (gain || drc) {
05049 k = AST_MULAW(j);
05050 if (drc) {
05051 k = drc_sample(k, drc);
05052 }
05053 k = (float)k*linear_gain;
05054 if (k > 32767) k = 32767;
05055 if (k < -32767) k = -32767;
05056 g->txgain[j] = AST_LIN2MU(k);
05057
05058 } else {
05059 g->txgain[j] = j;
05060 }
05061 }
05062 break;
05063 }
05064 }
05065
05066 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05067 {
05068 int j;
05069 int k;
05070 float linear_gain = pow(10.0, gain / 20.0);
05071
05072 switch (law) {
05073 case DAHDI_LAW_ALAW:
05074 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05075 if (gain || drc) {
05076 k = AST_ALAW(j);
05077 if (drc) {
05078 k = drc_sample(k, drc);
05079 }
05080 k = (float)k*linear_gain;
05081 if (k > 32767) k = 32767;
05082 if (k < -32767) k = -32767;
05083 g->rxgain[j] = AST_LIN2A(k);
05084 } else {
05085 g->rxgain[j] = j;
05086 }
05087 }
05088 break;
05089 case DAHDI_LAW_MULAW:
05090 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05091 if (gain || drc) {
05092 k = AST_MULAW(j);
05093 if (drc) {
05094 k = drc_sample(k, drc);
05095 }
05096 k = (float)k*linear_gain;
05097 if (k > 32767) k = 32767;
05098 if (k < -32767) k = -32767;
05099 g->rxgain[j] = AST_LIN2MU(k);
05100 } else {
05101 g->rxgain[j] = j;
05102 }
05103 }
05104 break;
05105 }
05106 }
05107
05108 static int set_actual_txgain(int fd, float gain, float drc, int law)
05109 {
05110 struct dahdi_gains g;
05111 int res;
05112
05113 memset(&g, 0, sizeof(g));
05114 res = ioctl(fd, DAHDI_GETGAINS, &g);
05115 if (res) {
05116 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05117 return res;
05118 }
05119
05120 fill_txgain(&g, gain, drc, law);
05121
05122 return ioctl(fd, DAHDI_SETGAINS, &g);
05123 }
05124
05125 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05126 {
05127 struct dahdi_gains g;
05128 int res;
05129
05130 memset(&g, 0, sizeof(g));
05131 res = ioctl(fd, DAHDI_GETGAINS, &g);
05132 if (res) {
05133 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05134 return res;
05135 }
05136
05137 fill_rxgain(&g, gain, drc, law);
05138
05139 return ioctl(fd, DAHDI_SETGAINS, &g);
05140 }
05141
05142 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05143 {
05144 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05145 }
05146
05147 static int bump_gains(struct dahdi_pvt *p)
05148 {
05149 int res;
05150
05151
05152 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05153 if (res) {
05154 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05155 return -1;
05156 }
05157
05158 return 0;
05159 }
05160
05161 static int restore_gains(struct dahdi_pvt *p)
05162 {
05163 int res;
05164
05165 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05166 if (res) {
05167 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05168 return -1;
05169 }
05170
05171 return 0;
05172 }
05173
05174 static inline int dahdi_set_hook(int fd, int hs)
05175 {
05176 int x, res;
05177
05178 x = hs;
05179 res = ioctl(fd, DAHDI_HOOK, &x);
05180
05181 if (res < 0) {
05182 if (errno == EINPROGRESS)
05183 return 0;
05184 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05185
05186 }
05187
05188 return res;
05189 }
05190
05191 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05192 {
05193 int x, res;
05194
05195 x = muted;
05196 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05197 switch (p->sig) {
05198 #if defined(HAVE_PRI)
05199 case SIG_PRI_LIB_HANDLE_CASES:
05200 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05201
05202 break;
05203 }
05204
05205 #endif
05206 #if defined(HAVE_SS7)
05207 case SIG_SS7:
05208 #endif
05209 {
05210 int y = 1;
05211
05212 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05213 if (res)
05214 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05215 p->channel, strerror(errno));
05216 }
05217 break;
05218 default:
05219 break;
05220 }
05221 #endif
05222 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05223 if (res < 0)
05224 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05225 return res;
05226 }
05227
05228 static int save_conference(struct dahdi_pvt *p)
05229 {
05230 struct dahdi_confinfo c;
05231 int res;
05232 if (p->saveconf.confmode) {
05233 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05234 return -1;
05235 }
05236 p->saveconf.chan = 0;
05237 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05238 if (res) {
05239 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05240 p->saveconf.confmode = 0;
05241 return -1;
05242 }
05243 memset(&c, 0, sizeof(c));
05244 c.confmode = DAHDI_CONF_NORMAL;
05245 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05246 if (res) {
05247 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05248 return -1;
05249 }
05250 ast_debug(1, "Disabled conferencing\n");
05251 return 0;
05252 }
05253
05254 static int restore_conference(struct dahdi_pvt *p)
05255 {
05256 int res;
05257 if (p->saveconf.confmode) {
05258 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05259 p->saveconf.confmode = 0;
05260 if (res) {
05261 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05262 return -1;
05263 }
05264 ast_debug(1, "Restored conferencing\n");
05265 }
05266 return 0;
05267 }
05268
05269 static int send_cwcidspill(struct dahdi_pvt *p)
05270 {
05271 p->callwaitcas = 0;
05272 p->cidcwexpire = 0;
05273 p->cid_suppress_expire = 0;
05274 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05275 return -1;
05276 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05277
05278 p->cidlen += READ_SIZE * 4;
05279 p->cidpos = 0;
05280 send_callerid(p);
05281 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05282 return 0;
05283 }
05284
05285 static int has_voicemail(struct dahdi_pvt *p)
05286 {
05287 int new_msgs;
05288 struct ast_event *event;
05289 char *mailbox, *context;
05290
05291 mailbox = context = ast_strdupa(p->mailbox);
05292 strsep(&context, "@");
05293 if (ast_strlen_zero(context))
05294 context = "default";
05295
05296 event = ast_event_get_cached(AST_EVENT_MWI,
05297 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05298 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05299 AST_EVENT_IE_END);
05300
05301 if (event) {
05302 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05303 ast_event_destroy(event);
05304 } else
05305 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05306
05307 return new_msgs;
05308 }
05309
05310
05311
05312 static int send_callerid(struct dahdi_pvt *p)
05313 {
05314
05315 int res;
05316
05317 if (p->subs[SUB_REAL].linear) {
05318 p->subs[SUB_REAL].linear = 0;
05319 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05320 }
05321 while (p->cidpos < p->cidlen) {
05322 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05323 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05324 if (res < 0) {
05325 if (errno == EAGAIN)
05326 return 0;
05327 else {
05328 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05329 return -1;
05330 }
05331 }
05332 if (!res)
05333 return 0;
05334 p->cidpos += res;
05335 }
05336 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05337 ast_free(p->cidspill);
05338 p->cidspill = NULL;
05339 if (p->callwaitcas) {
05340
05341 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05342 p->cid_suppress_expire = p->cidcwexpire;
05343 } else
05344 restore_conference(p);
05345 return 0;
05346 }
05347
05348 static int dahdi_callwait(struct ast_channel *ast)
05349 {
05350 struct dahdi_pvt *p = ast->tech_pvt;
05351 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05352 if (p->cidspill) {
05353 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05354 ast_free(p->cidspill);
05355 }
05356
05357
05358
05359
05360
05361 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05362 return -1;
05363 save_conference(p);
05364
05365 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05366 if (!p->callwaitrings && p->callwaitingcallerid) {
05367 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05368 p->callwaitcas = 1;
05369 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05370 } else {
05371 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05372 p->callwaitcas = 0;
05373 p->cidlen = 2400 + READ_SIZE * 4;
05374 }
05375 p->cidpos = 0;
05376 send_callerid(p);
05377
05378 return 0;
05379 }
05380
05381 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05382 {
05383 struct dahdi_pvt *p = ast->tech_pvt;
05384 int x, res, mysig;
05385 char dest[256];
05386
05387 ast_mutex_lock(&p->lock);
05388 ast_copy_string(dest, rdest, sizeof(dest));
05389 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05390 if ((ast->_state == AST_STATE_BUSY)) {
05391 p->subs[SUB_REAL].needbusy = 1;
05392 ast_mutex_unlock(&p->lock);
05393 return 0;
05394 }
05395 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05396 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05397 ast_mutex_unlock(&p->lock);
05398 return -1;
05399 }
05400 p->waitingfordt.tv_sec = 0;
05401 p->dialednone = 0;
05402 if ((p->radio || (p->oprmode < 0)))
05403 {
05404
05405 ast_setstate(ast, AST_STATE_UP);
05406 ast_mutex_unlock(&p->lock);
05407 return 0;
05408 }
05409 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05410 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05411 if (res)
05412 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05413 p->outgoing = 1;
05414
05415 if (IS_DIGITAL(ast->transfercapability)){
05416 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05417 } else {
05418 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05419 }
05420
05421 #ifdef HAVE_PRI
05422 if (dahdi_sig_pri_lib_handles(p->sig)) {
05423 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05424 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05425 ast_mutex_unlock(&p->lock);
05426 return res;
05427 }
05428 #endif
05429
05430 #if defined(HAVE_SS7)
05431 if (p->sig == SIG_SS7) {
05432 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05433 ast_mutex_unlock(&p->lock);
05434 return res;
05435 }
05436 #endif
05437
05438
05439 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05440 p->callwaitrings = 0;
05441 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05442 ast_mutex_unlock(&p->lock);
05443 return res;
05444 }
05445
05446 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05447 switch (mysig) {
05448 case 0:
05449
05450 ast_setstate(ast, AST_STATE_UP);
05451 break;
05452 case SIG_MFCR2:
05453 break;
05454 default:
05455 ast_debug(1, "not yet implemented\n");
05456 ast_mutex_unlock(&p->lock);
05457 return -1;
05458 }
05459
05460 #ifdef HAVE_OPENR2
05461 if (p->mfcr2) {
05462 openr2_calling_party_category_t chancat;
05463 int callres = 0;
05464 char *c, *l;
05465
05466
05467 p->dialdest[0] = '\0';
05468
05469 c = strchr(dest, '/');
05470 if (c) {
05471 c++;
05472 } else {
05473 c = "";
05474 }
05475 if (!p->hidecallerid) {
05476 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05477 } else {
05478 l = NULL;
05479 }
05480 if (strlen(c) < p->stripmsd) {
05481 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05482 ast_mutex_unlock(&p->lock);
05483 return -1;
05484 }
05485 p->dialing = 1;
05486 chancat = dahdi_r2_get_channel_category(ast);
05487 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05488 if (-1 == callres) {
05489 ast_mutex_unlock(&p->lock);
05490 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05491 return -1;
05492 }
05493 p->mfcr2_call_accepted = 0;
05494 p->mfcr2_progress = 0;
05495 ast_setstate(ast, AST_STATE_DIALING);
05496 }
05497 #endif
05498 ast_mutex_unlock(&p->lock);
05499 return 0;
05500 }
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513
05514
05515
05516
05517 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05518 {
05519 struct dahdi_pvt *cur;
05520
05521 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05522
05523
05524 for (cur = iflist; cur; cur = cur->next) {
05525 if (pvt->channel < cur->channel) {
05526
05527 pvt->prev = cur->prev;
05528 pvt->next = cur;
05529 if (cur->prev) {
05530
05531 cur->prev->next = pvt;
05532 } else {
05533
05534 iflist = pvt;
05535 }
05536 cur->prev = pvt;
05537 return;
05538 }
05539 }
05540
05541
05542 pvt->prev = ifend;
05543 pvt->next = NULL;
05544 if (ifend) {
05545 ifend->next = pvt;
05546 }
05547 ifend = pvt;
05548 if (!iflist) {
05549
05550 iflist = pvt;
05551 }
05552 }
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05568 {
05569
05570 if (pvt->prev) {
05571 pvt->prev->next = pvt->next;
05572 } else if (iflist == pvt) {
05573
05574 iflist = pvt->next;
05575 }
05576
05577
05578 if (pvt->next) {
05579 pvt->next->prev = pvt->prev;
05580 } else if (ifend == pvt) {
05581
05582 ifend = pvt->prev;
05583 }
05584
05585
05586 pvt->which_iflist = DAHDI_IFLIST_NONE;
05587 pvt->prev = NULL;
05588 pvt->next = NULL;
05589 }
05590
05591 #if defined(HAVE_PRI)
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05609 {
05610 struct dahdi_pvt *cur;
05611
05612 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05613
05614
05615 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05616 if (pvt->channel < cur->channel) {
05617
05618 pvt->prev = cur->prev;
05619 pvt->next = cur;
05620 if (cur->prev) {
05621
05622 cur->prev->next = pvt;
05623 } else {
05624
05625 pri->no_b_chan_iflist = pvt;
05626 }
05627 cur->prev = pvt;
05628 return;
05629 }
05630 }
05631
05632
05633 pvt->prev = pri->no_b_chan_end;
05634 pvt->next = NULL;
05635 if (pri->no_b_chan_end) {
05636 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05637 }
05638 pri->no_b_chan_end = pvt;
05639 if (!pri->no_b_chan_iflist) {
05640
05641 pri->no_b_chan_iflist = pvt;
05642 }
05643 }
05644 #endif
05645
05646 #if defined(HAVE_PRI)
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05662 {
05663
05664 if (pvt->prev) {
05665 pvt->prev->next = pvt->next;
05666 } else if (pri->no_b_chan_iflist == pvt) {
05667
05668 pri->no_b_chan_iflist = pvt->next;
05669 }
05670
05671
05672 if (pvt->next) {
05673 pvt->next->prev = pvt->prev;
05674 } else if (pri->no_b_chan_end == pvt) {
05675
05676 pri->no_b_chan_end = pvt->prev;
05677 }
05678
05679
05680 pvt->which_iflist = DAHDI_IFLIST_NONE;
05681 pvt->prev = NULL;
05682 pvt->next = NULL;
05683 }
05684 #endif
05685
05686 #if defined(HAVE_PRI)
05687
05688
05689
05690
05691
05692
05693
05694
05695
05696 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05697 {
05698 unsigned idx;
05699 struct sig_pri_span *pri;
05700
05701 pri = pvt->pri;
05702 if (!pri) {
05703
05704 return;
05705 }
05706 ast_mutex_lock(&pri->lock);
05707 for (idx = 0; idx < pri->numchans; ++idx) {
05708 if (pri->pvts[idx] == pvt->sig_pvt) {
05709 pri->pvts[idx] = NULL;
05710 ast_mutex_unlock(&pri->lock);
05711 return;
05712 }
05713 }
05714 ast_mutex_unlock(&pri->lock);
05715 }
05716 #endif
05717
05718 #if defined(HAVE_SS7)
05719
05720
05721
05722
05723
05724
05725
05726
05727
05728 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05729 {
05730 unsigned idx;
05731 struct sig_ss7_linkset *ss7;
05732
05733 ss7 = pvt->ss7;
05734 if (!ss7) {
05735
05736 return;
05737 }
05738 ast_mutex_lock(&ss7->lock);
05739 for (idx = 0; idx < ss7->numchans; ++idx) {
05740 if (ss7->pvts[idx] == pvt->sig_pvt) {
05741 ss7->pvts[idx] = NULL;
05742 ast_mutex_unlock(&ss7->lock);
05743 return;
05744 }
05745 }
05746 ast_mutex_unlock(&ss7->lock);
05747 }
05748 #endif
05749
05750 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05751 {
05752 if (cur->next && cur->next->span == cur->span) {
05753 return cur->next;
05754 } else if (cur->prev && cur->prev->span == cur->span) {
05755 return cur->prev;
05756 }
05757
05758 return NULL;
05759 }
05760
05761 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05762 {
05763 struct dahdi_pvt *p = pvt;
05764
05765 if (p->manages_span_alarms) {
05766 struct dahdi_pvt *next = find_next_iface_in_span(p);
05767 if (next) {
05768 next->manages_span_alarms = 1;
05769 }
05770 }
05771
05772
05773 #if defined(HAVE_PRI)
05774 dahdi_unlink_pri_pvt(p);
05775 #endif
05776 #if defined(HAVE_SS7)
05777 dahdi_unlink_ss7_pvt(p);
05778 #endif
05779 switch (pvt->which_iflist) {
05780 case DAHDI_IFLIST_NONE:
05781 break;
05782 case DAHDI_IFLIST_MAIN:
05783 dahdi_iflist_extract(p);
05784 break;
05785 #if defined(HAVE_PRI)
05786 case DAHDI_IFLIST_NO_B_CHAN:
05787 if (p->pri) {
05788 dahdi_nobch_extract(p->pri, p);
05789 }
05790 break;
05791 #endif
05792 }
05793
05794 if (p->sig_pvt) {
05795 if (analog_lib_handles(p->sig, 0, 0)) {
05796 analog_delete(p->sig_pvt);
05797 }
05798 switch (p->sig) {
05799 #if defined(HAVE_PRI)
05800 case SIG_PRI_LIB_HANDLE_CASES:
05801 sig_pri_chan_delete(p->sig_pvt);
05802 break;
05803 #endif
05804 #if defined(HAVE_SS7)
05805 case SIG_SS7:
05806 sig_ss7_chan_delete(p->sig_pvt);
05807 break;
05808 #endif
05809 default:
05810 break;
05811 }
05812 }
05813 ast_free(p->cidspill);
05814 if (p->use_smdi)
05815 ast_smdi_interface_unref(p->smdi_iface);
05816 if (p->mwi_event_sub)
05817 ast_event_unsubscribe(p->mwi_event_sub);
05818 if (p->vars) {
05819 ast_variables_destroy(p->vars);
05820 }
05821 if (p->cc_params) {
05822 ast_cc_config_params_destroy(p->cc_params);
05823 }
05824 ast_mutex_destroy(&p->lock);
05825 dahdi_close_sub(p, SUB_REAL);
05826 if (p->owner)
05827 p->owner->tech_pvt = NULL;
05828 ast_free(p);
05829 }
05830
05831 static void destroy_channel(struct dahdi_pvt *cur, int now)
05832 {
05833 int i;
05834
05835 if (!now) {
05836
05837 if (cur->owner) {
05838 return;
05839 }
05840 for (i = 0; i < 3; i++) {
05841 if (cur->subs[i].owner) {
05842 return;
05843 }
05844 }
05845 }
05846 destroy_dahdi_pvt(cur);
05847 }
05848
05849 static void destroy_all_channels(void)
05850 {
05851 int chan;
05852 #if defined(HAVE_PRI)
05853 unsigned span;
05854 struct sig_pri_span *pri;
05855 #endif
05856 struct dahdi_pvt *p;
05857
05858 while (num_restart_pending) {
05859 usleep(1);
05860 }
05861
05862 ast_mutex_lock(&iflock);
05863
05864 while (iflist) {
05865 p = iflist;
05866
05867 chan = p->channel;
05868 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05869 {
05870 char db_chan_name[20];
05871 char db_answer[5];
05872 char state;
05873 int why = -1;
05874
05875 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05876 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05877 sscanf(db_answer, "%1c:%30d", &state, &why);
05878 }
05879 if (!why) {
05880
05881 ast_db_del(db_chan_name, SRVST_DBKEY);
05882 }
05883 }
05884 #endif
05885
05886 destroy_dahdi_pvt(p);
05887 ast_verb(3, "Unregistered channel %d\n", chan);
05888 }
05889 ifcount = 0;
05890 ast_mutex_unlock(&iflock);
05891
05892 #if defined(HAVE_PRI)
05893
05894 for (span = 0; span < NUM_SPANS; ++span) {
05895 if (!pris[span].dchannels[0]) {
05896 break;
05897 }
05898 pri = &pris[span].pri;
05899 ast_mutex_lock(&pri->lock);
05900 while (pri->no_b_chan_iflist) {
05901 p = pri->no_b_chan_iflist;
05902
05903
05904 destroy_dahdi_pvt(p);
05905 }
05906 ast_mutex_unlock(&pri->lock);
05907 }
05908 #endif
05909 }
05910
05911 #if defined(HAVE_PRI)
05912 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05913
05914 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05915 {
05916
05917 struct dahdi_pvt *p;
05918
05919 if (ast_strlen_zero(digits)) {
05920 ast_debug(1, "No digit string sent to application!\n");
05921 return -1;
05922 }
05923
05924 p = (struct dahdi_pvt *)chan->tech_pvt;
05925
05926 if (!p) {
05927 ast_debug(1, "Unable to find technology private\n");
05928 return -1;
05929 }
05930
05931 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05932
05933 return 0;
05934 }
05935 #endif
05936
05937 #if defined(HAVE_PRI)
05938 #if defined(HAVE_PRI_PROG_W_CAUSE)
05939 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05940
05941 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05942 {
05943
05944 struct dahdi_pvt *pvt;
05945 char *parse;
05946 int res;
05947 AST_DECLARE_APP_ARGS(args,
05948 AST_APP_ARG(destination);
05949 AST_APP_ARG(original);
05950 AST_APP_ARG(reason);
05951 );
05952
05953 if (ast_strlen_zero(data)) {
05954 ast_log(LOG_DEBUG, "No data sent to application!\n");
05955 return -1;
05956 }
05957 if (chan->tech != &dahdi_tech) {
05958 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05959 return -1;
05960 }
05961 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05962 if (!pvt) {
05963 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05964 return -1;
05965 }
05966 switch (pvt->sig) {
05967 case SIG_PRI_LIB_HANDLE_CASES:
05968 break;
05969 default:
05970 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05971 chan->name);
05972 return -1;
05973 }
05974
05975 parse = ast_strdupa(data);
05976 AST_STANDARD_APP_ARGS(args, parse);
05977
05978 if (ast_strlen_zero(args.destination)) {
05979 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05980 return -1;
05981 }
05982
05983 if (ast_strlen_zero(args.original)) {
05984 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05985 args.original = NULL;
05986 }
05987
05988 if (ast_strlen_zero(args.reason)) {
05989 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05990 args.reason = NULL;
05991 }
05992
05993 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05994 args.destination, args.original, args.reason);
05995 if (!res) {
05996
05997
05998
05999
06000 ast_safe_sleep(chan, 5000);
06001 }
06002
06003 return -1;
06004 }
06005 #endif
06006 #endif
06007
06008 #if defined(HAVE_OPENR2)
06009 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
06010
06011 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
06012 {
06013
06014 openr2_call_mode_t accept_mode;
06015 int res, timeout, maxloops;
06016 struct ast_frame *f;
06017 struct dahdi_pvt *p;
06018 char *parse;
06019 AST_DECLARE_APP_ARGS(args,
06020 AST_APP_ARG(charge);
06021 );
06022
06023 if (ast_strlen_zero(data)) {
06024 ast_log(LOG_DEBUG, "No data sent to application!\n");
06025 return -1;
06026 }
06027
06028 if (chan->tech != &dahdi_tech) {
06029 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06030 return -1;
06031 }
06032
06033 p = (struct dahdi_pvt *)chan->tech_pvt;
06034 if (!p) {
06035 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06036 return -1;
06037 }
06038
06039 parse = ast_strdupa(data);
06040 AST_STANDARD_APP_ARGS(args, parse);
06041
06042 if (ast_strlen_zero(args.charge)) {
06043 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06044 return -1;
06045 }
06046
06047 ast_mutex_lock(&p->lock);
06048 if (!p->mfcr2 || !p->mfcr2call) {
06049 ast_mutex_unlock(&p->lock);
06050 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06051 return -1;
06052 }
06053
06054 if (p->mfcr2_call_accepted) {
06055 ast_mutex_unlock(&p->lock);
06056 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06057 return 0;
06058 }
06059 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06060 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06061 ast_mutex_unlock(&p->lock);
06062 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06063 return -1;
06064 }
06065 ast_mutex_unlock(&p->lock);
06066
06067 res = 0;
06068 timeout = 100;
06069 maxloops = 50;
06070
06071 while (maxloops > 0) {
06072 maxloops--;
06073 if (ast_check_hangup(chan)) {
06074 break;
06075 }
06076 res = ast_waitfor(chan, timeout);
06077 if (res < 0) {
06078 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06079 res = -1;
06080 break;
06081 }
06082 if (res == 0) {
06083 continue;
06084 }
06085 res = 0;
06086 f = ast_read(chan);
06087 if (!f) {
06088 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06089 res = -1;
06090 break;
06091 }
06092 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06093 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06094 ast_frfree(f);
06095 res = -1;
06096 break;
06097 }
06098 ast_frfree(f);
06099 ast_mutex_lock(&p->lock);
06100 if (p->mfcr2_call_accepted) {
06101 ast_mutex_unlock(&p->lock);
06102 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06103 break;
06104 }
06105 ast_mutex_unlock(&p->lock);
06106 }
06107 if (res == -1) {
06108 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06109 }
06110 return res;
06111 }
06112
06113 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06114 {
06115 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06116 switch (cause) {
06117 case AST_CAUSE_USER_BUSY:
06118 case AST_CAUSE_CALL_REJECTED:
06119 case AST_CAUSE_INTERWORKING:
06120 r2cause = OR2_CAUSE_BUSY_NUMBER;
06121 break;
06122
06123 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06124 case AST_CAUSE_SWITCH_CONGESTION:
06125 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06126 break;
06127
06128 case AST_CAUSE_UNALLOCATED:
06129 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06130 break;
06131
06132 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06133 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06134 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06135 break;
06136
06137 case AST_CAUSE_NO_ANSWER:
06138 case AST_CAUSE_NO_USER_RESPONSE:
06139 r2cause = OR2_CAUSE_NO_ANSWER;
06140 break;
06141
06142 default:
06143 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06144 break;
06145 }
06146 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06147 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06148 return r2cause;
06149 }
06150 #endif
06151
06152 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06153 {
06154 if (p->bufferoverrideinuse) {
06155
06156 struct dahdi_bufferinfo bi = {
06157 .txbufpolicy = p->buf_policy,
06158 .rxbufpolicy = p->buf_policy,
06159 .bufsize = p->bufsize,
06160 .numbufs = p->buf_no
06161 };
06162 int bpres;
06163
06164 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06165 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06166 }
06167 p->bufferoverrideinuse = 0;
06168 return bpres;
06169 }
06170
06171 return -1;
06172 }
06173
06174 static int dahdi_hangup(struct ast_channel *ast)
06175 {
06176 int res = 0;
06177 int idx,x;
06178 int law;
06179
06180 struct dahdi_pvt *p = ast->tech_pvt;
06181 struct dahdi_params par;
06182
06183 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06184 if (!ast->tech_pvt) {
06185 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06186 return 0;
06187 }
06188
06189 ast_mutex_lock(&p->lock);
06190 p->exten[0] = '\0';
06191 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06192 dahdi_confmute(p, 0);
06193 restore_gains(p);
06194 p->ignoredtmf = 0;
06195 p->waitingfordt.tv_sec = 0;
06196
06197 res = analog_hangup(p->sig_pvt, ast);
06198 revert_fax_buffers(p, ast);
06199
06200 goto hangup_out;
06201 } else {
06202 p->cid_num[0] = '\0';
06203 p->cid_name[0] = '\0';
06204 p->cid_subaddr[0] = '\0';
06205 }
06206
06207 #if defined(HAVE_PRI)
06208 if (dahdi_sig_pri_lib_handles(p->sig)) {
06209 x = 1;
06210 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06211
06212 dahdi_confmute(p, 0);
06213 p->muting = 0;
06214 restore_gains(p);
06215 if (p->dsp) {
06216 ast_dsp_free(p->dsp);
06217 p->dsp = NULL;
06218 }
06219 p->ignoredtmf = 0;
06220
06221
06222 p->subs[SUB_REAL].owner = NULL;
06223 p->subs[SUB_REAL].needbusy = 0;
06224 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06225
06226 p->owner = NULL;
06227 p->cid_tag[0] = '\0';
06228 p->ringt = 0;
06229 p->distinctivering = 0;
06230 p->confirmanswer = 0;
06231 p->outgoing = 0;
06232 p->digital = 0;
06233 p->faxhandled = 0;
06234 p->pulsedial = 0;
06235
06236 revert_fax_buffers(p, ast);
06237
06238 p->law = p->law_default;
06239 law = p->law_default;
06240 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06241 if (res < 0) {
06242 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06243 p->channel, strerror(errno));
06244 }
06245
06246 sig_pri_hangup(p->sig_pvt, ast);
06247
06248 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06249 dahdi_disable_ec(p);
06250
06251 x = 0;
06252 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06253 p->didtdd = 0;
06254
06255 p->rdnis[0] = '\0';
06256 update_conf(p);
06257 reset_conf(p);
06258
06259
06260 x = 0;
06261 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06262
06263 if (num_restart_pending == 0) {
06264 restart_monitor();
06265 }
06266 goto hangup_out;
06267 }
06268 #endif
06269
06270 #if defined(HAVE_SS7)
06271 if (p->sig == SIG_SS7) {
06272 x = 1;
06273 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06274
06275 dahdi_confmute(p, 0);
06276 p->muting = 0;
06277 restore_gains(p);
06278 if (p->dsp) {
06279 ast_dsp_free(p->dsp);
06280 p->dsp = NULL;
06281 }
06282 p->ignoredtmf = 0;
06283
06284
06285 p->subs[SUB_REAL].owner = NULL;
06286 p->subs[SUB_REAL].needbusy = 0;
06287 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06288
06289 p->owner = NULL;
06290 p->ringt = 0;
06291 p->distinctivering = 0;
06292 p->confirmanswer = 0;
06293 p->outgoing = 0;
06294 p->digital = 0;
06295 p->faxhandled = 0;
06296 p->pulsedial = 0;
06297
06298 revert_fax_buffers(p, ast);
06299
06300 p->law = p->law_default;
06301 law = p->law_default;
06302 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06303 if (res < 0) {
06304 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06305 p->channel, strerror(errno));
06306 }
06307
06308 sig_ss7_hangup(p->sig_pvt, ast);
06309
06310 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06311 dahdi_disable_ec(p);
06312
06313 x = 0;
06314 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06315 p->didtdd = 0;
06316
06317 update_conf(p);
06318 reset_conf(p);
06319
06320
06321 x = 0;
06322 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06323
06324 if (num_restart_pending == 0) {
06325 restart_monitor();
06326 }
06327 goto hangup_out;
06328 }
06329 #endif
06330
06331 idx = dahdi_get_index(ast, p, 1);
06332
06333 dahdi_confmute(p, 0);
06334 p->muting = 0;
06335 restore_gains(p);
06336 if (p->origcid_num) {
06337 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06338 ast_free(p->origcid_num);
06339 p->origcid_num = NULL;
06340 }
06341 if (p->origcid_name) {
06342 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06343 ast_free(p->origcid_name);
06344 p->origcid_name = NULL;
06345 }
06346 if (p->dsp)
06347 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06348
06349 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06350 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06351 p->ignoredtmf = 0;
06352
06353 if (idx > -1) {
06354
06355 p->subs[idx].owner = NULL;
06356 p->subs[idx].needanswer = 0;
06357 p->subs[idx].needflash = 0;
06358 p->subs[idx].needringing = 0;
06359 p->subs[idx].needbusy = 0;
06360 p->subs[idx].needcongestion = 0;
06361 p->subs[idx].linear = 0;
06362 p->polarity = POLARITY_IDLE;
06363 dahdi_setlinear(p->subs[idx].dfd, 0);
06364 if (idx == SUB_REAL) {
06365 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06366 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06367 if (p->subs[SUB_CALLWAIT].inthreeway) {
06368
06369 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06370
06371 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06372 unalloc_sub(p, SUB_CALLWAIT);
06373 p->owner = NULL;
06374 } else {
06375
06376 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06377 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06378 unalloc_sub(p, SUB_THREEWAY);
06379 if (p->subs[SUB_REAL].inthreeway) {
06380
06381
06382 ast_debug(1, "Call was complete, setting owner to former third call\n");
06383 p->owner = p->subs[SUB_REAL].owner;
06384 } else {
06385
06386 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06387 p->owner = NULL;
06388 }
06389 p->subs[SUB_REAL].inthreeway = 0;
06390 }
06391 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06392
06393 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06394 unalloc_sub(p, SUB_CALLWAIT);
06395 p->owner = p->subs[SUB_REAL].owner;
06396 if (p->owner->_state != AST_STATE_UP)
06397 p->subs[SUB_REAL].needanswer = 1;
06398 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06399 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06400 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06401 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06402 unalloc_sub(p, SUB_THREEWAY);
06403 if (p->subs[SUB_REAL].inthreeway) {
06404
06405
06406 ast_debug(1, "Call was complete, setting owner to former third call\n");
06407 p->owner = p->subs[SUB_REAL].owner;
06408 } else {
06409
06410 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06411 p->owner = NULL;
06412 }
06413 p->subs[SUB_REAL].inthreeway = 0;
06414 }
06415 } else if (idx == SUB_CALLWAIT) {
06416
06417 if (p->subs[SUB_CALLWAIT].inthreeway) {
06418
06419
06420 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06421 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06422 S_OR(p->mohsuggest, NULL),
06423 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06424 }
06425 p->subs[SUB_THREEWAY].inthreeway = 0;
06426
06427 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06428 unalloc_sub(p, SUB_THREEWAY);
06429 } else
06430 unalloc_sub(p, SUB_CALLWAIT);
06431 } else if (idx == SUB_THREEWAY) {
06432 if (p->subs[SUB_CALLWAIT].inthreeway) {
06433
06434
06435 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06436 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06437 S_OR(p->mohsuggest, NULL),
06438 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06439 }
06440 p->subs[SUB_CALLWAIT].inthreeway = 0;
06441 }
06442 p->subs[SUB_REAL].inthreeway = 0;
06443
06444
06445 unalloc_sub(p, SUB_THREEWAY);
06446 } else {
06447
06448 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06449 }
06450 }
06451
06452 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06453 p->owner = NULL;
06454 p->ringt = 0;
06455 p->distinctivering = 0;
06456 p->confirmanswer = 0;
06457 p->outgoing = 0;
06458 p->digital = 0;
06459 p->faxhandled = 0;
06460 p->pulsedial = 0;
06461 if (p->dsp) {
06462 ast_dsp_free(p->dsp);
06463 p->dsp = NULL;
06464 }
06465
06466 revert_fax_buffers(p, ast);
06467
06468 p->law = p->law_default;
06469 law = p->law_default;
06470 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06471 if (res < 0)
06472 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06473
06474 #ifdef HAVE_OPENR2
06475 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06476 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06477
06478 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06479 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06480 } else {
06481 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06482 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06483 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06484 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06485 dahdi_r2_disconnect_call(p, r2cause);
06486 }
06487 } else if (p->mfcr2call) {
06488 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06489
06490
06491
06492
06493 p->mfcr2call = 0;
06494 }
06495 #endif
06496 switch (p->sig) {
06497 case SIG_SS7:
06498 case SIG_MFCR2:
06499 case SIG_PRI_LIB_HANDLE_CASES:
06500 case 0:
06501 break;
06502 default:
06503 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06504 break;
06505 }
06506 if (res < 0) {
06507 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06508 }
06509 switch (p->sig) {
06510 case SIG_FXOGS:
06511 case SIG_FXOLS:
06512 case SIG_FXOKS:
06513 memset(&par, 0, sizeof(par));
06514 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06515 if (!res) {
06516 struct analog_pvt *analog_p = p->sig_pvt;
06517 #if 0
06518 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06519 #endif
06520
06521 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06522 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06523 else
06524 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06525 analog_p->fxsoffhookstate = par.rxisoffhook;
06526 }
06527 break;
06528 case SIG_FXSGS:
06529 case SIG_FXSLS:
06530 case SIG_FXSKS:
06531
06532
06533 if (ast->_state != AST_STATE_RESERVED) {
06534 time(&p->guardtime);
06535 p->guardtime += 2;
06536 }
06537 break;
06538 default:
06539 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06540 break;
06541 }
06542 if (p->sig)
06543 dahdi_disable_ec(p);
06544 x = 0;
06545 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06546 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06547 p->didtdd = 0;
06548 p->callwaitcas = 0;
06549 p->callwaiting = p->permcallwaiting;
06550 p->hidecallerid = p->permhidecallerid;
06551 p->waitingfordt.tv_sec = 0;
06552 p->dialing = 0;
06553 p->rdnis[0] = '\0';
06554 update_conf(p);
06555 reset_conf(p);
06556
06557 switch (p->sig) {
06558 case SIG_PRI_LIB_HANDLE_CASES:
06559 case SIG_SS7:
06560 x = 0;
06561 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06562 break;
06563 default:
06564 break;
06565 }
06566 if (num_restart_pending == 0)
06567 restart_monitor();
06568 }
06569
06570 p->callwaitingrepeat = 0;
06571 p->cidcwexpire = 0;
06572 p->cid_suppress_expire = 0;
06573 p->oprmode = 0;
06574 hangup_out:
06575 ast->tech_pvt = NULL;
06576 ast_free(p->cidspill);
06577 p->cidspill = NULL;
06578
06579 ast_mutex_unlock(&p->lock);
06580 ast_verb(3, "Hungup '%s'\n", ast->name);
06581
06582 ast_mutex_lock(&iflock);
06583 if (p->restartpending) {
06584 num_restart_pending--;
06585 }
06586
06587 if (p->destroy) {
06588 destroy_channel(p, 0);
06589 }
06590 ast_mutex_unlock(&iflock);
06591
06592 ast_module_unref(ast_module_info->self);
06593 return 0;
06594 }
06595
06596 static int dahdi_answer(struct ast_channel *ast)
06597 {
06598 struct dahdi_pvt *p = ast->tech_pvt;
06599 int res = 0;
06600 int idx;
06601 ast_setstate(ast, AST_STATE_UP);
06602 ast_mutex_lock(&p->lock);
06603 idx = dahdi_get_index(ast, p, 0);
06604 if (idx < 0)
06605 idx = SUB_REAL;
06606
06607 if ((p->radio || (p->oprmode < 0))) {
06608 ast_mutex_unlock(&p->lock);
06609 return 0;
06610 }
06611
06612 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06613 res = analog_answer(p->sig_pvt, ast);
06614 ast_mutex_unlock(&p->lock);
06615 return res;
06616 }
06617
06618 switch (p->sig) {
06619 #if defined(HAVE_PRI)
06620 case SIG_PRI_LIB_HANDLE_CASES:
06621 res = sig_pri_answer(p->sig_pvt, ast);
06622 break;
06623 #endif
06624 #if defined(HAVE_SS7)
06625 case SIG_SS7:
06626 res = sig_ss7_answer(p->sig_pvt, ast);
06627 break;
06628 #endif
06629 #ifdef HAVE_OPENR2
06630 case SIG_MFCR2:
06631 if (!p->mfcr2_call_accepted) {
06632
06633
06634 p->mfcr2_answer_pending = 1;
06635 if (p->mfcr2_charge_calls) {
06636 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06637 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06638 } else {
06639 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06640 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06641 }
06642 } else {
06643 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06644 dahdi_r2_answer(p);
06645 }
06646 break;
06647 #endif
06648 case 0:
06649 ast_mutex_unlock(&p->lock);
06650 return 0;
06651 default:
06652 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06653 res = -1;
06654 break;
06655 }
06656 ast_mutex_unlock(&p->lock);
06657 return res;
06658 }
06659
06660 static void disable_dtmf_detect(struct dahdi_pvt *p)
06661 {
06662 int val = 0;
06663
06664 p->ignoredtmf = 1;
06665
06666 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06667
06668 if (!p->hardwaredtmf && p->dsp) {
06669 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06670 ast_dsp_set_features(p->dsp, p->dsp_features);
06671 }
06672 }
06673
06674 static void enable_dtmf_detect(struct dahdi_pvt *p)
06675 {
06676 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06677
06678 if (p->channel == CHAN_PSEUDO)
06679 return;
06680
06681 p->ignoredtmf = 0;
06682
06683 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06684
06685 if (!p->hardwaredtmf && p->dsp) {
06686 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06687 ast_dsp_set_features(p->dsp, p->dsp_features);
06688 }
06689 }
06690
06691 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06692 {
06693 char *cp;
06694 struct dahdi_pvt *p = chan->tech_pvt;
06695
06696
06697 if (!p || !data || (*datalen < 1)) {
06698 errno = EINVAL;
06699 return -1;
06700 }
06701
06702 switch (option) {
06703 case AST_OPTION_DIGIT_DETECT:
06704 cp = (char *) data;
06705 *cp = p->ignoredtmf ? 0 : 1;
06706 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06707 break;
06708 case AST_OPTION_FAX_DETECT:
06709 cp = (char *) data;
06710 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06711 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06712 break;
06713 case AST_OPTION_CC_AGENT_TYPE:
06714 #if defined(HAVE_PRI)
06715 #if defined(HAVE_PRI_CCSS)
06716 if (dahdi_sig_pri_lib_handles(p->sig)) {
06717 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06718 break;
06719 }
06720 #endif
06721 #endif
06722 return -1;
06723 default:
06724 return -1;
06725 }
06726
06727 errno = 0;
06728
06729 return 0;
06730 }
06731
06732 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06733 {
06734 char *cp;
06735 signed char *scp;
06736 int x;
06737 int idx;
06738 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06739 struct oprmode *oprmode;
06740
06741
06742
06743 if (!p || !data || (datalen < 1)) {
06744 errno = EINVAL;
06745 return -1;
06746 }
06747
06748 switch (option) {
06749 case AST_OPTION_TXGAIN:
06750 scp = (signed char *) data;
06751 idx = dahdi_get_index(chan, p, 0);
06752 if (idx < 0) {
06753 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06754 return -1;
06755 }
06756 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06757 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06758 case AST_OPTION_RXGAIN:
06759 scp = (signed char *) data;
06760 idx = dahdi_get_index(chan, p, 0);
06761 if (idx < 0) {
06762 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06763 return -1;
06764 }
06765 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06766 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06767 case AST_OPTION_TONE_VERIFY:
06768 if (!p->dsp)
06769 break;
06770 cp = (char *) data;
06771 switch (*cp) {
06772 case 1:
06773 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06774 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06775 break;
06776 case 2:
06777 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06778 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06779 break;
06780 default:
06781 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06782 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06783 break;
06784 }
06785 break;
06786 case AST_OPTION_TDD:
06787
06788 cp = (char *) data;
06789 p->mate = 0;
06790 if (!*cp) {
06791 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06792 if (p->tdd)
06793 tdd_free(p->tdd);
06794 p->tdd = 0;
06795 break;
06796 }
06797 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06798 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06799 dahdi_disable_ec(p);
06800
06801 if (!p->didtdd) {
06802 unsigned char mybuf[41000];
06803 unsigned char *buf;
06804 int size, res, fd, len;
06805 struct pollfd fds[1];
06806
06807 buf = mybuf;
06808 memset(buf, 0x7f, sizeof(mybuf));
06809 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06810 len = 40000;
06811 idx = dahdi_get_index(chan, p, 0);
06812 if (idx < 0) {
06813 ast_log(LOG_WARNING, "No index in TDD?\n");
06814 return -1;
06815 }
06816 fd = p->subs[idx].dfd;
06817 while (len) {
06818 if (ast_check_hangup(chan))
06819 return -1;
06820 size = len;
06821 if (size > READ_SIZE)
06822 size = READ_SIZE;
06823 fds[0].fd = fd;
06824 fds[0].events = POLLPRI | POLLOUT;
06825 fds[0].revents = 0;
06826 res = poll(fds, 1, -1);
06827 if (!res) {
06828 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06829 continue;
06830 }
06831
06832 if (fds[0].revents & POLLPRI)
06833 return -1;
06834 if (!(fds[0].revents & POLLOUT)) {
06835 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06836 continue;
06837 }
06838 res = write(fd, buf, size);
06839 if (res != size) {
06840 if (res == -1) return -1;
06841 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06842 break;
06843 }
06844 len -= size;
06845 buf += size;
06846 }
06847 p->didtdd = 1;
06848 }
06849 if (*cp == 2) {
06850 if (p->tdd)
06851 tdd_free(p->tdd);
06852 p->tdd = 0;
06853 p->mate = 1;
06854 break;
06855 }
06856 if (!p->tdd) {
06857 p->tdd = tdd_new();
06858 }
06859 break;
06860 case AST_OPTION_RELAXDTMF:
06861 if (!p->dsp)
06862 break;
06863 cp = (char *) data;
06864 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06865 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06866 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06867 break;
06868 case AST_OPTION_AUDIO_MODE:
06869 #if defined(HAVE_PRI)
06870 if (dahdi_sig_pri_lib_handles(p->sig)
06871 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06872
06873 break;
06874 }
06875 #endif
06876
06877 cp = (char *) data;
06878 if (!*cp) {
06879 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06880 x = 0;
06881 dahdi_disable_ec(p);
06882 } else {
06883 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06884 x = 1;
06885 }
06886 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06887 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06888 break;
06889 case AST_OPTION_OPRMODE:
06890 oprmode = (struct oprmode *) data;
06891
06892 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06893 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06894 chan->tech->type, oprmode->peer->tech->type);
06895 errno = EINVAL;
06896 return -1;
06897 }
06898 pp = oprmode->peer->tech_pvt;
06899 p->oprmode = pp->oprmode = 0;
06900
06901 p->oprpeer = pp;
06902 pp->oprpeer = p;
06903
06904 if (oprmode->mode)
06905 {
06906 pp->oprmode = oprmode->mode;
06907 p->oprmode = -oprmode->mode;
06908 }
06909 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06910 oprmode->mode, chan->name,oprmode->peer->name);
06911 break;
06912 case AST_OPTION_ECHOCAN:
06913 cp = (char *) data;
06914 if (*cp) {
06915 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06916 dahdi_enable_ec(p);
06917 } else {
06918 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06919 dahdi_disable_ec(p);
06920 }
06921 break;
06922 case AST_OPTION_DIGIT_DETECT:
06923 cp = (char *) data;
06924 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06925 if (*cp) {
06926 enable_dtmf_detect(p);
06927 } else {
06928 disable_dtmf_detect(p);
06929 }
06930 break;
06931 case AST_OPTION_FAX_DETECT:
06932 cp = (char *) data;
06933 if (p->dsp) {
06934 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06935 if (*cp) {
06936 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06937 } else {
06938 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06939 }
06940 ast_dsp_set_features(p->dsp, p->dsp_features);
06941 }
06942 break;
06943 default:
06944 return -1;
06945 }
06946 errno = 0;
06947
06948 return 0;
06949 }
06950
06951 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06952 {
06953 struct dahdi_pvt *p = chan->tech_pvt;
06954 int res = 0;
06955
06956 if (!p) {
06957
06958 *buf = '\0';
06959 return -1;
06960 }
06961
06962 if (!strcasecmp(data, "rxgain")) {
06963 ast_mutex_lock(&p->lock);
06964 snprintf(buf, len, "%f", p->rxgain);
06965 ast_mutex_unlock(&p->lock);
06966 } else if (!strcasecmp(data, "txgain")) {
06967 ast_mutex_lock(&p->lock);
06968 snprintf(buf, len, "%f", p->txgain);
06969 ast_mutex_unlock(&p->lock);
06970 } else if (!strcasecmp(data, "dahdi_channel")) {
06971 ast_mutex_lock(&p->lock);
06972 snprintf(buf, len, "%d", p->channel);
06973 ast_mutex_unlock(&p->lock);
06974 } else if (!strcasecmp(data, "dahdi_span")) {
06975 ast_mutex_lock(&p->lock);
06976 snprintf(buf, len, "%d", p->span);
06977 ast_mutex_unlock(&p->lock);
06978 } else if (!strcasecmp(data, "dahdi_type")) {
06979 ast_mutex_lock(&p->lock);
06980 switch (p->sig) {
06981 #if defined(HAVE_OPENR2)
06982 case SIG_MFCR2:
06983 ast_copy_string(buf, "mfc/r2", len);
06984 break;
06985 #endif
06986 #if defined(HAVE_PRI)
06987 case SIG_PRI_LIB_HANDLE_CASES:
06988 ast_copy_string(buf, "pri", len);
06989 break;
06990 #endif
06991 case 0:
06992 ast_copy_string(buf, "pseudo", len);
06993 break;
06994 #if defined(HAVE_SS7)
06995 case SIG_SS7:
06996 ast_copy_string(buf, "ss7", len);
06997 break;
06998 #endif
06999 default:
07000
07001 ast_copy_string(buf, "analog", len);
07002 break;
07003 }
07004 ast_mutex_unlock(&p->lock);
07005 #if defined(HAVE_PRI)
07006 #if defined(HAVE_PRI_REVERSE_CHARGE)
07007 } else if (!strcasecmp(data, "reversecharge")) {
07008 ast_mutex_lock(&p->lock);
07009 switch (p->sig) {
07010 case SIG_PRI_LIB_HANDLE_CASES:
07011 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
07012 break;
07013 default:
07014 *buf = '\0';
07015 res = -1;
07016 break;
07017 }
07018 ast_mutex_unlock(&p->lock);
07019 #endif
07020 #if defined(HAVE_PRI_SETUP_KEYPAD)
07021 } else if (!strcasecmp(data, "keypad_digits")) {
07022 ast_mutex_lock(&p->lock);
07023 switch (p->sig) {
07024 case SIG_PRI_LIB_HANDLE_CASES:
07025 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07026 len);
07027 break;
07028 default:
07029 *buf = '\0';
07030 res = -1;
07031 break;
07032 }
07033 ast_mutex_unlock(&p->lock);
07034 #endif
07035 } else if (!strcasecmp(data, "no_media_path")) {
07036 ast_mutex_lock(&p->lock);
07037 switch (p->sig) {
07038 case SIG_PRI_LIB_HANDLE_CASES:
07039
07040
07041
07042
07043 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07044 break;
07045 default:
07046 *buf = '\0';
07047 res = -1;
07048 break;
07049 }
07050 ast_mutex_unlock(&p->lock);
07051 #endif
07052 } else {
07053 *buf = '\0';
07054 res = -1;
07055 }
07056
07057 return res;
07058 }
07059
07060
07061 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07062 {
07063 int res;
07064 char policy_str[21] = "";
07065
07066 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07067 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07068 return 1;
07069 }
07070 if (*num_buffers < 0) {
07071 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07072 return -1;
07073 }
07074 if (!strcasecmp(policy_str, "full")) {
07075 *policy = DAHDI_POLICY_WHEN_FULL;
07076 } else if (!strcasecmp(policy_str, "immediate")) {
07077 *policy = DAHDI_POLICY_IMMEDIATE;
07078 #if defined(HAVE_DAHDI_HALF_FULL)
07079 } else if (!strcasecmp(policy_str, "half")) {
07080 *policy = DAHDI_POLICY_HALF_FULL;
07081 #endif
07082 } else {
07083 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07084 return -1;
07085 }
07086
07087 return 0;
07088 }
07089
07090 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07091 {
07092 struct dahdi_pvt *p = chan->tech_pvt;
07093 int res = 0;
07094
07095 if (!p) {
07096
07097 return -1;
07098 }
07099
07100 if (!strcasecmp(data, "buffers")) {
07101 int num_bufs, policy;
07102
07103 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07104 struct dahdi_bufferinfo bi = {
07105 .txbufpolicy = policy,
07106 .rxbufpolicy = policy,
07107 .bufsize = p->bufsize,
07108 .numbufs = num_bufs,
07109 };
07110 int bpres;
07111
07112 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07113 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07114 } else {
07115 p->bufferoverrideinuse = 1;
07116 }
07117 } else {
07118 res = -1;
07119 }
07120 } else if (!strcasecmp(data, "echocan_mode")) {
07121 if (!strcasecmp(value, "on")) {
07122 ast_mutex_lock(&p->lock);
07123 dahdi_enable_ec(p);
07124 ast_mutex_unlock(&p->lock);
07125 } else if (!strcasecmp(value, "off")) {
07126 ast_mutex_lock(&p->lock);
07127 dahdi_disable_ec(p);
07128 ast_mutex_unlock(&p->lock);
07129 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07130 } else if (!strcasecmp(value, "fax")) {
07131 int blah = 1;
07132
07133 ast_mutex_lock(&p->lock);
07134 if (!p->echocanon) {
07135 dahdi_enable_ec(p);
07136 }
07137 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07138 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07139 }
07140 ast_mutex_unlock(&p->lock);
07141 } else if (!strcasecmp(value, "voice")) {
07142 int blah = 0;
07143
07144 ast_mutex_lock(&p->lock);
07145 if (!p->echocanon) {
07146 dahdi_enable_ec(p);
07147 }
07148 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07149 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07150 }
07151 ast_mutex_unlock(&p->lock);
07152 #endif
07153 } else {
07154 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07155 res = -1;
07156 }
07157 } else {
07158 res = -1;
07159 }
07160
07161 return res;
07162 }
07163
07164 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07165 {
07166
07167 int x;
07168 int hasslaves;
07169 if (!master)
07170 return;
07171 if (needlock) {
07172 ast_mutex_lock(&master->lock);
07173 if (slave) {
07174 while (ast_mutex_trylock(&slave->lock)) {
07175 DEADLOCK_AVOIDANCE(&master->lock);
07176 }
07177 }
07178 }
07179 hasslaves = 0;
07180 for (x = 0; x < MAX_SLAVES; x++) {
07181 if (master->slaves[x]) {
07182 if (!slave || (master->slaves[x] == slave)) {
07183
07184 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07185 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07186 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07187 master->slaves[x]->master = NULL;
07188 master->slaves[x] = NULL;
07189 } else
07190 hasslaves = 1;
07191 }
07192 if (!hasslaves)
07193 master->inconference = 0;
07194 }
07195 if (!slave) {
07196 if (master->master) {
07197
07198 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07199 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07200 hasslaves = 0;
07201 for (x = 0; x < MAX_SLAVES; x++) {
07202 if (master->master->slaves[x] == master)
07203 master->master->slaves[x] = NULL;
07204 else if (master->master->slaves[x])
07205 hasslaves = 1;
07206 }
07207 if (!hasslaves)
07208 master->master->inconference = 0;
07209 }
07210 master->master = NULL;
07211 }
07212 update_conf(master);
07213 if (needlock) {
07214 if (slave)
07215 ast_mutex_unlock(&slave->lock);
07216 ast_mutex_unlock(&master->lock);
07217 }
07218 }
07219
07220 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07221 int x;
07222 if (!slave || !master) {
07223 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07224 return;
07225 }
07226 for (x = 0; x < MAX_SLAVES; x++) {
07227 if (!master->slaves[x]) {
07228 master->slaves[x] = slave;
07229 break;
07230 }
07231 }
07232 if (x >= MAX_SLAVES) {
07233 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07234 master->slaves[MAX_SLAVES - 1] = slave;
07235 }
07236 if (slave->master)
07237 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07238 slave->master = master;
07239
07240 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07241 }
07242
07243 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)
07244 {
07245 struct ast_channel *who;
07246 struct dahdi_pvt *p0, *p1, *op0, *op1;
07247 struct dahdi_pvt *master = NULL, *slave = NULL;
07248 struct ast_frame *f;
07249 int inconf = 0;
07250 int nothingok = 1;
07251 int ofd0, ofd1;
07252 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07253 int os0 = -1, os1 = -1;
07254 int priority = 0;
07255 struct ast_channel *oc0, *oc1;
07256 enum ast_bridge_result res;
07257 struct timeval start = ast_tvnow();
07258 #ifdef PRI_2BCT
07259 int triedtopribridge = 0;
07260 q931_call *q931c0;
07261 q931_call *q931c1;
07262 #endif
07263
07264
07265
07266
07267
07268
07269 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07270 return AST_BRIDGE_FAILED_NOWARN;
07271
07272 ast_channel_lock(c0);
07273 while (ast_channel_trylock(c1)) {
07274 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07275 }
07276
07277 p0 = c0->tech_pvt;
07278 p1 = c1->tech_pvt;
07279
07280 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07281 ast_channel_unlock(c0);
07282 ast_channel_unlock(c1);
07283 return AST_BRIDGE_FAILED_NOWARN;
07284 }
07285
07286 oi0 = dahdi_get_index(c0, p0, 0);
07287 oi1 = dahdi_get_index(c1, p1, 0);
07288 if ((oi0 < 0) || (oi1 < 0)) {
07289 ast_channel_unlock(c0);
07290 ast_channel_unlock(c1);
07291 return AST_BRIDGE_FAILED;
07292 }
07293
07294 op0 = p0 = c0->tech_pvt;
07295 op1 = p1 = c1->tech_pvt;
07296 ofd0 = c0->fds[0];
07297 ofd1 = c1->fds[0];
07298 oc0 = p0->owner;
07299 oc1 = p1->owner;
07300
07301 if (ast_mutex_trylock(&p0->lock)) {
07302
07303 ast_channel_unlock(c0);
07304 ast_channel_unlock(c1);
07305 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07306 return AST_BRIDGE_RETRY;
07307 }
07308 if (ast_mutex_trylock(&p1->lock)) {
07309
07310 ast_mutex_unlock(&p0->lock);
07311 ast_channel_unlock(c0);
07312 ast_channel_unlock(c1);
07313 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07314 return AST_BRIDGE_RETRY;
07315 }
07316
07317 if ((p0->callwaiting && p0->callwaitingcallerid)
07318 || (p1->callwaiting && p1->callwaitingcallerid)) {
07319
07320
07321
07322
07323
07324
07325
07326
07327
07328 ast_mutex_unlock(&p0->lock);
07329 ast_mutex_unlock(&p1->lock);
07330 ast_channel_unlock(c0);
07331 ast_channel_unlock(c1);
07332 return AST_BRIDGE_FAILED_NOWARN;
07333 }
07334
07335 #if defined(HAVE_PRI)
07336 if ((dahdi_sig_pri_lib_handles(p0->sig)
07337 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07338 || (dahdi_sig_pri_lib_handles(p1->sig)
07339 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07340
07341
07342
07343
07344 ast_mutex_unlock(&p0->lock);
07345 ast_mutex_unlock(&p1->lock);
07346 ast_channel_unlock(c0);
07347 ast_channel_unlock(c1);
07348 return AST_BRIDGE_FAILED_NOWARN;
07349 }
07350 #endif
07351
07352 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07353 if (p0->owner && p1->owner) {
07354
07355 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07356 master = p0;
07357 slave = p1;
07358 inconf = 1;
07359 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07360 master = p1;
07361 slave = p0;
07362 inconf = 1;
07363 } else {
07364 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07365 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07366 p0->channel,
07367 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07368 p0->subs[SUB_REAL].inthreeway, p0->channel,
07369 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07370 p1->subs[SUB_REAL].inthreeway);
07371 }
07372 nothingok = 0;
07373 }
07374 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07375 if (p1->subs[SUB_THREEWAY].inthreeway) {
07376 master = p1;
07377 slave = p0;
07378 nothingok = 0;
07379 }
07380 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07381 if (p0->subs[SUB_THREEWAY].inthreeway) {
07382 master = p0;
07383 slave = p1;
07384 nothingok = 0;
07385 }
07386 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07387
07388
07389 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07390 master = p1;
07391 slave = p0;
07392 nothingok = 0;
07393 }
07394 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07395
07396 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07397 master = p0;
07398 slave = p1;
07399 nothingok = 0;
07400 }
07401 }
07402 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07403 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07404 if (master && slave) {
07405
07406
07407
07408 if ((oi1 == SUB_THREEWAY) &&
07409 p1->subs[SUB_THREEWAY].inthreeway &&
07410 p1->subs[SUB_REAL].owner &&
07411 p1->subs[SUB_REAL].inthreeway &&
07412 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07413 ast_debug(1,
07414 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07415 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07416 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07417 os1 = p1->subs[SUB_REAL].owner->_state;
07418 } else {
07419 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07420 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07421 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07422 }
07423 if ((oi0 == SUB_THREEWAY) &&
07424 p0->subs[SUB_THREEWAY].inthreeway &&
07425 p0->subs[SUB_REAL].owner &&
07426 p0->subs[SUB_REAL].inthreeway &&
07427 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07428 ast_debug(1,
07429 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07430 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07431 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07432 os0 = p0->subs[SUB_REAL].owner->_state;
07433 } else {
07434 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07435 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07436 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07437 }
07438 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07439 if (!p0->echocanbridged || !p1->echocanbridged) {
07440
07441 dahdi_disable_ec(p0);
07442 dahdi_disable_ec(p1);
07443 }
07444 }
07445 dahdi_link(slave, master);
07446 master->inconference = inconf;
07447 } else if (!nothingok)
07448 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07449
07450 update_conf(p0);
07451 update_conf(p1);
07452 t0 = p0->subs[SUB_REAL].inthreeway;
07453 t1 = p1->subs[SUB_REAL].inthreeway;
07454
07455 ast_mutex_unlock(&p0->lock);
07456 ast_mutex_unlock(&p1->lock);
07457
07458 ast_channel_unlock(c0);
07459 ast_channel_unlock(c1);
07460
07461
07462 if ((!master || !slave) && !nothingok) {
07463 dahdi_enable_ec(p0);
07464 dahdi_enable_ec(p1);
07465 return AST_BRIDGE_FAILED;
07466 }
07467
07468 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07469
07470 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07471 disable_dtmf_detect(op0);
07472
07473 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07474 disable_dtmf_detect(op1);
07475
07476 for (;;) {
07477 struct ast_channel *c0_priority[2] = {c0, c1};
07478 struct ast_channel *c1_priority[2] = {c1, c0};
07479 int ms;
07480
07481
07482
07483
07484 ast_channel_lock(c0);
07485 while (ast_channel_trylock(c1)) {
07486 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07487 }
07488
07489 p0 = c0->tech_pvt;
07490 p1 = c1->tech_pvt;
07491
07492 if (op0 == p0)
07493 i0 = dahdi_get_index(c0, p0, 1);
07494 if (op1 == p1)
07495 i1 = dahdi_get_index(c1, p1, 1);
07496
07497 ast_channel_unlock(c0);
07498 ast_channel_unlock(c1);
07499 ms = ast_remaining_ms(start, timeoutms);
07500 if (!ms ||
07501 (op0 != p0) ||
07502 (op1 != p1) ||
07503 (ofd0 != c0->fds[0]) ||
07504 (ofd1 != c1->fds[0]) ||
07505 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07506 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07507 (oc0 != p0->owner) ||
07508 (oc1 != p1->owner) ||
07509 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07510 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07511 (oi0 != i0) ||
07512 (oi1 != i1)) {
07513 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07514 op0->channel, oi0, op1->channel, oi1);
07515 res = AST_BRIDGE_RETRY;
07516 goto return_from_bridge;
07517 }
07518
07519 #ifdef PRI_2BCT
07520 if (!triedtopribridge) {
07521 triedtopribridge = 1;
07522 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07523 ast_mutex_lock(&p0->pri->lock);
07524 switch (p0->sig) {
07525 case SIG_PRI_LIB_HANDLE_CASES:
07526 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07527 break;
07528 default:
07529 q931c0 = NULL;
07530 break;
07531 }
07532 switch (p1->sig) {
07533 case SIG_PRI_LIB_HANDLE_CASES:
07534 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07535 break;
07536 default:
07537 q931c1 = NULL;
07538 break;
07539 }
07540 if (q931c0 && q931c1) {
07541 pri_channel_bridge(q931c0, q931c1);
07542 }
07543 ast_mutex_unlock(&p0->pri->lock);
07544 }
07545 }
07546 #endif
07547
07548 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &ms);
07549 if (!who) {
07550 ast_debug(1, "Ooh, empty read...\n");
07551 continue;
07552 }
07553 f = ast_read(who);
07554 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07555 *fo = f;
07556 *rc = who;
07557 res = AST_BRIDGE_COMPLETE;
07558 goto return_from_bridge;
07559 }
07560 if (f->frametype == AST_FRAME_DTMF) {
07561 if ((who == c0) && p0->pulsedial) {
07562 ast_write(c1, f);
07563 } else if ((who == c1) && p1->pulsedial) {
07564 ast_write(c0, f);
07565 } else {
07566 *fo = f;
07567 *rc = who;
07568 res = AST_BRIDGE_COMPLETE;
07569 goto return_from_bridge;
07570 }
07571 }
07572 ast_frfree(f);
07573
07574
07575 priority = !priority;
07576 }
07577
07578 return_from_bridge:
07579 if (op0 == p0)
07580 dahdi_enable_ec(p0);
07581
07582 if (op1 == p1)
07583 dahdi_enable_ec(p1);
07584
07585 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07586 enable_dtmf_detect(op0);
07587
07588 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07589 enable_dtmf_detect(op1);
07590
07591 dahdi_unlink(slave, master, 1);
07592
07593 return res;
07594 }
07595
07596 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07597 {
07598 struct dahdi_pvt *p = newchan->tech_pvt;
07599 int x;
07600
07601 ast_mutex_lock(&p->lock);
07602
07603 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07604 if (p->owner == oldchan) {
07605 p->owner = newchan;
07606 }
07607 for (x = 0; x < 3; x++) {
07608 if (p->subs[x].owner == oldchan) {
07609 if (!x) {
07610 dahdi_unlink(NULL, p, 0);
07611 }
07612 p->subs[x].owner = newchan;
07613 }
07614 }
07615 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07616 analog_fixup(oldchan, newchan, p->sig_pvt);
07617 #if defined(HAVE_PRI)
07618 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07619 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07620 #endif
07621 #if defined(HAVE_SS7)
07622 } else if (p->sig == SIG_SS7) {
07623 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07624 #endif
07625 }
07626 update_conf(p);
07627
07628 ast_mutex_unlock(&p->lock);
07629
07630 if (newchan->_state == AST_STATE_RINGING) {
07631 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07632 }
07633 return 0;
07634 }
07635
07636 static int dahdi_ring_phone(struct dahdi_pvt *p)
07637 {
07638 int x;
07639 int res;
07640
07641 x = 0;
07642 x = DAHDI_ONHOOK;
07643 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07644 do {
07645 x = DAHDI_RING;
07646 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07647 if (res) {
07648 switch (errno) {
07649 case EBUSY:
07650 case EINTR:
07651
07652 usleep(10000);
07653 continue;
07654 case EINPROGRESS:
07655 res = 0;
07656 break;
07657 default:
07658 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07659 res = 0;
07660 }
07661 }
07662 } while (res);
07663 return res;
07664 }
07665
07666 static void *analog_ss_thread(void *data);
07667
07668 static int attempt_transfer(struct dahdi_pvt *p)
07669 {
07670
07671
07672
07673 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07674
07675
07676 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07677 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07678 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07679 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07680 }
07681 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07682 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07683 }
07684 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07685 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07686 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07687 return -1;
07688 }
07689
07690 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07691 unalloc_sub(p, SUB_THREEWAY);
07692 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07693 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07694 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07695 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07696 }
07697 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07698 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07699 }
07700 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07701 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07702 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07703 return -1;
07704 }
07705
07706 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07707 ast_channel_unlock(p->subs[SUB_REAL].owner);
07708 unalloc_sub(p, SUB_THREEWAY);
07709
07710 return 1;
07711 } else {
07712 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07713 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07714 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07715 return -1;
07716 }
07717 return 0;
07718 }
07719
07720 static int check_for_conference(struct dahdi_pvt *p)
07721 {
07722 struct dahdi_confinfo ci;
07723
07724 if (p->master || (p->confno > -1))
07725 return 0;
07726 memset(&ci, 0, sizeof(ci));
07727 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07728 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07729 return 0;
07730 }
07731
07732
07733
07734 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07735 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07736 return 1;
07737 }
07738 return 0;
07739 }
07740
07741
07742
07743
07744
07745
07746 static int get_alarms(struct dahdi_pvt *p)
07747 {
07748 int res;
07749 struct dahdi_spaninfo zi;
07750 struct dahdi_params params;
07751
07752 memset(&zi, 0, sizeof(zi));
07753 zi.spanno = p->span;
07754
07755 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07756 if (zi.alarms != DAHDI_ALARM_NONE)
07757 return zi.alarms;
07758 } else {
07759 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07760 return 0;
07761 }
07762
07763
07764 memset(¶ms, 0, sizeof(params));
07765 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07766 return params.chan_alarms;
07767
07768 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07769
07770 return DAHDI_ALARM_NONE;
07771 }
07772
07773 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07774 {
07775 struct dahdi_pvt *p = ast->tech_pvt;
07776 struct ast_frame *f = *dest;
07777
07778 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07779 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07780 f->subclass.integer, f->subclass.integer, ast->name);
07781
07782 if (p->confirmanswer) {
07783 if (f->frametype == AST_FRAME_DTMF_END) {
07784 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07785
07786
07787 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07788 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07789
07790 p->confirmanswer = 0;
07791 } else {
07792 p->subs[idx].f.frametype = AST_FRAME_NULL;
07793 p->subs[idx].f.subclass.integer = 0;
07794 }
07795 *dest = &p->subs[idx].f;
07796 } else if (p->callwaitcas) {
07797 if (f->frametype == AST_FRAME_DTMF_END) {
07798 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07799 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07800 ast_free(p->cidspill);
07801 p->cidspill = NULL;
07802 send_cwcidspill(p);
07803 }
07804 p->callwaitcas = 0;
07805 }
07806 p->subs[idx].f.frametype = AST_FRAME_NULL;
07807 p->subs[idx].f.subclass.integer = 0;
07808 *dest = &p->subs[idx].f;
07809 } else if (f->subclass.integer == 'f') {
07810 if (f->frametype == AST_FRAME_DTMF_END) {
07811
07812 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07813
07814 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07815 struct dahdi_bufferinfo bi = {
07816 .txbufpolicy = p->faxbuf_policy,
07817 .bufsize = p->bufsize,
07818 .numbufs = p->faxbuf_no
07819 };
07820 int res;
07821
07822 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07823 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07824 } else {
07825 p->bufferoverrideinuse = 1;
07826 }
07827 }
07828 p->faxhandled = 1;
07829 if (p->dsp) {
07830 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07831 ast_dsp_set_features(p->dsp, p->dsp_features);
07832 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07833 }
07834 if (strcmp(ast->exten, "fax")) {
07835 const char *target_context = S_OR(ast->macrocontext, ast->context);
07836
07837
07838
07839
07840
07841 ast_mutex_unlock(&p->lock);
07842 ast_channel_unlock(ast);
07843 if (ast_exists_extension(ast, target_context, "fax", 1,
07844 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07845 ast_channel_lock(ast);
07846 ast_mutex_lock(&p->lock);
07847 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07848
07849 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07850 if (ast_async_goto(ast, target_context, "fax", 1))
07851 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07852 } else {
07853 ast_channel_lock(ast);
07854 ast_mutex_lock(&p->lock);
07855 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07856 }
07857 } else {
07858 ast_debug(1, "Already in a fax extension, not redirecting\n");
07859 }
07860 } else {
07861 ast_debug(1, "Fax already handled\n");
07862 }
07863 dahdi_confmute(p, 0);
07864 }
07865 p->subs[idx].f.frametype = AST_FRAME_NULL;
07866 p->subs[idx].f.subclass.integer = 0;
07867 *dest = &p->subs[idx].f;
07868 }
07869 }
07870
07871 static void handle_alarms(struct dahdi_pvt *p, int alms)
07872 {
07873 const char *alarm_str;
07874
07875 #if defined(HAVE_PRI)
07876 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07877 return;
07878 }
07879 #endif
07880
07881 alarm_str = alarm2str(alms);
07882 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07883 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07884 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07885 "Alarm: %s\r\n"
07886 "Channel: %d\r\n",
07887 alarm_str, p->channel);
07888 }
07889
07890 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07891 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07892 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07893 "Alarm: %s\r\n"
07894 "Span: %d\r\n",
07895 alarm_str, p->span);
07896 }
07897 }
07898
07899 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07900 {
07901 int res, x;
07902 int idx, mysig;
07903 char *c;
07904 struct dahdi_pvt *p = ast->tech_pvt;
07905 pthread_t threadid;
07906 struct ast_channel *chan;
07907 struct ast_frame *f;
07908
07909 idx = dahdi_get_index(ast, p, 0);
07910 if (idx < 0) {
07911 return &ast_null_frame;
07912 }
07913 mysig = p->sig;
07914 if (p->outsigmod > -1)
07915 mysig = p->outsigmod;
07916 p->subs[idx].f.frametype = AST_FRAME_NULL;
07917 p->subs[idx].f.subclass.integer = 0;
07918 p->subs[idx].f.datalen = 0;
07919 p->subs[idx].f.samples = 0;
07920 p->subs[idx].f.mallocd = 0;
07921 p->subs[idx].f.offset = 0;
07922 p->subs[idx].f.src = "dahdi_handle_event";
07923 p->subs[idx].f.data.ptr = NULL;
07924 f = &p->subs[idx].f;
07925
07926 if (p->fake_event) {
07927 res = p->fake_event;
07928 p->fake_event = 0;
07929 } else
07930 res = dahdi_get_event(p->subs[idx].dfd);
07931
07932 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07933
07934 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07935 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07936 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07937 #if defined(HAVE_PRI)
07938 if (dahdi_sig_pri_lib_handles(p->sig)
07939 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07940 && p->pri
07941 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07942
07943 } else
07944 #endif
07945 {
07946
07947 dahdi_confmute(p, 0);
07948 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07949 p->subs[idx].f.subclass.integer = res & 0xff;
07950 dahdi_handle_dtmf(ast, idx, &f);
07951 }
07952 return f;
07953 }
07954
07955 if (res & DAHDI_EVENT_DTMFDOWN) {
07956 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07957 #if defined(HAVE_PRI)
07958 if (dahdi_sig_pri_lib_handles(p->sig)
07959 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07960 && p->pri
07961 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07962
07963 } else
07964 #endif
07965 {
07966
07967 dahdi_confmute(p, 1);
07968 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07969 p->subs[idx].f.subclass.integer = res & 0xff;
07970 dahdi_handle_dtmf(ast, idx, &f);
07971 }
07972 return &p->subs[idx].f;
07973 }
07974
07975 switch (res) {
07976 case DAHDI_EVENT_EC_DISABLED:
07977 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07978 p->echocanon = 0;
07979 break;
07980 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07981 case DAHDI_EVENT_TX_CED_DETECTED:
07982 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07983 break;
07984 case DAHDI_EVENT_RX_CED_DETECTED:
07985 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07986 break;
07987 case DAHDI_EVENT_EC_NLP_DISABLED:
07988 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07989 break;
07990 case DAHDI_EVENT_EC_NLP_ENABLED:
07991 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07992 break;
07993 #endif
07994 case DAHDI_EVENT_BITSCHANGED:
07995 #ifdef HAVE_OPENR2
07996 if (p->sig != SIG_MFCR2) {
07997 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07998 } else {
07999 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
08000 openr2_chan_handle_cas(p->r2chan);
08001 }
08002 #else
08003 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
08004 #endif
08005 break;
08006 case DAHDI_EVENT_PULSE_START:
08007
08008 if (!ast->pbx)
08009 tone_zone_play_tone(p->subs[idx].dfd, -1);
08010 break;
08011 case DAHDI_EVENT_DIALCOMPLETE:
08012
08013 #if defined(HAVE_PRI)
08014 if (dahdi_sig_pri_lib_handles(p->sig)) {
08015 if (p->inalarm) {
08016 break;
08017 }
08018 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
08019 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
08020 strerror(errno));
08021 return NULL;
08022 }
08023 if (x) {
08024
08025 break;
08026 }
08027
08028
08029
08030
08031 sig_pri_dial_complete(p->sig_pvt, ast);
08032 break;
08033 }
08034 #endif
08035 #ifdef HAVE_OPENR2
08036 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08037
08038
08039 break;
08040 }
08041 #endif
08042 if (p->inalarm) break;
08043 if ((p->radio || (p->oprmode < 0))) break;
08044 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08045 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08046 return NULL;
08047 }
08048 if (!x) {
08049 dahdi_enable_ec(p);
08050 if (p->echobreak) {
08051 dahdi_train_ec(p);
08052 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08053 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08054 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08055 p->echobreak = 0;
08056 } else {
08057 p->dialing = 0;
08058 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08059
08060 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08061 ast_setstate(ast, AST_STATE_UP);
08062 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08063 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08064 break;
08065 } else {
08066
08067 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08068 }
08069 }
08070 if (ast->_state == AST_STATE_DIALING) {
08071 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08072 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08073 } else if (p->confirmanswer || (!p->dialednone
08074 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08075 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08076 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08077 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08078 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08079 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08080 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08081 || (mysig == SIG_SF_FEATB)))) {
08082 ast_setstate(ast, AST_STATE_RINGING);
08083 } else if (!p->answeronpolarityswitch) {
08084 ast_setstate(ast, AST_STATE_UP);
08085 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08086 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08087
08088 p->polarity = POLARITY_REV;
08089 } else {
08090
08091 p->polarity = POLARITY_IDLE;
08092 }
08093 }
08094 }
08095 }
08096 break;
08097 case DAHDI_EVENT_ALARM:
08098 switch (p->sig) {
08099 #if defined(HAVE_PRI)
08100 case SIG_PRI_LIB_HANDLE_CASES:
08101 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08102 break;
08103 #endif
08104 #if defined(HAVE_SS7)
08105 case SIG_SS7:
08106 sig_ss7_set_alarm(p->sig_pvt, 1);
08107 break;
08108 #endif
08109 default:
08110 p->inalarm = 1;
08111 break;
08112 }
08113 res = get_alarms(p);
08114 handle_alarms(p, res);
08115 #ifdef HAVE_PRI
08116 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08117
08118 } else {
08119 break;
08120 }
08121 #endif
08122 #if defined(HAVE_SS7)
08123 if (p->sig == SIG_SS7)
08124 break;
08125 #endif
08126 #ifdef HAVE_OPENR2
08127 if (p->sig == SIG_MFCR2)
08128 break;
08129 #endif
08130 case DAHDI_EVENT_ONHOOK:
08131 if (p->radio) {
08132 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08133 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08134 break;
08135 }
08136 if (p->oprmode < 0)
08137 {
08138 if (p->oprmode != -1) break;
08139 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08140 {
08141
08142 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08143 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08144 save_conference(p->oprpeer);
08145 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08146 }
08147 break;
08148 }
08149 switch (p->sig) {
08150 case SIG_FXOLS:
08151 case SIG_FXOGS:
08152 case SIG_FXOKS:
08153
08154 if (idx == SUB_REAL) {
08155
08156 if (p->subs[SUB_CALLWAIT].owner) {
08157
08158 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08159 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08160 unalloc_sub(p, SUB_CALLWAIT);
08161 #if 0
08162 p->subs[idx].needanswer = 0;
08163 p->subs[idx].needringing = 0;
08164 #endif
08165 p->callwaitingrepeat = 0;
08166 p->cidcwexpire = 0;
08167 p->cid_suppress_expire = 0;
08168 p->owner = NULL;
08169
08170 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08171 p->dialing = 1;
08172 dahdi_ring_phone(p);
08173 } else if (p->subs[SUB_THREEWAY].owner) {
08174 unsigned int mssinceflash;
08175
08176
08177 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08178
08179 DLA_UNLOCK(&p->lock);
08180 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08181
08182
08183
08184 DLA_LOCK(&p->lock);
08185 if (p->owner != ast) {
08186 ast_log(LOG_WARNING, "This isn't good...\n");
08187 return NULL;
08188 }
08189 }
08190 if (!p->subs[SUB_THREEWAY].owner) {
08191 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08192 return NULL;
08193 }
08194 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08195 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08196 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08197
08198
08199 if (p->subs[SUB_THREEWAY].owner)
08200 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08201 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08202 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08203 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08204 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08205 if (p->transfer) {
08206
08207 p->subs[SUB_REAL].inthreeway = 0;
08208 p->subs[SUB_THREEWAY].inthreeway = 0;
08209
08210 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08211 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08212
08213 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08214 p->owner = NULL;
08215
08216 dahdi_ring_phone(p);
08217 } else {
08218 if ((res = attempt_transfer(p)) < 0) {
08219 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08220 if (p->subs[SUB_THREEWAY].owner)
08221 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08222 } else if (res) {
08223
08224 if (p->subs[SUB_THREEWAY].owner)
08225 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08226 break;
08227 }
08228 }
08229 } else {
08230 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08231 if (p->subs[SUB_THREEWAY].owner)
08232 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08233 }
08234 } else {
08235 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08236
08237 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08238 p->owner = NULL;
08239
08240 dahdi_ring_phone(p);
08241 }
08242 }
08243 } else {
08244 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08245 }
08246
08247 default:
08248 dahdi_disable_ec(p);
08249 return NULL;
08250 }
08251 break;
08252 case DAHDI_EVENT_RINGOFFHOOK:
08253 if (p->inalarm) break;
08254 if (p->oprmode < 0)
08255 {
08256 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08257 {
08258
08259 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08260 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08261 restore_conference(p->oprpeer);
08262 }
08263 break;
08264 }
08265 if (p->radio)
08266 {
08267 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08268 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08269 break;
08270 }
08271
08272
08273 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08274 c = strchr(p->dialdest, '/');
08275 if (c)
08276 c++;
08277 else
08278 c = p->dialdest;
08279 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08280 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08281 if (strlen(p->dop.dialstr) > 4) {
08282 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08283 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08284 p->echorest[sizeof(p->echorest) - 1] = '\0';
08285 p->echobreak = 1;
08286 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08287 } else
08288 p->echobreak = 0;
08289 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08290 int saveerr = errno;
08291
08292 x = DAHDI_ONHOOK;
08293 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08294 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08295 return NULL;
08296 }
08297 p->dialing = 1;
08298 return &p->subs[idx].f;
08299 }
08300 switch (p->sig) {
08301 case SIG_FXOLS:
08302 case SIG_FXOGS:
08303 case SIG_FXOKS:
08304 switch (ast->_state) {
08305 case AST_STATE_RINGING:
08306 dahdi_enable_ec(p);
08307 dahdi_train_ec(p);
08308 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08309 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08310
08311 p->subs[SUB_REAL].needringing = 0;
08312 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08313 ast_debug(1, "channel %d answered\n", p->channel);
08314
08315
08316 ast_free(p->cidspill);
08317 p->cidspill = NULL;
08318 restore_conference(p);
08319
08320 p->dialing = 0;
08321 p->callwaitcas = 0;
08322 if (p->confirmanswer) {
08323
08324 p->subs[idx].f.frametype = AST_FRAME_NULL;
08325 p->subs[idx].f.subclass.integer = 0;
08326 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08327
08328 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08329 if (res < 0) {
08330 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08331 p->dop.dialstr[0] = '\0';
08332 return NULL;
08333 } else {
08334 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08335 p->subs[idx].f.frametype = AST_FRAME_NULL;
08336 p->subs[idx].f.subclass.integer = 0;
08337 p->dialing = 1;
08338 }
08339 p->dop.dialstr[0] = '\0';
08340 ast_setstate(ast, AST_STATE_DIALING);
08341 } else
08342 ast_setstate(ast, AST_STATE_UP);
08343 return &p->subs[idx].f;
08344 case AST_STATE_DOWN:
08345 ast_setstate(ast, AST_STATE_RING);
08346 ast->rings = 1;
08347 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08348 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08349 ast_debug(1, "channel %d picked up\n", p->channel);
08350 return &p->subs[idx].f;
08351 case AST_STATE_UP:
08352
08353 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08354
08355 if (ast_bridged_channel(p->owner))
08356 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08357 p->subs[idx].needunhold = 1;
08358 break;
08359 case AST_STATE_RESERVED:
08360
08361 if (has_voicemail(p))
08362 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08363 else
08364 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08365 break;
08366 default:
08367 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08368 }
08369 break;
08370 case SIG_FXSLS:
08371 case SIG_FXSGS:
08372 case SIG_FXSKS:
08373 if (ast->_state == AST_STATE_RING) {
08374 p->ringt = p->ringt_base;
08375 }
08376
08377
08378
08379 ast_debug(1, "Setting IDLE polarity due "
08380 "to ring. Old polarity was %d\n",
08381 p->polarity);
08382 p->polarity = POLARITY_IDLE;
08383
08384
08385 case SIG_EM:
08386 case SIG_EM_E1:
08387 case SIG_EMWINK:
08388 case SIG_FEATD:
08389 case SIG_FEATDMF:
08390 case SIG_FEATDMF_TA:
08391 case SIG_E911:
08392 case SIG_FGC_CAMA:
08393 case SIG_FGC_CAMAMF:
08394 case SIG_FEATB:
08395 case SIG_SF:
08396 case SIG_SFWINK:
08397 case SIG_SF_FEATD:
08398 case SIG_SF_FEATDMF:
08399 case SIG_SF_FEATB:
08400 if (ast->_state == AST_STATE_PRERING)
08401 ast_setstate(ast, AST_STATE_RING);
08402 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08403 ast_debug(1, "Ring detected\n");
08404 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08405 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08406 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08407 ast_debug(1, "Line answered\n");
08408 if (p->confirmanswer) {
08409 p->subs[idx].f.frametype = AST_FRAME_NULL;
08410 p->subs[idx].f.subclass.integer = 0;
08411 } else {
08412 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08413 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08414 ast_setstate(ast, AST_STATE_UP);
08415 }
08416 } else if (ast->_state != AST_STATE_RING)
08417 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08418 break;
08419 default:
08420 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08421 }
08422 break;
08423 case DAHDI_EVENT_RINGBEGIN:
08424 switch (p->sig) {
08425 case SIG_FXSLS:
08426 case SIG_FXSGS:
08427 case SIG_FXSKS:
08428 if (ast->_state == AST_STATE_RING) {
08429 p->ringt = p->ringt_base;
08430 }
08431 break;
08432 }
08433 break;
08434 case DAHDI_EVENT_RINGERON:
08435 break;
08436 case DAHDI_EVENT_NOALARM:
08437 switch (p->sig) {
08438 #if defined(HAVE_PRI)
08439 case SIG_PRI_LIB_HANDLE_CASES:
08440 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08441 break;
08442 #endif
08443 #if defined(HAVE_SS7)
08444 case SIG_SS7:
08445 sig_ss7_set_alarm(p->sig_pvt, 0);
08446 break;
08447 #endif
08448 default:
08449 p->inalarm = 0;
08450 break;
08451 }
08452 handle_clear_alarms(p);
08453 break;
08454 case DAHDI_EVENT_WINKFLASH:
08455 if (p->inalarm) break;
08456 if (p->radio) break;
08457 if (p->oprmode < 0) break;
08458 if (p->oprmode > 1)
08459 {
08460 struct dahdi_params par;
08461
08462 memset(&par, 0, sizeof(par));
08463 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08464 {
08465 if (!par.rxisoffhook)
08466 {
08467
08468 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08469 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08470 save_conference(p);
08471 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08472 }
08473 }
08474 break;
08475 }
08476
08477 p->flashtime = ast_tvnow();
08478 switch (mysig) {
08479 case SIG_FXOLS:
08480 case SIG_FXOGS:
08481 case SIG_FXOKS:
08482 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08483 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08484
08485
08486 ast_free(p->cidspill);
08487 p->cidspill = NULL;
08488 restore_conference(p);
08489 p->callwaitcas = 0;
08490
08491 if (idx != SUB_REAL) {
08492 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08493 goto winkflashdone;
08494 }
08495
08496 if (p->subs[SUB_CALLWAIT].owner) {
08497
08498 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08499 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08500 p->owner = p->subs[SUB_REAL].owner;
08501 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08502 if (p->owner->_state == AST_STATE_RINGING) {
08503 ast_setstate(p->owner, AST_STATE_UP);
08504 p->subs[SUB_REAL].needanswer = 1;
08505 }
08506 p->callwaitingrepeat = 0;
08507 p->cidcwexpire = 0;
08508 p->cid_suppress_expire = 0;
08509
08510 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08511 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08512 S_OR(p->mohsuggest, NULL),
08513 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08514 }
08515 p->subs[SUB_CALLWAIT].needhold = 1;
08516 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08517 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08518 S_OR(p->mohsuggest, NULL),
08519 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08520 }
08521 p->subs[SUB_REAL].needunhold = 1;
08522 } else if (!p->subs[SUB_THREEWAY].owner) {
08523 if (!p->threewaycalling) {
08524
08525 p->subs[SUB_REAL].needflash = 1;
08526 goto winkflashdone;
08527 } else if (!check_for_conference(p)) {
08528 char cid_num[256];
08529 char cid_name[256];
08530
08531 cid_num[0] = 0;
08532 cid_name[0] = 0;
08533 if (p->dahditrcallerid && p->owner) {
08534 if (p->owner->caller.id.number.valid
08535 && p->owner->caller.id.number.str) {
08536 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08537 sizeof(cid_num));
08538 }
08539 if (p->owner->caller.id.name.valid
08540 && p->owner->caller.id.name.str) {
08541 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08542 sizeof(cid_name));
08543 }
08544 }
08545
08546
08547 if (!((ast->pbx) ||
08548 (ast->_state == AST_STATE_UP) ||
08549 (ast->_state == AST_STATE_RING))) {
08550 ast_debug(1, "Flash when call not up or ringing\n");
08551 goto winkflashdone;
08552 }
08553 if (alloc_sub(p, SUB_THREEWAY)) {
08554 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08555 goto winkflashdone;
08556 }
08557
08558
08559
08560
08561
08562
08563
08564 ast_mutex_unlock(&p->lock);
08565 ast_channel_unlock(ast);
08566 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08567 ast_channel_lock(ast);
08568 ast_mutex_lock(&p->lock);
08569 if (p->dahditrcallerid) {
08570 if (!p->origcid_num)
08571 p->origcid_num = ast_strdup(p->cid_num);
08572 if (!p->origcid_name)
08573 p->origcid_name = ast_strdup(p->cid_name);
08574 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08575 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08576 }
08577
08578 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08579
08580 dahdi_disable_ec(p);
08581 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08582 if (res)
08583 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08584 p->owner = chan;
08585 if (!chan) {
08586 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08587 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08588 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08589 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08590 dahdi_enable_ec(p);
08591 ast_hangup(chan);
08592 } else {
08593 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08594
08595
08596 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08597 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08598 S_OR(p->mohsuggest, NULL),
08599 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08600 }
08601 p->subs[SUB_THREEWAY].needhold = 1;
08602 }
08603 }
08604 } else {
08605
08606 if (p->subs[SUB_THREEWAY].inthreeway) {
08607
08608 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08609
08610 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08611
08612 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08613 p->owner = p->subs[SUB_REAL].owner;
08614 }
08615
08616 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08617 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08618 p->subs[SUB_REAL].inthreeway = 0;
08619 p->subs[SUB_THREEWAY].inthreeway = 0;
08620 } else {
08621
08622 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08623 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08624 int otherindex = SUB_THREEWAY;
08625
08626 ast_verb(3, "Building conference call with %s and %s\n",
08627 p->subs[SUB_THREEWAY].owner->name,
08628 p->subs[SUB_REAL].owner->name);
08629
08630 p->subs[SUB_THREEWAY].inthreeway = 1;
08631 p->subs[SUB_REAL].inthreeway = 1;
08632 if (ast->_state == AST_STATE_UP) {
08633 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08634 otherindex = SUB_REAL;
08635 }
08636 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08637 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08638 p->subs[otherindex].needunhold = 1;
08639 p->owner = p->subs[SUB_REAL].owner;
08640 } else {
08641 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08642 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08643 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08644 p->owner = p->subs[SUB_REAL].owner;
08645 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08646 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08647 p->subs[SUB_REAL].needunhold = 1;
08648 dahdi_enable_ec(p);
08649 }
08650 }
08651 }
08652 winkflashdone:
08653 update_conf(p);
08654 break;
08655 case SIG_EM:
08656 case SIG_EM_E1:
08657 case SIG_FEATD:
08658 case SIG_SF:
08659 case SIG_SFWINK:
08660 case SIG_SF_FEATD:
08661 case SIG_FXSLS:
08662 case SIG_FXSGS:
08663 if (p->dialing)
08664 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08665 else
08666 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08667 break;
08668 case SIG_FEATDMF_TA:
08669 switch (p->whichwink) {
08670 case 0:
08671 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08672 S_COR(p->owner->caller.ani.number.valid,
08673 p->owner->caller.ani.number.str, ""));
08674 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08675 p->owner->caller.ani2,
08676 S_COR(p->owner->caller.ani.number.valid,
08677 p->owner->caller.ani.number.str, ""));
08678 break;
08679 case 1:
08680 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08681 break;
08682 case 2:
08683 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08684 return NULL;
08685 }
08686 p->whichwink++;
08687
08688 case SIG_FEATDMF:
08689 case SIG_E911:
08690 case SIG_FGC_CAMAMF:
08691 case SIG_FGC_CAMA:
08692 case SIG_FEATB:
08693 case SIG_SF_FEATDMF:
08694 case SIG_SF_FEATB:
08695 case SIG_EMWINK:
08696
08697 if (!ast_strlen_zero(p->dop.dialstr)) {
08698 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08699 if (res < 0) {
08700 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08701 p->dop.dialstr[0] = '\0';
08702 return NULL;
08703 } else
08704 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08705 }
08706 p->dop.dialstr[0] = '\0';
08707 break;
08708 default:
08709 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08710 }
08711 break;
08712 case DAHDI_EVENT_HOOKCOMPLETE:
08713 if (p->inalarm) break;
08714 if ((p->radio || (p->oprmode < 0))) break;
08715 if (p->waitingfordt.tv_sec) break;
08716 switch (mysig) {
08717 case SIG_FXSLS:
08718 case SIG_FXSGS:
08719 case SIG_FXSKS:
08720 case SIG_EM:
08721 case SIG_EM_E1:
08722 case SIG_EMWINK:
08723 case SIG_FEATD:
08724 case SIG_SF:
08725 case SIG_SFWINK:
08726 case SIG_SF_FEATD:
08727 if (!ast_strlen_zero(p->dop.dialstr)) {
08728 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08729 if (res < 0) {
08730 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08731 p->dop.dialstr[0] = '\0';
08732 return NULL;
08733 } else
08734 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08735 }
08736 p->dop.dialstr[0] = '\0';
08737 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08738 break;
08739 case SIG_FEATDMF:
08740 case SIG_FEATDMF_TA:
08741 case SIG_E911:
08742 case SIG_FGC_CAMA:
08743 case SIG_FGC_CAMAMF:
08744 case SIG_FEATB:
08745 case SIG_SF_FEATDMF:
08746 case SIG_SF_FEATB:
08747 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08748 break;
08749 default:
08750 break;
08751 }
08752 break;
08753 case DAHDI_EVENT_POLARITY:
08754
08755
08756
08757
08758
08759
08760 if (p->polarity == POLARITY_IDLE) {
08761 p->polarity = POLARITY_REV;
08762 if (p->answeronpolarityswitch &&
08763 ((ast->_state == AST_STATE_DIALING) ||
08764 (ast->_state == AST_STATE_RINGING))) {
08765 ast_debug(1, "Answering on polarity switch!\n");
08766 ast_setstate(p->owner, AST_STATE_UP);
08767 if (p->hanguponpolarityswitch) {
08768 p->polaritydelaytv = ast_tvnow();
08769 }
08770 } else
08771 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08772 }
08773
08774
08775 if (p->hanguponpolarityswitch &&
08776 (p->polarityonanswerdelay > 0) &&
08777 (p->polarity == POLARITY_REV) &&
08778 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08779
08780 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08781
08782 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08783 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08784 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08785 p->polarity = POLARITY_IDLE;
08786 } else
08787 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
08788
08789 } else {
08790 p->polarity = POLARITY_IDLE;
08791 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08792 }
08793
08794 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %" PRIi64 "\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
08795 break;
08796 default:
08797 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08798 }
08799 return &p->subs[idx].f;
08800 }
08801
08802 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08803 {
08804 int res;
08805 int idx;
08806 struct ast_frame *f;
08807 int usedindex = -1;
08808 struct dahdi_pvt *p = ast->tech_pvt;
08809
08810 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08811 idx = SUB_REAL;
08812 }
08813
08814 p->subs[idx].f.frametype = AST_FRAME_NULL;
08815 p->subs[idx].f.datalen = 0;
08816 p->subs[idx].f.samples = 0;
08817 p->subs[idx].f.mallocd = 0;
08818 p->subs[idx].f.offset = 0;
08819 p->subs[idx].f.subclass.integer = 0;
08820 p->subs[idx].f.delivery = ast_tv(0,0);
08821 p->subs[idx].f.src = "dahdi_exception";
08822 p->subs[idx].f.data.ptr = NULL;
08823
08824
08825 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08826
08827
08828
08829
08830
08831 if (p->fake_event) {
08832 res = p->fake_event;
08833 p->fake_event = 0;
08834 } else
08835 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08836
08837 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08838 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08839 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08840 p->owner = p->subs[SUB_REAL].owner;
08841 if (p->owner && ast_bridged_channel(p->owner))
08842 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08843 p->subs[SUB_REAL].needunhold = 1;
08844 }
08845 switch (res) {
08846 case DAHDI_EVENT_ONHOOK:
08847 dahdi_disable_ec(p);
08848 if (p->owner) {
08849 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08850 dahdi_ring_phone(p);
08851 p->callwaitingrepeat = 0;
08852 p->cidcwexpire = 0;
08853 p->cid_suppress_expire = 0;
08854 } else
08855 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08856 update_conf(p);
08857 break;
08858 case DAHDI_EVENT_RINGOFFHOOK:
08859 dahdi_enable_ec(p);
08860 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08861 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08862 p->subs[SUB_REAL].needanswer = 1;
08863 p->dialing = 0;
08864 }
08865 break;
08866 case DAHDI_EVENT_HOOKCOMPLETE:
08867 case DAHDI_EVENT_RINGERON:
08868 case DAHDI_EVENT_RINGEROFF:
08869
08870 break;
08871 case DAHDI_EVENT_WINKFLASH:
08872 p->flashtime = ast_tvnow();
08873 if (p->owner) {
08874 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08875 if (p->owner->_state != AST_STATE_UP) {
08876
08877 usedindex = dahdi_get_index(p->owner, p, 0);
08878 if (usedindex > -1) {
08879 p->subs[usedindex].needanswer = 1;
08880 }
08881 ast_setstate(p->owner, AST_STATE_UP);
08882 }
08883 p->callwaitingrepeat = 0;
08884 p->cidcwexpire = 0;
08885 p->cid_suppress_expire = 0;
08886 if (ast_bridged_channel(p->owner))
08887 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08888 p->subs[SUB_REAL].needunhold = 1;
08889 } else
08890 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08891 update_conf(p);
08892 break;
08893 default:
08894 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08895 }
08896 f = &p->subs[idx].f;
08897 return f;
08898 }
08899 if (!(p->radio || (p->oprmode < 0)))
08900 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08901
08902 if (ast != p->owner) {
08903 if (p->owner) {
08904 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08905 }
08906 f = &p->subs[idx].f;
08907 return f;
08908 }
08909
08910 f = dahdi_handle_event(ast);
08911 if (!f) {
08912 const char *name = ast_strdupa(ast->name);
08913
08914
08915 ast_mutex_unlock(&p->lock);
08916 ast_channel_unlock(ast);
08917 ast_set_hangupsource(ast, name, 0);
08918 ast_channel_lock(ast);
08919 ast_mutex_lock(&p->lock);
08920 }
08921 return f;
08922 }
08923
08924 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08925 {
08926 struct dahdi_pvt *p = ast->tech_pvt;
08927 struct ast_frame *f;
08928 ast_mutex_lock(&p->lock);
08929 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08930 struct analog_pvt *analog_p = p->sig_pvt;
08931 f = analog_exception(analog_p, ast);
08932 } else {
08933 f = __dahdi_exception(ast);
08934 }
08935 ast_mutex_unlock(&p->lock);
08936 return f;
08937 }
08938
08939 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08940 {
08941 struct dahdi_pvt *p;
08942 int res;
08943 int idx;
08944 void *readbuf;
08945 struct ast_frame *f;
08946
08947
08948
08949
08950
08951
08952 p = ast->tech_pvt;
08953 while (ast_mutex_trylock(&p->lock)) {
08954 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08955
08956
08957
08958
08959
08960
08961
08962
08963
08964
08965
08966
08967 if (ast->tech_pvt != p) {
08968
08969 return &ast_null_frame;
08970 }
08971 }
08972
08973 idx = dahdi_get_index(ast, p, 0);
08974
08975
08976 if (idx < 0) {
08977 ast_log(LOG_WARNING, "We don't exist?\n");
08978 ast_mutex_unlock(&p->lock);
08979 return NULL;
08980 }
08981
08982 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08983 ast_mutex_unlock(&p->lock);
08984 return NULL;
08985 }
08986
08987 p->subs[idx].f.frametype = AST_FRAME_NULL;
08988 p->subs[idx].f.datalen = 0;
08989 p->subs[idx].f.samples = 0;
08990 p->subs[idx].f.mallocd = 0;
08991 p->subs[idx].f.offset = 0;
08992 p->subs[idx].f.subclass.integer = 0;
08993 p->subs[idx].f.delivery = ast_tv(0,0);
08994 p->subs[idx].f.src = "dahdi_read";
08995 p->subs[idx].f.data.ptr = NULL;
08996
08997
08998 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08999 {
09000 struct dahdi_params ps;
09001
09002 memset(&ps, 0, sizeof(ps));
09003 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
09004 ast_mutex_unlock(&p->lock);
09005 return NULL;
09006 }
09007 p->firstradio = 1;
09008 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09009 if (ps.rxisoffhook)
09010 {
09011 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
09012 }
09013 else
09014 {
09015 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
09016 }
09017 ast_mutex_unlock(&p->lock);
09018 return &p->subs[idx].f;
09019 }
09020 if (p->ringt > 0) {
09021 if (!(--p->ringt)) {
09022 ast_mutex_unlock(&p->lock);
09023 return NULL;
09024 }
09025 }
09026
09027 #ifdef HAVE_OPENR2
09028 if (p->mfcr2) {
09029 openr2_chan_process_event(p->r2chan);
09030 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
09031 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09032
09033
09034 if (p->mfcr2_call_accepted &&
09035 !p->mfcr2_progress &&
09036 ast->_state == AST_STATE_RINGING) {
09037 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09038 ast_queue_frame(p->owner, &f);
09039 p->mfcr2_progress = 1;
09040 }
09041 }
09042 }
09043 #endif
09044
09045 if (p->subs[idx].needringing) {
09046
09047 p->subs[idx].needringing = 0;
09048 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09049 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09050 ast_setstate(ast, AST_STATE_RINGING);
09051 ast_mutex_unlock(&p->lock);
09052 return &p->subs[idx].f;
09053 }
09054
09055 if (p->subs[idx].needbusy) {
09056
09057 p->subs[idx].needbusy = 0;
09058 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09059 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09060 ast_mutex_unlock(&p->lock);
09061 return &p->subs[idx].f;
09062 }
09063
09064 if (p->subs[idx].needcongestion) {
09065
09066 p->subs[idx].needcongestion = 0;
09067 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09068 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09069 ast_mutex_unlock(&p->lock);
09070 return &p->subs[idx].f;
09071 }
09072
09073 if (p->subs[idx].needanswer) {
09074
09075 p->subs[idx].needanswer = 0;
09076 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09077 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09078 ast_mutex_unlock(&p->lock);
09079 return &p->subs[idx].f;
09080 }
09081 #ifdef HAVE_OPENR2
09082 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09083
09084
09085
09086
09087 ast_mutex_unlock(&p->lock);
09088 return &ast_null_frame;
09089 }
09090 #endif
09091
09092 if (p->subs[idx].needflash) {
09093
09094 p->subs[idx].needflash = 0;
09095 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09096 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09097 ast_mutex_unlock(&p->lock);
09098 return &p->subs[idx].f;
09099 }
09100
09101 if (p->subs[idx].needhold) {
09102
09103 p->subs[idx].needhold = 0;
09104 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09105 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09106 ast_mutex_unlock(&p->lock);
09107 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09108 return &p->subs[idx].f;
09109 }
09110
09111 if (p->subs[idx].needunhold) {
09112
09113 p->subs[idx].needunhold = 0;
09114 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09115 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09116 ast_mutex_unlock(&p->lock);
09117 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09118 return &p->subs[idx].f;
09119 }
09120
09121
09122
09123
09124
09125 if (p->fake_event && p->owner == ast) {
09126 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09127 struct analog_pvt *analog_p = p->sig_pvt;
09128
09129 f = analog_exception(analog_p, ast);
09130 } else {
09131 f = __dahdi_exception(ast);
09132 }
09133 ast_mutex_unlock(&p->lock);
09134 return f;
09135 }
09136
09137 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09138 if (!p->subs[idx].linear) {
09139 p->subs[idx].linear = 1;
09140 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09141 if (res)
09142 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09143 }
09144 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09145 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09146 if (p->subs[idx].linear) {
09147 p->subs[idx].linear = 0;
09148 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09149 if (res)
09150 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09151 }
09152 } else {
09153 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09154 ast_mutex_unlock(&p->lock);
09155 return NULL;
09156 }
09157 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09158 CHECK_BLOCKING(ast);
09159 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09160 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09161
09162 if (res < 0) {
09163 f = NULL;
09164 if (res == -1) {
09165 if (errno == EAGAIN) {
09166
09167 ast_mutex_unlock(&p->lock);
09168 return &p->subs[idx].f;
09169 } else if (errno == ELAST) {
09170 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09171 struct analog_pvt *analog_p = p->sig_pvt;
09172 f = analog_exception(analog_p, ast);
09173 } else {
09174 f = __dahdi_exception(ast);
09175 }
09176 } else
09177 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09178 }
09179 ast_mutex_unlock(&p->lock);
09180 return f;
09181 }
09182 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09183 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09184 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09185 struct analog_pvt *analog_p = p->sig_pvt;
09186 f = analog_exception(analog_p, ast);
09187 } else {
09188 f = __dahdi_exception(ast);
09189 }
09190 ast_mutex_unlock(&p->lock);
09191 return f;
09192 }
09193 if (p->tdd) {
09194 int c;
09195
09196 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09197 if (c < 0) {
09198 ast_debug(1,"tdd_feed failed\n");
09199 ast_mutex_unlock(&p->lock);
09200 return NULL;
09201 }
09202 if (c) {
09203 p->subs[idx].f.subclass.integer = 0;
09204 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09205 p->subs[idx].f.mallocd = 0;
09206 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09207 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09208 p->subs[idx].f.datalen = 1;
09209 *((char *) p->subs[idx].f.data.ptr) = c;
09210 ast_mutex_unlock(&p->lock);
09211 return &p->subs[idx].f;
09212 }
09213 }
09214 if (idx == SUB_REAL) {
09215
09216 if (p->cidcwexpire) {
09217 if (!--p->cidcwexpire) {
09218
09219 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09220 restore_conference(p);
09221 }
09222 }
09223 if (p->cid_suppress_expire) {
09224 --p->cid_suppress_expire;
09225 }
09226 if (p->callwaitingrepeat) {
09227 if (!--p->callwaitingrepeat) {
09228
09229 ++p->callwaitrings;
09230 dahdi_callwait(ast);
09231 }
09232 }
09233 }
09234 if (p->subs[idx].linear) {
09235 p->subs[idx].f.datalen = READ_SIZE * 2;
09236 } else
09237 p->subs[idx].f.datalen = READ_SIZE;
09238
09239
09240 if ((p->owner == ast) && p->cidspill) {
09241 send_callerid(p);
09242 }
09243
09244 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09245 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09246 p->subs[idx].f.samples = READ_SIZE;
09247 p->subs[idx].f.mallocd = 0;
09248 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09249 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09250 #if 0
09251 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09252 #endif
09253 if (p->dialing || p->radio ||
09254 (idx && (ast->_state != AST_STATE_UP)) ||
09255 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09256 ) {
09257
09258
09259 p->subs[idx].f.frametype = AST_FRAME_NULL;
09260 p->subs[idx].f.subclass.integer = 0;
09261 p->subs[idx].f.samples = 0;
09262 p->subs[idx].f.mallocd = 0;
09263 p->subs[idx].f.offset = 0;
09264 p->subs[idx].f.data.ptr = NULL;
09265 p->subs[idx].f.datalen= 0;
09266 }
09267 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09268
09269 int mute;
09270
09271 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09272
09273
09274 mute = ast_dsp_was_muted(p->dsp);
09275 if (p->muting != mute) {
09276 p->muting = mute;
09277 dahdi_confmute(p, mute);
09278 }
09279
09280 if (f) {
09281 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09282 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09283
09284
09285 ast_frfree(f);
09286 f = NULL;
09287 }
09288 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09289 || f->frametype == AST_FRAME_DTMF_END) {
09290 #ifdef HAVE_PRI
09291 if (dahdi_sig_pri_lib_handles(p->sig)
09292 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09293 && p->pri
09294 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09295 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09296
09297 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09298 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09299 f->subclass.integer, f->subclass.integer, ast->name);
09300
09301 f->frametype = AST_FRAME_NULL;
09302 f->subclass.integer = 0;
09303 }
09304 #endif
09305
09306 p->pulsedial = 0;
09307 } else if (p->waitingfordt.tv_sec) {
09308 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09309 p->waitingfordt.tv_sec = 0;
09310 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09311 ast_frfree(f);
09312 f = NULL;
09313 } else if (f->frametype == AST_FRAME_VOICE) {
09314 f->frametype = AST_FRAME_NULL;
09315 f->subclass.integer = 0;
09316 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) {
09317 p->waitingfordt.tv_sec = 0;
09318 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09319 ast_dsp_set_features(p->dsp, p->dsp_features);
09320 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09321 if (!ast_strlen_zero(p->dop.dialstr)) {
09322 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09323 if (res < 0) {
09324 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09325 p->dop.dialstr[0] = '\0';
09326 ast_mutex_unlock(&p->lock);
09327 ast_frfree(f);
09328 return NULL;
09329 } else {
09330 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09331 p->dialing = 1;
09332 p->dop.dialstr[0] = '\0';
09333 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09334 ast_setstate(ast, AST_STATE_DIALING);
09335 }
09336 }
09337 }
09338 }
09339 }
09340 }
09341 } else
09342 f = &p->subs[idx].f;
09343
09344 if (f) {
09345 switch (f->frametype) {
09346 case AST_FRAME_DTMF_BEGIN:
09347 case AST_FRAME_DTMF_END:
09348 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09349 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09350 } else {
09351 dahdi_handle_dtmf(ast, idx, &f);
09352 }
09353 break;
09354 case AST_FRAME_VOICE:
09355 if (p->cidspill || p->cid_suppress_expire) {
09356
09357 p->subs[idx].f.frametype = AST_FRAME_NULL;
09358 p->subs[idx].f.subclass.integer = 0;
09359 p->subs[idx].f.samples = 0;
09360 p->subs[idx].f.mallocd = 0;
09361 p->subs[idx].f.offset = 0;
09362 p->subs[idx].f.data.ptr = NULL;
09363 p->subs[idx].f.datalen= 0;
09364 }
09365 break;
09366 default:
09367 break;
09368 }
09369 }
09370
09371 ast_mutex_unlock(&p->lock);
09372 return f;
09373 }
09374
09375 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09376 {
09377 int sent=0;
09378 int size;
09379 int res;
09380 int fd;
09381 fd = p->subs[idx].dfd;
09382 while (len) {
09383 size = len;
09384 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09385 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09386 res = write(fd, buf, size);
09387 if (res != size) {
09388 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09389 return sent;
09390 }
09391 len -= size;
09392 buf += size;
09393 }
09394 return sent;
09395 }
09396
09397 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09398 {
09399 struct dahdi_pvt *p = ast->tech_pvt;
09400 int res;
09401 int idx;
09402 idx = dahdi_get_index(ast, p, 0);
09403 if (idx < 0) {
09404 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09405 return -1;
09406 }
09407
09408
09409 if (frame->frametype != AST_FRAME_VOICE) {
09410 if (frame->frametype != AST_FRAME_IMAGE)
09411 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09412 return 0;
09413 }
09414 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09415 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09416 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09417 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09418 return -1;
09419 }
09420 if (p->dialing) {
09421 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09422 return 0;
09423 }
09424 if (!p->owner) {
09425 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09426 return 0;
09427 }
09428 if (p->cidspill) {
09429 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09430 ast->name);
09431 return 0;
09432 }
09433
09434 if (!frame->data.ptr || !frame->datalen)
09435 return 0;
09436
09437 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09438 if (!p->subs[idx].linear) {
09439 p->subs[idx].linear = 1;
09440 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09441 if (res)
09442 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09443 }
09444 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09445 } else {
09446
09447 if (p->subs[idx].linear) {
09448 p->subs[idx].linear = 0;
09449 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09450 if (res)
09451 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09452 }
09453 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09454 }
09455 if (res < 0) {
09456 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09457 return -1;
09458 }
09459 return 0;
09460 }
09461
09462 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09463 {
09464 struct dahdi_pvt *p = chan->tech_pvt;
09465 int res=-1;
09466 int idx;
09467 int func = DAHDI_FLASH;
09468
09469 ast_mutex_lock(&p->lock);
09470 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09471 switch (p->sig) {
09472 #if defined(HAVE_PRI)
09473 case SIG_PRI_LIB_HANDLE_CASES:
09474 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09475 ast_mutex_unlock(&p->lock);
09476 return res;
09477 #endif
09478 #if defined(HAVE_SS7)
09479 case SIG_SS7:
09480 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09481 ast_mutex_unlock(&p->lock);
09482 return res;
09483 #endif
09484 default:
09485 break;
09486 }
09487 #ifdef HAVE_OPENR2
09488 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09489 ast_mutex_unlock(&p->lock);
09490
09491
09492 return 0;
09493 }
09494 #endif
09495 idx = dahdi_get_index(chan, p, 0);
09496 if (idx == SUB_REAL) {
09497 switch (condition) {
09498 case AST_CONTROL_BUSY:
09499 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09500 break;
09501 case AST_CONTROL_RINGING:
09502 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09503
09504 if (chan->_state != AST_STATE_UP) {
09505 if ((chan->_state != AST_STATE_RING) ||
09506 ((p->sig != SIG_FXSKS) &&
09507 (p->sig != SIG_FXSLS) &&
09508 (p->sig != SIG_FXSGS)))
09509 ast_setstate(chan, AST_STATE_RINGING);
09510 }
09511 break;
09512 case AST_CONTROL_INCOMPLETE:
09513 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09514
09515 res = 0;
09516 break;
09517 case AST_CONTROL_PROCEEDING:
09518 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09519
09520 res = 0;
09521 break;
09522 case AST_CONTROL_PROGRESS:
09523 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09524
09525 res = 0;
09526 break;
09527 case AST_CONTROL_CONGESTION:
09528
09529 switch (chan->hangupcause) {
09530 case AST_CAUSE_USER_BUSY:
09531 case AST_CAUSE_NORMAL_CLEARING:
09532 case 0:
09533
09534 chan->hangupcause = AST_CAUSE_CONGESTION;
09535 break;
09536 default:
09537 break;
09538 }
09539 break;
09540 case AST_CONTROL_HOLD:
09541 ast_moh_start(chan, data, p->mohinterpret);
09542 break;
09543 case AST_CONTROL_UNHOLD:
09544 ast_moh_stop(chan);
09545 break;
09546 case AST_CONTROL_RADIO_KEY:
09547 if (p->radio)
09548 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09549 res = 0;
09550 break;
09551 case AST_CONTROL_RADIO_UNKEY:
09552 if (p->radio)
09553 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09554 res = 0;
09555 break;
09556 case AST_CONTROL_FLASH:
09557
09558 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09559
09560 p->dop.dialstr[0] = '\0';
09561 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09562 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09563 chan->name, strerror(errno));
09564 } else
09565 res = 0;
09566 } else
09567 res = 0;
09568 break;
09569 case AST_CONTROL_SRCUPDATE:
09570 res = 0;
09571 break;
09572 case -1:
09573 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09574 break;
09575 }
09576 } else {
09577 res = 0;
09578 }
09579 ast_mutex_unlock(&p->lock);
09580 return res;
09581 }
09582
09583 #if defined(HAVE_PRI)
09584 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09585 #else
09586 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09587 #endif
09588 {
09589 struct ast_str *chan_name;
09590 int x, y;
09591
09592
09593 if (!(chan_name = ast_str_create(32))) {
09594 return NULL;
09595 }
09596 if (i->channel == CHAN_PSEUDO) {
09597 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09598 #if defined(HAVE_PRI)
09599 } else if (i->pri) {
09600 ast_mutex_lock(&i->pri->lock);
09601 y = ++i->pri->new_chan_seq;
09602 if (is_outgoing) {
09603 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09604 address[0] = '\0';
09605 } else if (ast_strlen_zero(i->cid_subaddr)) {
09606
09607 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09608 } else {
09609
09610 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09611 i->cid_subaddr, y);
09612 }
09613 ast_mutex_unlock(&i->pri->lock);
09614 #endif
09615 } else {
09616 y = 1;
09617 do {
09618 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09619 for (x = 0; x < 3; ++x) {
09620 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09621 i->subs[x].owner->name + 6)) {
09622 break;
09623 }
09624 }
09625 ++y;
09626 } while (x < 3);
09627 }
09628 return chan_name;
09629 }
09630
09631 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09632 {
09633 struct ast_channel *tmp;
09634 format_t deflaw;
09635 int x;
09636 int features;
09637 struct ast_str *chan_name;
09638 struct ast_variable *v;
09639 char *dashptr;
09640 char device_name[AST_CHANNEL_NAME];
09641
09642 if (i->subs[idx].owner) {
09643 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09644 return NULL;
09645 }
09646
09647 #if defined(HAVE_PRI)
09648
09649
09650
09651
09652 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09653 #else
09654 chan_name = create_channel_name(i);
09655 #endif
09656 if (!chan_name) {
09657 return NULL;
09658 }
09659
09660 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));
09661 ast_free(chan_name);
09662 if (!tmp)
09663 return NULL;
09664 tmp->tech = &dahdi_tech;
09665 #if defined(HAVE_PRI)
09666 if (i->pri) {
09667 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09668 }
09669 #endif
09670 ast_channel_cc_params_init(tmp, i->cc_params);
09671 if (law) {
09672 i->law = law;
09673 if (law == DAHDI_LAW_ALAW) {
09674 deflaw = AST_FORMAT_ALAW;
09675 } else {
09676 deflaw = AST_FORMAT_ULAW;
09677 }
09678 } else {
09679 switch (i->sig) {
09680 case SIG_PRI_LIB_HANDLE_CASES:
09681
09682 i->law = (i->law_default == DAHDI_LAW_ALAW)
09683 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09684 break;
09685 default:
09686 i->law = i->law_default;
09687 break;
09688 }
09689 if (i->law_default == DAHDI_LAW_ALAW) {
09690 deflaw = AST_FORMAT_ALAW;
09691 } else {
09692 deflaw = AST_FORMAT_ULAW;
09693 }
09694 }
09695 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09696 tmp->nativeformats = deflaw;
09697
09698 tmp->rawreadformat = deflaw;
09699 tmp->readformat = deflaw;
09700 tmp->rawwriteformat = deflaw;
09701 tmp->writeformat = deflaw;
09702 i->subs[idx].linear = 0;
09703 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09704 features = 0;
09705 if (idx == SUB_REAL) {
09706 if (i->busydetect && CANBUSYDETECT(i))
09707 features |= DSP_FEATURE_BUSY_DETECT;
09708 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09709 features |= DSP_FEATURE_CALL_PROGRESS;
09710 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09711 features |= DSP_FEATURE_WAITDIALTONE;
09712 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09713 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09714 features |= DSP_FEATURE_FAX_DETECT;
09715 }
09716 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09717 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09718 i->hardwaredtmf = 0;
09719 features |= DSP_FEATURE_DIGIT_DETECT;
09720 } else if (NEED_MFDETECT(i)) {
09721 i->hardwaredtmf = 1;
09722 features |= DSP_FEATURE_DIGIT_DETECT;
09723 }
09724 }
09725 if (features) {
09726 if (i->dsp) {
09727 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09728 } else {
09729 if (i->channel != CHAN_PSEUDO)
09730 i->dsp = ast_dsp_new();
09731 else
09732 i->dsp = NULL;
09733 if (i->dsp) {
09734 i->dsp_features = features;
09735 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09736
09737 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09738
09739
09740 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09741 features = 0;
09742 }
09743 #endif
09744 ast_dsp_set_features(i->dsp, features);
09745 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09746 if (!ast_strlen_zero(progzone))
09747 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09748 if (i->busydetect && CANBUSYDETECT(i)) {
09749 if(i->silencethreshold > 0)
09750 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09751 ast_dsp_set_busy_count(i->dsp, i->busycount);
09752 if(i->busytonelength > 0)
09753 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09754 if((i->busytonelength == i->busyquietlength) && i->busycompare)
09755 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09756 }
09757 }
09758 }
09759 }
09760
09761 if (state == AST_STATE_RING)
09762 tmp->rings = 1;
09763 tmp->tech_pvt = i;
09764 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09765
09766 tmp->callgroup = i->callgroup;
09767 tmp->pickupgroup = i->pickupgroup;
09768 }
09769 if (!ast_strlen_zero(i->parkinglot))
09770 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09771 if (!ast_strlen_zero(i->language))
09772 ast_string_field_set(tmp, language, i->language);
09773 if (!i->owner)
09774 i->owner = tmp;
09775 if (!ast_strlen_zero(i->accountcode))
09776 ast_string_field_set(tmp, accountcode, i->accountcode);
09777 if (i->amaflags)
09778 tmp->amaflags = i->amaflags;
09779 i->subs[idx].owner = tmp;
09780 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09781 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09782 ast_string_field_set(tmp, call_forward, i->call_forward);
09783 }
09784
09785 if (!i->adsi)
09786 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09787 if (!ast_strlen_zero(i->exten))
09788 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09789 if (!ast_strlen_zero(i->rdnis)) {
09790 tmp->redirecting.from.number.valid = 1;
09791 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09792 }
09793 if (!ast_strlen_zero(i->dnid)) {
09794 tmp->dialed.number.str = ast_strdup(i->dnid);
09795 }
09796
09797
09798
09799 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09800 if (!ast_strlen_zero(i->cid_ani)) {
09801 tmp->caller.ani.number.valid = 1;
09802 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09803 } else if (!ast_strlen_zero(i->cid_num)) {
09804 tmp->caller.ani.number.valid = 1;
09805 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09806 }
09807 #else
09808 if (!ast_strlen_zero(i->cid_num)) {
09809 tmp->caller.ani.number.valid = 1;
09810 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09811 }
09812 #endif
09813 tmp->caller.id.name.presentation = i->callingpres;
09814 tmp->caller.id.number.presentation = i->callingpres;
09815 tmp->caller.id.number.plan = i->cid_ton;
09816 tmp->caller.ani2 = i->cid_ani2;
09817 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09818
09819 i->fake_event = 0;
09820
09821 dahdi_confmute(i, 0);
09822 i->muting = 0;
09823
09824 ast_jb_configure(tmp, &global_jbconf);
09825
09826
09827 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09828 dashptr = strrchr(device_name, '-');
09829 if (dashptr) {
09830 *dashptr = '\0';
09831 }
09832 tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE;
09833 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name);
09834
09835 for (v = i->vars ; v ; v = v->next)
09836 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09837
09838 ast_module_ref(ast_module_info->self);
09839
09840 dahdi_ami_channel_event(i, tmp);
09841 if (startpbx) {
09842 #ifdef HAVE_OPENR2
09843 if (i->mfcr2call) {
09844 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09845 }
09846 #endif
09847 if (ast_pbx_start(tmp)) {
09848 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09849 ast_hangup(tmp);
09850 return NULL;
09851 }
09852 }
09853 return tmp;
09854 }
09855
09856
09857 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09858 {
09859 char c;
09860
09861 *str = 0;
09862 for (;;)
09863 {
09864
09865 c = ast_waitfordigit(chan, ms);
09866
09867 if (c < 1)
09868 return c;
09869 *str++ = c;
09870 *str = 0;
09871 if (strchr(term, c))
09872 return 1;
09873 }
09874 }
09875
09876 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09877 {
09878 int j;
09879 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09880 for (;;)
09881 {
09882
09883 j = DAHDI_IOMUX_SIGEVENT;
09884
09885 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09886
09887 if (j & DAHDI_IOMUX_SIGEVENT) break;
09888 }
09889
09890 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09891 return 0;
09892 }
09893
09894
09895
09896
09897
09898
09899
09900
09901
09902
09903 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09904 {
09905 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09906 return analog_dnd(dahdichan->sig_pvt, flag);
09907 }
09908
09909 if (flag == -1) {
09910 return dahdichan->dnd;
09911 }
09912
09913
09914 dahdichan->dnd = flag;
09915 ast_verb(3, "%s DND on channel %d\n",
09916 flag? "Enabled" : "Disabled",
09917 dahdichan->channel);
09918 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09919 "Channel: DAHDI/%d\r\n"
09920 "Status: %s\r\n", dahdichan->channel,
09921 flag? "enabled" : "disabled");
09922
09923 return 0;
09924 }
09925
09926 static int canmatch_featurecode(const char *exten)
09927 {
09928 int extlen = strlen(exten);
09929 const char *pickup_ext;
09930 if (!extlen) {
09931 return 1;
09932 }
09933 pickup_ext = ast_pickup_ext();
09934 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09935 return 1;
09936 }
09937
09938 if (exten[0] == '*' && extlen < 3) {
09939 if (extlen == 1) {
09940 return 1;
09941 }
09942
09943 switch (exten[1]) {
09944 case '6':
09945 case '7':
09946 case '8':
09947 return 1;
09948 }
09949 }
09950 return 0;
09951 }
09952
09953 static void *analog_ss_thread(void *data)
09954 {
09955 struct ast_channel *chan = data;
09956 struct dahdi_pvt *p = chan->tech_pvt;
09957 char exten[AST_MAX_EXTENSION] = "";
09958 char exten2[AST_MAX_EXTENSION] = "";
09959 unsigned char buf[256];
09960 char dtmfcid[300];
09961 char dtmfbuf[300];
09962 struct callerid_state *cs = NULL;
09963 char *name = NULL, *number = NULL;
09964 int distMatches;
09965 int curRingData[3];
09966 int receivedRingT;
09967 int counter1;
09968 int counter;
09969 int samples = 0;
09970 struct ast_smdi_md_message *smdi_msg = NULL;
09971 int flags = 0;
09972 int i;
09973 int timeout;
09974 int getforward = 0;
09975 char *s1, *s2;
09976 int len = 0;
09977 int res;
09978 int idx;
09979
09980 ast_mutex_lock(&ss_thread_lock);
09981 ss_thread_count++;
09982 ast_mutex_unlock(&ss_thread_lock);
09983
09984
09985
09986 if (!p) {
09987 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09988 ast_hangup(chan);
09989 goto quit;
09990 }
09991 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09992 idx = dahdi_get_index(chan, p, 1);
09993 if (idx < 0) {
09994 ast_log(LOG_WARNING, "Huh?\n");
09995 ast_hangup(chan);
09996 goto quit;
09997 }
09998 if (p->dsp)
09999 ast_dsp_digitreset(p->dsp);
10000 switch (p->sig) {
10001 case SIG_FEATD:
10002 case SIG_FEATDMF:
10003 case SIG_FEATDMF_TA:
10004 case SIG_E911:
10005 case SIG_FGC_CAMAMF:
10006 case SIG_FEATB:
10007 case SIG_EMWINK:
10008 case SIG_SF_FEATD:
10009 case SIG_SF_FEATDMF:
10010 case SIG_SF_FEATB:
10011 case SIG_SFWINK:
10012 if (dahdi_wink(p, idx))
10013 goto quit;
10014
10015 case SIG_EM:
10016 case SIG_EM_E1:
10017 case SIG_SF:
10018 case SIG_FGC_CAMA:
10019 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10020 if (p->dsp)
10021 ast_dsp_digitreset(p->dsp);
10022
10023 if (p->dsp) {
10024 if (NEED_MFDETECT(p))
10025 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10026 else
10027 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10028 }
10029 memset(dtmfbuf, 0, sizeof(dtmfbuf));
10030
10031 if (!p->immediate)
10032
10033 res = ast_waitfordigit(chan, 5000);
10034 else
10035 res = 0;
10036 if (res > 0) {
10037
10038 dtmfbuf[0] = res;
10039 switch (p->sig) {
10040 case SIG_FEATD:
10041 case SIG_SF_FEATD:
10042 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10043 if (res > 0)
10044 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10045 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10046 break;
10047 case SIG_FEATDMF_TA:
10048 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10049 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10050 if (dahdi_wink(p, idx)) goto quit;
10051 dtmfbuf[0] = 0;
10052
10053 res = ast_waitfordigit(chan, 5000);
10054 if (res <= 0) break;
10055 dtmfbuf[0] = res;
10056
10057 case SIG_FEATDMF:
10058 case SIG_E911:
10059 case SIG_FGC_CAMAMF:
10060 case SIG_SF_FEATDMF:
10061 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10062
10063 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10064 {
10065 if (dahdi_wink(p, idx)) goto quit;
10066 dtmfbuf[0] = 0;
10067
10068 res = ast_waitfordigit(chan, 5000);
10069 if (res <= 0) break;
10070 dtmfbuf[0] = res;
10071 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10072 }
10073 if (res > 0) {
10074
10075 if (p->sig == SIG_E911)
10076 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10077 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10078 }
10079 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10080 break;
10081 case SIG_FEATB:
10082 case SIG_SF_FEATB:
10083 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10084 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10085 break;
10086 case SIG_EMWINK:
10087
10088
10089
10090
10091 if (res == '*') {
10092 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10093 if (res > 0)
10094 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10095 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10096 break;
10097 }
10098 default:
10099
10100 len = 1;
10101 dtmfbuf[len] = '\0';
10102 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10103 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10104 timeout = matchdigittimeout;
10105 } else {
10106 timeout = gendigittimeout;
10107 }
10108 res = ast_waitfordigit(chan, timeout);
10109 if (res < 0) {
10110 ast_debug(1, "waitfordigit returned < 0...\n");
10111 ast_hangup(chan);
10112 goto quit;
10113 } else if (res) {
10114 dtmfbuf[len++] = res;
10115 dtmfbuf[len] = '\0';
10116 } else {
10117 break;
10118 }
10119 }
10120 break;
10121 }
10122 }
10123 if (res == -1) {
10124 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10125 ast_hangup(chan);
10126 goto quit;
10127 } else if (res < 0) {
10128 ast_debug(1, "Got hung up before digits finished\n");
10129 ast_hangup(chan);
10130 goto quit;
10131 }
10132
10133 if (p->sig == SIG_FGC_CAMA) {
10134 char anibuf[100];
10135
10136 if (ast_safe_sleep(chan,1000) == -1) {
10137 ast_hangup(chan);
10138 goto quit;
10139 }
10140 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10141 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10142 res = my_getsigstr(chan, anibuf, "#", 10000);
10143 if ((res > 0) && (strlen(anibuf) > 2)) {
10144 if (anibuf[strlen(anibuf) - 1] == '#')
10145 anibuf[strlen(anibuf) - 1] = 0;
10146 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10147 }
10148 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10149 }
10150
10151 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10152 if (ast_strlen_zero(exten))
10153 ast_copy_string(exten, "s", sizeof(exten));
10154 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10155
10156 if (exten[0] == '*') {
10157 char *stringp=NULL;
10158 ast_copy_string(exten2, exten, sizeof(exten2));
10159
10160 stringp=exten2 +1;
10161 s1 = strsep(&stringp, "*");
10162 s2 = strsep(&stringp, "*");
10163 if (s2) {
10164 if (!ast_strlen_zero(p->cid_num))
10165 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10166 else
10167 ast_set_callerid(chan, s1, NULL, s1);
10168 ast_copy_string(exten, s2, sizeof(exten));
10169 } else
10170 ast_copy_string(exten, s1, sizeof(exten));
10171 } else if (p->sig == SIG_FEATD)
10172 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10173 }
10174 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10175 if (exten[0] == '*') {
10176 char *stringp=NULL;
10177 ast_copy_string(exten2, exten, sizeof(exten2));
10178
10179 stringp=exten2 +1;
10180 s1 = strsep(&stringp, "#");
10181 s2 = strsep(&stringp, "#");
10182 if (s2) {
10183 if (!ast_strlen_zero(p->cid_num))
10184 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10185 else
10186 if (*(s1 + 2))
10187 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10188 ast_copy_string(exten, s2 + 1, sizeof(exten));
10189 } else
10190 ast_copy_string(exten, s1 + 2, sizeof(exten));
10191 } else
10192 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10193 }
10194 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10195 if (exten[0] == '*') {
10196 char *stringp=NULL;
10197 ast_copy_string(exten2, exten, sizeof(exten2));
10198
10199 stringp=exten2 +1;
10200 s1 = strsep(&stringp, "#");
10201 s2 = strsep(&stringp, "#");
10202 if (s2 && (*(s2 + 1) == '0')) {
10203 if (*(s2 + 2))
10204 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10205 }
10206 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10207 else ast_copy_string(exten, "911", sizeof(exten));
10208 } else
10209 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10210 }
10211 if (p->sig == SIG_FEATB) {
10212 if (exten[0] == '*') {
10213 char *stringp=NULL;
10214 ast_copy_string(exten2, exten, sizeof(exten2));
10215
10216 stringp=exten2 +1;
10217 s1 = strsep(&stringp, "#");
10218 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10219 } else
10220 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10221 }
10222 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10223 dahdi_wink(p, idx);
10224
10225
10226
10227 if (ast_safe_sleep(chan, 100)) {
10228 ast_hangup(chan);
10229 goto quit;
10230 }
10231 }
10232 dahdi_enable_ec(p);
10233 if (NEED_MFDETECT(p)) {
10234 if (p->dsp) {
10235 if (!p->hardwaredtmf)
10236 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10237 else {
10238 ast_dsp_free(p->dsp);
10239 p->dsp = NULL;
10240 }
10241 }
10242 }
10243
10244 if (ast_exists_extension(chan, chan->context, exten, 1,
10245 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10246 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10247 if (p->dsp) ast_dsp_digitreset(p->dsp);
10248 res = ast_pbx_run(chan);
10249 if (res) {
10250 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10251 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10252 }
10253 goto quit;
10254 } else {
10255 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10256 sleep(2);
10257 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10258 if (res < 0)
10259 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10260 else
10261 sleep(1);
10262 res = ast_streamfile(chan, "ss-noservice", chan->language);
10263 if (res >= 0)
10264 ast_waitstream(chan, "");
10265 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10266 ast_hangup(chan);
10267 goto quit;
10268 }
10269 break;
10270 case SIG_FXOLS:
10271 case SIG_FXOGS:
10272 case SIG_FXOKS:
10273
10274 timeout = firstdigittimeout;
10275
10276
10277 if (p->subs[SUB_THREEWAY].owner)
10278 timeout = 999999;
10279 while (len < AST_MAX_EXTENSION-1) {
10280
10281
10282 if (p->immediate)
10283 res = 's';
10284 else
10285 res = ast_waitfordigit(chan, timeout);
10286 timeout = 0;
10287 if (res < 0) {
10288 ast_debug(1, "waitfordigit returned < 0...\n");
10289 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10290 ast_hangup(chan);
10291 goto quit;
10292 } else if (res) {
10293 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10294 exten[len++]=res;
10295 exten[len] = '\0';
10296 }
10297 if (!ast_ignore_pattern(chan->context, exten))
10298 tone_zone_play_tone(p->subs[idx].dfd, -1);
10299 else
10300 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10301 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10302 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10303 if (getforward) {
10304
10305 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10306 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10307 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10308 if (res)
10309 break;
10310 usleep(500000);
10311 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10312 sleep(1);
10313 memset(exten, 0, sizeof(exten));
10314 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10315 len = 0;
10316 getforward = 0;
10317 } else {
10318 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10319 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10320 if (!ast_strlen_zero(p->cid_num)) {
10321 if (!p->hidecallerid)
10322 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10323 else
10324 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10325 }
10326 if (!ast_strlen_zero(p->cid_name)) {
10327 if (!p->hidecallerid)
10328 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10329 }
10330 ast_setstate(chan, AST_STATE_RING);
10331 dahdi_enable_ec(p);
10332 res = ast_pbx_run(chan);
10333 if (res) {
10334 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10335 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10336 }
10337 goto quit;
10338 }
10339 } else {
10340
10341
10342 timeout = matchdigittimeout;
10343 }
10344 } else if (res == 0) {
10345 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10346 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10347 dahdi_wait_event(p->subs[idx].dfd);
10348 ast_hangup(chan);
10349 goto quit;
10350 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10351 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10352
10353 p->callwaiting = 0;
10354 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10355 if (res) {
10356 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10357 chan->name, strerror(errno));
10358 }
10359 len = 0;
10360 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10361 memset(exten, 0, sizeof(exten));
10362 timeout = firstdigittimeout;
10363
10364 } else if (!strcmp(exten,ast_pickup_ext())) {
10365
10366
10367
10368
10369 if (idx == SUB_REAL) {
10370
10371 if (p->subs[SUB_THREEWAY].owner) {
10372
10373
10374 alloc_sub(p, SUB_CALLWAIT);
10375 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10376 unalloc_sub(p, SUB_THREEWAY);
10377 }
10378 dahdi_enable_ec(p);
10379 if (ast_pickup_call(chan)) {
10380 ast_debug(1, "No call pickup possible...\n");
10381 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10382 dahdi_wait_event(p->subs[idx].dfd);
10383 }
10384 ast_hangup(chan);
10385 goto quit;
10386 } else {
10387 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10388 ast_hangup(chan);
10389 goto quit;
10390 }
10391
10392 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10393 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10394
10395 p->hidecallerid = 1;
10396 ast_party_number_free(&chan->caller.id.number);
10397 ast_party_number_init(&chan->caller.id.number);
10398 ast_party_name_free(&chan->caller.id.name);
10399 ast_party_name_init(&chan->caller.id.name);
10400 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10401 if (res) {
10402 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10403 chan->name, strerror(errno));
10404 }
10405 len = 0;
10406 memset(exten, 0, sizeof(exten));
10407 timeout = firstdigittimeout;
10408 } else if (p->callreturn && !strcmp(exten, "*69")) {
10409 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10410 break;
10411 } else if (!strcmp(exten, "*78")) {
10412 dahdi_dnd(p, 1);
10413
10414 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10415 getforward = 0;
10416 memset(exten, 0, sizeof(exten));
10417 len = 0;
10418 } else if (!strcmp(exten, "*79")) {
10419 dahdi_dnd(p, 0);
10420
10421 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10422 getforward = 0;
10423 memset(exten, 0, sizeof(exten));
10424 len = 0;
10425 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10426 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10427 getforward = 1;
10428 memset(exten, 0, sizeof(exten));
10429 len = 0;
10430 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10431 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10432 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10433 memset(p->call_forward, 0, sizeof(p->call_forward));
10434 getforward = 0;
10435 memset(exten, 0, sizeof(exten));
10436 len = 0;
10437 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10438 p->subs[SUB_THREEWAY].owner &&
10439 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10440
10441
10442 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10443 chan, exten, chan->context, 0, NULL);
10444 ast_verb(3, "Parking call to '%s'\n", chan->name);
10445 break;
10446 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10447 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10448
10449 p->hidecallerid = 0;
10450 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10451 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10452 if (res) {
10453 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10454 chan->name, strerror(errno));
10455 }
10456 len = 0;
10457 memset(exten, 0, sizeof(exten));
10458 timeout = firstdigittimeout;
10459 } else if (!strcmp(exten, "*0")) {
10460 struct ast_channel *nbridge =
10461 p->subs[SUB_THREEWAY].owner;
10462 struct dahdi_pvt *pbridge = NULL;
10463
10464 if (nbridge && ast_bridged_channel(nbridge))
10465 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10466 if (nbridge && pbridge &&
10467 (nbridge->tech == &dahdi_tech) &&
10468 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10469 ISTRUNK(pbridge)) {
10470 int func = DAHDI_FLASH;
10471
10472 p->dop.dialstr[0] = '\0';
10473
10474 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10475 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10476 nbridge->name, strerror(errno));
10477 }
10478 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10479 unalloc_sub(p, SUB_THREEWAY);
10480 p->owner = p->subs[SUB_REAL].owner;
10481 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10482 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10483 ast_hangup(chan);
10484 goto quit;
10485 } else {
10486 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10487 dahdi_wait_event(p->subs[idx].dfd);
10488 tone_zone_play_tone(p->subs[idx].dfd, -1);
10489 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10490 unalloc_sub(p, SUB_THREEWAY);
10491 p->owner = p->subs[SUB_REAL].owner;
10492 ast_hangup(chan);
10493 goto quit;
10494 }
10495 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10496 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10497 && !canmatch_featurecode(exten)) {
10498 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10499 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10500 chan->context);
10501 break;
10502 }
10503 if (!timeout)
10504 timeout = gendigittimeout;
10505 if (len && !ast_ignore_pattern(chan->context, exten))
10506 tone_zone_play_tone(p->subs[idx].dfd, -1);
10507 }
10508 break;
10509 case SIG_FXSLS:
10510 case SIG_FXSGS:
10511 case SIG_FXSKS:
10512
10513 if (p->use_smdi && p->smdi_iface) {
10514 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10515
10516 if (smdi_msg != NULL) {
10517 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10518
10519 if (smdi_msg->type == 'B')
10520 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10521 else if (smdi_msg->type == 'N')
10522 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10523
10524 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10525 } else {
10526 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10527 }
10528 }
10529
10530 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10531 number = smdi_msg->calling_st;
10532
10533
10534
10535
10536 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10537 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10538
10539 if (p->cid_signalling == CID_SIG_DTMF) {
10540 int k = 0;
10541 int off_ms;
10542 struct timeval start = ast_tvnow();
10543 int ms;
10544 cs = NULL;
10545 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10546 dahdi_setlinear(p->subs[idx].dfd, 0);
10547
10548
10549
10550
10551
10552
10553 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10554 off_ms = 4000;
10555 for (;;) {
10556 struct ast_frame *f;
10557
10558 ms = ast_remaining_ms(start, off_ms);
10559 res = ast_waitfor(chan, ms);
10560 if (res <= 0) {
10561
10562
10563
10564
10565
10566 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10567 "Exiting simple switch\n");
10568 ast_hangup(chan);
10569 goto quit;
10570 }
10571 f = ast_read(chan);
10572 if (!f)
10573 break;
10574 if (f->frametype == AST_FRAME_DTMF) {
10575 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10576 dtmfbuf[k++] = f->subclass.integer;
10577 }
10578 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10579 start = ast_tvnow();
10580 }
10581 ast_frfree(f);
10582 if (chan->_state == AST_STATE_RING ||
10583 chan->_state == AST_STATE_RINGING)
10584 break;
10585 }
10586 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10587 dtmfbuf[k] = '\0';
10588 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10589
10590 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10591 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10592 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10593
10594 if (!ast_strlen_zero(dtmfcid))
10595 number = dtmfcid;
10596 else
10597 number = NULL;
10598
10599 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10600 cs = callerid_new(p->cid_signalling);
10601 if (cs) {
10602 int off_ms;
10603 struct timeval start;
10604 int ms;
10605 samples = 0;
10606 #if 1
10607 bump_gains(p);
10608 #endif
10609
10610 dahdi_setlinear(p->subs[idx].dfd, 0);
10611
10612
10613 for (;;) {
10614 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10615 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10616 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10617 callerid_free(cs);
10618 ast_hangup(chan);
10619 goto quit;
10620 }
10621 if (i & DAHDI_IOMUX_SIGEVENT) {
10622 res = dahdi_get_event(p->subs[idx].dfd);
10623 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10624 if (res == DAHDI_EVENT_NOALARM) {
10625 p->inalarm = 0;
10626 }
10627
10628 if (p->cid_signalling == CID_SIG_V23_JP) {
10629 if (res == DAHDI_EVENT_RINGBEGIN) {
10630 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10631 usleep(1);
10632 }
10633 } else {
10634 res = 0;
10635 break;
10636 }
10637 } else if (i & DAHDI_IOMUX_READ) {
10638 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10639 if (res < 0) {
10640 if (errno != ELAST) {
10641 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10642 callerid_free(cs);
10643 ast_hangup(chan);
10644 goto quit;
10645 }
10646 break;
10647 }
10648 samples += res;
10649
10650 if (p->cid_signalling == CID_SIG_V23_JP) {
10651 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10652 } else {
10653 res = callerid_feed(cs, buf, res, AST_LAW(p));
10654 }
10655 if (res < 0) {
10656
10657
10658
10659
10660 ast_log(LOG_WARNING,
10661 "Failed to decode CallerID on channel '%s'\n",
10662 chan->name);
10663 break;
10664 } else if (res)
10665 break;
10666 else if (samples > (8000 * 10))
10667 break;
10668 }
10669 }
10670 if (res == 1) {
10671 callerid_get(cs, &name, &number, &flags);
10672 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10673 }
10674
10675 if (p->cid_signalling == CID_SIG_V23_JP) {
10676 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10677 usleep(1);
10678 }
10679
10680
10681 start = ast_tvnow();
10682 off_ms = 4000;
10683 for (;;) {
10684 struct ast_frame *f;
10685
10686 ms = ast_remaining_ms(start, off_ms);
10687 res = ast_waitfor(chan, ms);
10688 if (res <= 0) {
10689 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10690 "Exiting simple switch\n");
10691 ast_hangup(chan);
10692 goto quit;
10693 }
10694 if (!(f = ast_read(chan))) {
10695 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10696 ast_hangup(chan);
10697 goto quit;
10698 }
10699 ast_frfree(f);
10700 if (chan->_state == AST_STATE_RING ||
10701 chan->_state == AST_STATE_RINGING)
10702 break;
10703 }
10704
10705
10706
10707 if (p->usedistinctiveringdetection) {
10708 len = 0;
10709 distMatches = 0;
10710
10711 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10712 curRingData[receivedRingT] = 0;
10713 receivedRingT = 0;
10714 counter = 0;
10715 counter1 = 0;
10716
10717 if (strcmp(p->context,p->defcontext) != 0) {
10718 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10719 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10720 }
10721
10722 for (;;) {
10723 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10724 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10725 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10726 callerid_free(cs);
10727 ast_hangup(chan);
10728 goto quit;
10729 }
10730 if (i & DAHDI_IOMUX_SIGEVENT) {
10731 res = dahdi_get_event(p->subs[idx].dfd);
10732 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10733 if (res == DAHDI_EVENT_NOALARM) {
10734 p->inalarm = 0;
10735 }
10736 res = 0;
10737
10738
10739 curRingData[receivedRingT] = p->ringt;
10740
10741 if (p->ringt < p->ringt_base/2)
10742 break;
10743
10744
10745 if (++receivedRingT == ARRAY_LEN(curRingData))
10746 break;
10747 } else if (i & DAHDI_IOMUX_READ) {
10748 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10749 if (res < 0) {
10750 if (errno != ELAST) {
10751 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10752 callerid_free(cs);
10753 ast_hangup(chan);
10754 goto quit;
10755 }
10756 break;
10757 }
10758 if (p->ringt > 0) {
10759 if (!(--p->ringt)) {
10760 res = -1;
10761 break;
10762 }
10763 }
10764 }
10765 }
10766
10767 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10768 for (counter = 0; counter < 3; counter++) {
10769
10770
10771 distMatches = 0;
10772 for (counter1 = 0; counter1 < 3; counter1++) {
10773 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10774 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10775 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10776 curRingData[counter1]);
10777 distMatches++;
10778 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10779 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10780 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10781 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10782 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10783 distMatches++;
10784 }
10785 }
10786
10787 if (distMatches == 3) {
10788
10789 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10790 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10791 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10792 break;
10793 }
10794 }
10795 }
10796
10797 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10798 #if 1
10799 restore_gains(p);
10800 #endif
10801 } else
10802 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10803 } else {
10804 ast_log(LOG_WARNING, "Channel %s in prering "
10805 "state, but I have nothing to do. "
10806 "Terminating simple switch, should be "
10807 "restarted by the actual ring.\n",
10808 chan->name);
10809 ast_hangup(chan);
10810 goto quit;
10811 }
10812 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10813 if (p->cid_signalling == CID_SIG_DTMF) {
10814 int k = 0;
10815 int off_ms;
10816 struct timeval start;
10817 int ms;
10818 cs = NULL;
10819 dahdi_setlinear(p->subs[idx].dfd, 0);
10820 off_ms = 2000;
10821 start = ast_tvnow();
10822 for (;;) {
10823 struct ast_frame *f;
10824
10825 ms = ast_remaining_ms(start, off_ms);
10826 res = ast_waitfor(chan, ms);
10827 if (res <= 0) {
10828 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10829 "Exiting simple switch\n");
10830 ast_hangup(chan);
10831 goto quit;
10832 }
10833 f = ast_read(chan);
10834 if (!f) {
10835
10836 ast_hangup(chan);
10837 goto quit;
10838 }
10839 if (f->frametype == AST_FRAME_DTMF) {
10840 dtmfbuf[k++] = f->subclass.integer;
10841 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10842 start = ast_tvnow();
10843 }
10844 ast_frfree(f);
10845
10846 if (p->ringt_base == p->ringt)
10847 break;
10848 }
10849 dtmfbuf[k] = '\0';
10850 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10851
10852 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10853 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10854 dtmfcid, flags);
10855
10856 if (!ast_strlen_zero(dtmfcid))
10857 number = dtmfcid;
10858 else
10859 number = NULL;
10860
10861 } else {
10862
10863 cs = callerid_new(p->cid_signalling);
10864 if (cs) {
10865 #if 1
10866 bump_gains(p);
10867 #endif
10868 samples = 0;
10869 len = 0;
10870 distMatches = 0;
10871
10872 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10873 curRingData[receivedRingT] = 0;
10874 receivedRingT = 0;
10875 counter = 0;
10876 counter1 = 0;
10877
10878 if (strcmp(p->context,p->defcontext) != 0) {
10879 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10880 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10881 }
10882
10883
10884 dahdi_setlinear(p->subs[idx].dfd, 0);
10885 for (;;) {
10886 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10887 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10888 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10889 callerid_free(cs);
10890 ast_hangup(chan);
10891 goto quit;
10892 }
10893 if (i & DAHDI_IOMUX_SIGEVENT) {
10894 res = dahdi_get_event(p->subs[idx].dfd);
10895 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10896 if (res == DAHDI_EVENT_NOALARM) {
10897 p->inalarm = 0;
10898 }
10899
10900 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10901 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10902 p->polarity = POLARITY_IDLE;
10903 callerid_free(cs);
10904 ast_hangup(chan);
10905 goto quit;
10906 }
10907 res = 0;
10908
10909
10910 curRingData[receivedRingT] = p->ringt;
10911
10912 if (p->ringt < p->ringt_base/2)
10913 break;
10914
10915
10916 if (++receivedRingT == ARRAY_LEN(curRingData))
10917 break;
10918 } else if (i & DAHDI_IOMUX_READ) {
10919 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10920 if (res < 0) {
10921 if (errno != ELAST) {
10922 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10923 callerid_free(cs);
10924 ast_hangup(chan);
10925 goto quit;
10926 }
10927 break;
10928 }
10929 if (p->ringt > 0) {
10930 if (!(--p->ringt)) {
10931 res = -1;
10932 break;
10933 }
10934 }
10935 samples += res;
10936 res = callerid_feed(cs, buf, res, AST_LAW(p));
10937 if (res < 0) {
10938
10939
10940
10941
10942 ast_log(LOG_WARNING,
10943 "Failed to decode CallerID on channel '%s'\n",
10944 chan->name);
10945 break;
10946 } else if (res)
10947 break;
10948 else if (samples > (8000 * 10))
10949 break;
10950 }
10951 }
10952 if (res == 1) {
10953 callerid_get(cs, &name, &number, &flags);
10954 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10955 }
10956 if (distinctiveringaftercid == 1) {
10957
10958 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10959 curRingData[receivedRingT] = 0;
10960 }
10961 receivedRingT = 0;
10962 ast_verb(3, "Detecting post-CID distinctive ring\n");
10963 for (;;) {
10964 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10965 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10966 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10967 callerid_free(cs);
10968 ast_hangup(chan);
10969 goto quit;
10970 }
10971 if (i & DAHDI_IOMUX_SIGEVENT) {
10972 res = dahdi_get_event(p->subs[idx].dfd);
10973 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10974 if (res == DAHDI_EVENT_NOALARM) {
10975 p->inalarm = 0;
10976 }
10977 res = 0;
10978
10979
10980 curRingData[receivedRingT] = p->ringt;
10981
10982 if (p->ringt < p->ringt_base/2)
10983 break;
10984
10985
10986 if (++receivedRingT == ARRAY_LEN(curRingData))
10987 break;
10988 } else if (i & DAHDI_IOMUX_READ) {
10989 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10990 if (res < 0) {
10991 if (errno != ELAST) {
10992 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10993 callerid_free(cs);
10994 ast_hangup(chan);
10995 goto quit;
10996 }
10997 break;
10998 }
10999 if (p->ringt > 0) {
11000 if (!(--p->ringt)) {
11001 res = -1;
11002 break;
11003 }
11004 }
11005 }
11006 }
11007 }
11008 if (p->usedistinctiveringdetection) {
11009
11010 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
11011
11012 for (counter = 0; counter < 3; counter++) {
11013
11014
11015
11016 ast_verb(3, "Checking %d,%d,%d\n",
11017 p->drings.ringnum[counter].ring[0],
11018 p->drings.ringnum[counter].ring[1],
11019 p->drings.ringnum[counter].ring[2]);
11020 distMatches = 0;
11021 for (counter1 = 0; counter1 < 3; counter1++) {
11022 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
11023 if (p->drings.ringnum[counter].ring[counter1] == -1) {
11024 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
11025 curRingData[counter1]);
11026 distMatches++;
11027 }
11028 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
11029 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
11030 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
11031 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
11032 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
11033 distMatches++;
11034 }
11035 }
11036 if (distMatches == 3) {
11037
11038 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
11039 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
11040 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
11041 break;
11042 }
11043 }
11044 }
11045
11046 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
11047 #if 1
11048 restore_gains(p);
11049 #endif
11050 if (res < 0) {
11051 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
11052 }
11053 } else
11054 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11055 }
11056 } else
11057 cs = NULL;
11058
11059 if (number)
11060 ast_shrink_phone_number(number);
11061 ast_set_callerid(chan, number, name, number);
11062
11063 if (smdi_msg)
11064 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11065
11066 if (cs)
11067 callerid_free(cs);
11068
11069 my_handle_notify_message(chan, p, flags, -1);
11070
11071 ast_setstate(chan, AST_STATE_RING);
11072 chan->rings = 1;
11073 p->ringt = p->ringt_base;
11074 res = ast_pbx_run(chan);
11075 if (res) {
11076 ast_hangup(chan);
11077 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11078 }
11079 goto quit;
11080 default:
11081 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11082 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11083 if (res < 0)
11084 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11085 }
11086 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11087 if (res < 0)
11088 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11089 ast_hangup(chan);
11090 quit:
11091 ast_mutex_lock(&ss_thread_lock);
11092 ss_thread_count--;
11093 ast_cond_signal(&ss_thread_complete);
11094 ast_mutex_unlock(&ss_thread_lock);
11095 return NULL;
11096 }
11097
11098 struct mwi_thread_data {
11099 struct dahdi_pvt *pvt;
11100 unsigned char buf[READ_SIZE];
11101 size_t len;
11102 };
11103
11104 static int calc_energy(const unsigned char *buf, int len, format_t law)
11105 {
11106 int x;
11107 int sum = 0;
11108
11109 if (!len)
11110 return 0;
11111
11112 for (x = 0; x < len; x++)
11113 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11114
11115 return sum / len;
11116 }
11117
11118 static void *mwi_thread(void *data)
11119 {
11120 struct mwi_thread_data *mtd = data;
11121 struct callerid_state *cs;
11122 pthread_t threadid;
11123 int samples = 0;
11124 char *name, *number;
11125 int flags;
11126 int i, res;
11127 unsigned int spill_done = 0;
11128 int spill_result = -1;
11129
11130 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11131 goto quit_no_clean;
11132 }
11133
11134 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11135
11136 bump_gains(mtd->pvt);
11137
11138 for (;;) {
11139 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11140 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11141 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11142 goto quit;
11143 }
11144
11145 if (i & DAHDI_IOMUX_SIGEVENT) {
11146 struct ast_channel *chan;
11147
11148
11149
11150
11151 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11152
11153 switch (res) {
11154 case DAHDI_EVENT_NEONMWI_ACTIVE:
11155 case DAHDI_EVENT_NEONMWI_INACTIVE:
11156 case DAHDI_EVENT_NONE:
11157 case DAHDI_EVENT_BITSCHANGED:
11158 break;
11159 case DAHDI_EVENT_NOALARM:
11160 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11161 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11162
11163 analog_p->inalarm = 0;
11164 }
11165 mtd->pvt->inalarm = 0;
11166 handle_clear_alarms(mtd->pvt);
11167 break;
11168 case DAHDI_EVENT_ALARM:
11169 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11170 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11171
11172 analog_p->inalarm = 1;
11173 }
11174 mtd->pvt->inalarm = 1;
11175 res = get_alarms(mtd->pvt);
11176 handle_alarms(mtd->pvt, res);
11177 break;
11178 default:
11179 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11180 callerid_free(cs);
11181
11182 restore_gains(mtd->pvt);
11183 mtd->pvt->ringt = mtd->pvt->ringt_base;
11184
11185 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11186 int result;
11187
11188 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11189 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11190 } else {
11191 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11192 }
11193 if (result) {
11194 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11195 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11196 if (res < 0)
11197 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11198 ast_hangup(chan);
11199 }
11200 } else {
11201 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11202 }
11203 goto quit_no_clean;
11204 }
11205 } else if (i & DAHDI_IOMUX_READ) {
11206 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11207 if (errno != ELAST) {
11208 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11209 goto quit;
11210 }
11211 break;
11212 }
11213 samples += res;
11214 if (!spill_done) {
11215 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11216
11217
11218
11219
11220 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11221 break;
11222 } else if (spill_result) {
11223 spill_done = 1;
11224 }
11225 } else {
11226
11227
11228
11229 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11230 break;
11231 }
11232 if (samples > (8000 * 4))
11233 break;
11234 }
11235 }
11236
11237 if (spill_result == 1) {
11238 callerid_get(cs, &name, &number, &flags);
11239 if (flags & CID_MSGWAITING) {
11240 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11241 notify_message(mtd->pvt->mailbox, 1);
11242 } else if (flags & CID_NOMSGWAITING) {
11243 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11244 notify_message(mtd->pvt->mailbox, 0);
11245 } else {
11246 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11247 }
11248 }
11249
11250
11251 quit:
11252 callerid_free(cs);
11253
11254 restore_gains(mtd->pvt);
11255
11256 quit_no_clean:
11257 mtd->pvt->mwimonitoractive = 0;
11258 ast_free(mtd);
11259
11260 return NULL;
11261 }
11262
11263
11264
11265
11266
11267
11268
11269
11270 static int mwi_send_init(struct dahdi_pvt * pvt)
11271 {
11272 int x;
11273
11274 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11275
11276 if (pvt->mwisend_rpas) {
11277 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11278 pvt->mwisendactive = 1;
11279 } else if (pvt->mwisend_fsk) {
11280 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11281 pvt->mwisendactive = 1;
11282 } else {
11283 pvt->mwisendactive = 0;
11284 return 0;
11285 }
11286 #else
11287 if (mwisend_rpas) {
11288 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11289 } else {
11290 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11291 }
11292 pvt->mwisendactive = 1;
11293 #endif
11294
11295 if (pvt->cidspill) {
11296 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11297 ast_free(pvt->cidspill);
11298 pvt->cidspill = NULL;
11299 pvt->cidpos = 0;
11300 pvt->cidlen = 0;
11301 }
11302 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11303 if (!pvt->cidspill) {
11304 pvt->mwisendactive = 0;
11305 return -1;
11306 }
11307 x = DAHDI_FLUSH_BOTH;
11308 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11309 x = 3000;
11310 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11311 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11312 if (pvt->mwisend_fsk) {
11313 #endif
11314 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11315 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11316 pvt->cidpos = 0;
11317 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11318 }
11319 #endif
11320 return 0;
11321 }
11322
11323 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11324 {
11325 struct timeval now;
11326 int res;
11327
11328
11329
11330
11331 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11332 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11333 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11334
11335 switch ( pvt->mwisend_data.mwisend_current) {
11336 case MWI_SEND_SA:
11337
11338 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11339 if (res) {
11340 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11341 goto quit;
11342 }
11343 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11344 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11345 break;
11346 case MWI_SEND_SA_WAIT:
11347 break;
11348 case MWI_SEND_PAUSE:
11349 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11350 if (pvt->mwisend_fsk) {
11351 #endif
11352 gettimeofday(&now, NULL);
11353 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11354 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11355 }
11356 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11357 } else {
11358 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11359 }
11360 #endif
11361 break;
11362 case MWI_SEND_SPILL:
11363
11364 if(0 < num_read) {
11365 if (num_read > pvt->cidlen - pvt->cidpos)
11366 num_read = pvt->cidlen - pvt->cidpos;
11367 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11368 if (res > 0) {
11369 pvt->cidpos += res;
11370 if (pvt->cidpos >= pvt->cidlen) {
11371 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11372 }
11373 } else {
11374 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11375 goto quit;
11376 }
11377 }
11378 break;
11379 case MWI_SEND_CLEANUP:
11380
11381 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11382 break;
11383 default:
11384
11385 goto quit;
11386 }
11387 }
11388
11389 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11390 if (pvt->cidspill) {
11391 ast_free(pvt->cidspill);
11392 pvt->cidspill = NULL;
11393 pvt->cidpos = 0;
11394 pvt->cidlen = 0;
11395 }
11396 pvt->mwisendactive = 0;
11397 }
11398 return 0;
11399 quit:
11400 if (pvt->cidspill) {
11401 ast_free(pvt->cidspill);
11402 pvt->cidspill = NULL;
11403 pvt->cidpos = 0;
11404 pvt->cidlen = 0;
11405 }
11406 pvt->mwisendactive = 0;
11407 return -1;
11408 }
11409
11410 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11411 {
11412 int handled = 0;
11413
11414 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11415 switch (event) {
11416 case DAHDI_EVENT_RINGEROFF:
11417 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11418 handled = 1;
11419
11420 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11421 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11422 ast_free(pvt->cidspill);
11423 pvt->cidspill = NULL;
11424 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11425 pvt->mwisendactive = 0;
11426 } else {
11427 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11428 gettimeofday(&pvt->mwisend_data.pause, NULL);
11429 }
11430 }
11431 break;
11432
11433 case DAHDI_EVENT_RINGOFFHOOK:
11434 if (pvt->cidspill) {
11435 ast_free(pvt->cidspill);
11436 pvt->cidspill = NULL;
11437 pvt->cidpos = 0;
11438 pvt->cidlen = 0;
11439 }
11440 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11441 pvt->mwisendactive = 0;
11442 break;
11443 case DAHDI_EVENT_RINGERON:
11444 case DAHDI_EVENT_HOOKCOMPLETE:
11445 break;
11446 default:
11447 break;
11448 }
11449 }
11450 return handled;
11451 }
11452
11453
11454 static int dahdi_destroy_channel_bynum(int channel)
11455 {
11456 struct dahdi_pvt *cur;
11457
11458 ast_mutex_lock(&iflock);
11459 for (cur = iflist; cur; cur = cur->next) {
11460 if (cur->channel == channel) {
11461 int x = DAHDI_FLASH;
11462
11463
11464 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11465
11466 destroy_channel(cur, 1);
11467 ast_mutex_unlock(&iflock);
11468 ast_module_unref(ast_module_info->self);
11469 return RESULT_SUCCESS;
11470 }
11471 }
11472 ast_mutex_unlock(&iflock);
11473 return RESULT_FAILURE;
11474 }
11475
11476 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11477 {
11478 int res;
11479 pthread_t threadid;
11480 struct ast_channel *chan;
11481
11482
11483
11484 switch (event) {
11485 case DAHDI_EVENT_NONE:
11486 case DAHDI_EVENT_BITSCHANGED:
11487 break;
11488 case DAHDI_EVENT_WINKFLASH:
11489 case DAHDI_EVENT_RINGOFFHOOK:
11490 if (i->inalarm) break;
11491 if (i->radio) break;
11492
11493 switch (i->sig) {
11494 case SIG_FXOLS:
11495 case SIG_FXOGS:
11496 case SIG_FXOKS:
11497 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11498 if (res && (errno == EBUSY))
11499 break;
11500
11501
11502 ast_free(i->cidspill);
11503 i->cidspill = NULL;
11504 restore_conference(i);
11505
11506 if (i->immediate) {
11507 dahdi_enable_ec(i);
11508
11509 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11510 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11511 if (!chan) {
11512 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11513 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11514 if (res < 0)
11515 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11516 }
11517 } else {
11518
11519 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11520 if (chan) {
11521 if (has_voicemail(i))
11522 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11523 else
11524 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11525 if (res < 0)
11526 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11527 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11528 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11529 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11530 if (res < 0)
11531 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11532 ast_hangup(chan);
11533 }
11534 } else
11535 ast_log(LOG_WARNING, "Unable to create channel\n");
11536 }
11537 break;
11538 case SIG_FXSLS:
11539 case SIG_FXSGS:
11540 case SIG_FXSKS:
11541 i->ringt = i->ringt_base;
11542
11543 case SIG_EMWINK:
11544 case SIG_FEATD:
11545 case SIG_FEATDMF:
11546 case SIG_FEATDMF_TA:
11547 case SIG_E911:
11548 case SIG_FGC_CAMA:
11549 case SIG_FGC_CAMAMF:
11550 case SIG_FEATB:
11551 case SIG_EM:
11552 case SIG_EM_E1:
11553 case SIG_SFWINK:
11554 case SIG_SF_FEATD:
11555 case SIG_SF_FEATDMF:
11556 case SIG_SF_FEATB:
11557 case SIG_SF:
11558
11559 if (i->cid_start == CID_START_POLARITY_IN) {
11560 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11561 } else {
11562 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11563 }
11564
11565 if (!chan) {
11566 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11567 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11568 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11569 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11570 if (res < 0) {
11571 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11572 }
11573 ast_hangup(chan);
11574 }
11575 break;
11576 default:
11577 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11578 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11579 if (res < 0)
11580 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11581 return NULL;
11582 }
11583 break;
11584 case DAHDI_EVENT_NOALARM:
11585 switch (i->sig) {
11586 #if defined(HAVE_PRI)
11587 case SIG_PRI_LIB_HANDLE_CASES:
11588 ast_mutex_lock(&i->lock);
11589 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11590 ast_mutex_unlock(&i->lock);
11591 break;
11592 #endif
11593 #if defined(HAVE_SS7)
11594 case SIG_SS7:
11595 sig_ss7_set_alarm(i->sig_pvt, 0);
11596 break;
11597 #endif
11598 default:
11599 i->inalarm = 0;
11600 break;
11601 }
11602 handle_clear_alarms(i);
11603 break;
11604 case DAHDI_EVENT_ALARM:
11605 switch (i->sig) {
11606 #if defined(HAVE_PRI)
11607 case SIG_PRI_LIB_HANDLE_CASES:
11608 ast_mutex_lock(&i->lock);
11609 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11610 ast_mutex_unlock(&i->lock);
11611 break;
11612 #endif
11613 #if defined(HAVE_SS7)
11614 case SIG_SS7:
11615 sig_ss7_set_alarm(i->sig_pvt, 1);
11616 break;
11617 #endif
11618 default:
11619 i->inalarm = 1;
11620 break;
11621 }
11622 res = get_alarms(i);
11623 handle_alarms(i, res);
11624
11625 case DAHDI_EVENT_ONHOOK:
11626 if (i->radio)
11627 break;
11628
11629 switch (i->sig) {
11630 case SIG_FXOLS:
11631 case SIG_FXOGS:
11632 case SIG_FEATD:
11633 case SIG_FEATDMF:
11634 case SIG_FEATDMF_TA:
11635 case SIG_E911:
11636 case SIG_FGC_CAMA:
11637 case SIG_FGC_CAMAMF:
11638 case SIG_FEATB:
11639 case SIG_EM:
11640 case SIG_EM_E1:
11641 case SIG_EMWINK:
11642 case SIG_SF_FEATD:
11643 case SIG_SF_FEATDMF:
11644 case SIG_SF_FEATB:
11645 case SIG_SF:
11646 case SIG_SFWINK:
11647 case SIG_FXSLS:
11648 case SIG_FXSGS:
11649 case SIG_FXSKS:
11650 case SIG_FXOKS:
11651 dahdi_disable_ec(i);
11652
11653 #ifdef ZHONE_HACK
11654 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11655 usleep(1);
11656 #endif
11657 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11658 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11659 break;
11660 case SIG_SS7:
11661 case SIG_PRI_LIB_HANDLE_CASES:
11662 dahdi_disable_ec(i);
11663 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11664 break;
11665 default:
11666 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11667 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11668 return NULL;
11669 }
11670 break;
11671 case DAHDI_EVENT_POLARITY:
11672 switch (i->sig) {
11673 case SIG_FXSLS:
11674 case SIG_FXSKS:
11675 case SIG_FXSGS:
11676
11677
11678
11679
11680 if (i->hanguponpolarityswitch)
11681 i->polarity = POLARITY_REV;
11682 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11683 i->polarity = POLARITY_REV;
11684 ast_verb(2, "Starting post polarity "
11685 "CID detection on channel %d\n",
11686 i->channel);
11687 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11688 if (!chan) {
11689 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11690 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11691 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11692 ast_hangup(chan);
11693 }
11694 }
11695 break;
11696 default:
11697 ast_log(LOG_WARNING, "handle_init_event detected "
11698 "polarity reversal on non-FXO (SIG_FXS) "
11699 "interface %d\n", i->channel);
11700 }
11701 break;
11702 case DAHDI_EVENT_REMOVED:
11703 ast_log(LOG_NOTICE,
11704 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11705 i->channel);
11706 return i;
11707 case DAHDI_EVENT_NEONMWI_ACTIVE:
11708 if (i->mwimonitor_neon) {
11709 notify_message(i->mailbox, 1);
11710 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11711 }
11712 break;
11713 case DAHDI_EVENT_NEONMWI_INACTIVE:
11714 if (i->mwimonitor_neon) {
11715 notify_message(i->mailbox, 0);
11716 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11717 }
11718 break;
11719 }
11720 return NULL;
11721 }
11722
11723 static void *do_monitor(void *data)
11724 {
11725 int count, res, res2, spoint, pollres=0;
11726 struct dahdi_pvt *i;
11727 struct dahdi_pvt *last = NULL;
11728 struct dahdi_pvt *doomed;
11729 time_t thispass = 0, lastpass = 0;
11730 int found;
11731 char buf[1024];
11732 struct pollfd *pfds=NULL;
11733 int lastalloc = -1;
11734
11735
11736
11737 #if 0
11738 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11739 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11740 return NULL;
11741 }
11742 ast_debug(1, "Monitor starting...\n");
11743 #endif
11744 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11745
11746 for (;;) {
11747
11748 ast_mutex_lock(&iflock);
11749 if (!pfds || (lastalloc != ifcount)) {
11750 if (pfds) {
11751 ast_free(pfds);
11752 pfds = NULL;
11753 }
11754 if (ifcount) {
11755 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11756 ast_mutex_unlock(&iflock);
11757 return NULL;
11758 }
11759 }
11760 lastalloc = ifcount;
11761 }
11762
11763
11764 count = 0;
11765 for (i = iflist; i; i = i->next) {
11766 ast_mutex_lock(&i->lock);
11767 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11768 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11769 struct analog_pvt *p = i->sig_pvt;
11770
11771 if (!p) {
11772 ast_log(LOG_ERROR, "No sig_pvt?\n");
11773 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11774
11775 pfds[count].fd = i->subs[SUB_REAL].dfd;
11776 pfds[count].events = POLLPRI;
11777 pfds[count].revents = 0;
11778
11779 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11780 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11781 pfds[count].events |= POLLIN;
11782 }
11783 count++;
11784 }
11785 } else {
11786 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11787
11788 pfds[count].fd = i->subs[SUB_REAL].dfd;
11789 pfds[count].events = POLLPRI;
11790 pfds[count].revents = 0;
11791
11792
11793 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11794 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11795 pfds[count].events |= POLLIN;
11796 }
11797 count++;
11798 }
11799 }
11800 }
11801 ast_mutex_unlock(&i->lock);
11802 }
11803
11804 ast_mutex_unlock(&iflock);
11805
11806 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11807 pthread_testcancel();
11808
11809 res = poll(pfds, count, 1000);
11810 pthread_testcancel();
11811 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11812
11813
11814 if (res < 0) {
11815 if ((errno != EAGAIN) && (errno != EINTR))
11816 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11817 continue;
11818 }
11819
11820
11821 ast_mutex_lock(&iflock);
11822 found = 0;
11823 spoint = 0;
11824 lastpass = thispass;
11825 thispass = time(NULL);
11826 doomed = NULL;
11827 for (i = iflist;; i = i->next) {
11828 if (doomed) {
11829 int res;
11830 res = dahdi_destroy_channel_bynum(doomed->channel);
11831 if (res != RESULT_SUCCESS) {
11832 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11833 }
11834 doomed = NULL;
11835 }
11836 if (!i) {
11837 break;
11838 }
11839
11840 if (thispass != lastpass) {
11841 if (!found && ((i == last) || ((i == iflist) && !last))) {
11842 last = i;
11843 if (last) {
11844 struct analog_pvt *analog_p = last->sig_pvt;
11845
11846 if (analog_p
11847 && !last->mwisendactive
11848 && (last->sig & __DAHDI_SIG_FXO)
11849 && !analog_p->fxsoffhookstate
11850 && !last->owner
11851 && !ast_strlen_zero(last->mailbox)
11852 && (thispass - analog_p->onhooktime > 3)) {
11853 res = has_voicemail(last);
11854 if (analog_p->msgstate != res) {
11855
11856 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11857 if (res2) {
11858
11859 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11860 }
11861
11862 if (mwi_send_init(last)) {
11863 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11864 }
11865 analog_p->msgstate = res;
11866 found ++;
11867 }
11868 }
11869 last = last->next;
11870 }
11871 }
11872 }
11873 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11874 if (i->radio && !i->owner)
11875 {
11876 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11877 if (res)
11878 {
11879 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11880
11881 ast_mutex_unlock(&iflock);
11882 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11883 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11884 else
11885 doomed = handle_init_event(i, res);
11886 ast_mutex_lock(&iflock);
11887 }
11888 continue;
11889 }
11890 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11891 if (pollres & POLLIN) {
11892 if (i->owner || i->subs[SUB_REAL].owner) {
11893 #ifdef HAVE_PRI
11894 if (!i->pri)
11895 #endif
11896 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11897 continue;
11898 }
11899 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11900 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11901 continue;
11902 }
11903 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11904 if (res > 0) {
11905 if (i->mwimonitor_fsk) {
11906 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11907 pthread_attr_t attr;
11908 pthread_t threadid;
11909 struct mwi_thread_data *mtd;
11910
11911 pthread_attr_init(&attr);
11912 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11913
11914 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11915 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11916 mtd->pvt = i;
11917 memcpy(mtd->buf, buf, res);
11918 mtd->len = res;
11919 i->mwimonitoractive = 1;
11920 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11921 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11922 i->mwimonitoractive = 0;
11923 ast_free(mtd);
11924 }
11925 }
11926 }
11927
11928 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11929 int energy;
11930 struct timeval now;
11931
11932
11933
11934 if (1 == i->dtmfcid_holdoff_state) {
11935 gettimeofday(&i->dtmfcid_delay, NULL);
11936 i->dtmfcid_holdoff_state = 2;
11937 } else if (2 == i->dtmfcid_holdoff_state) {
11938 gettimeofday(&now, NULL);
11939 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11940 i->dtmfcid_holdoff_state = 0;
11941 }
11942 } else {
11943 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11944 if (!i->mwisendactive && energy > dtmfcid_level) {
11945 pthread_t threadid;
11946 struct ast_channel *chan;
11947 ast_mutex_unlock(&iflock);
11948 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11949
11950 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11951 i->dtmfcid_holdoff_state = 1;
11952 } else {
11953 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11954 if (!chan) {
11955 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11956 } else {
11957 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11958 if (res) {
11959 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11960 ast_hangup(chan);
11961 } else {
11962 i->dtmfcid_holdoff_state = 1;
11963 }
11964 }
11965 }
11966 ast_mutex_lock(&iflock);
11967 }
11968 }
11969 }
11970 if (i->mwisendactive) {
11971 mwi_send_process_buffer(i, res);
11972 }
11973 } else {
11974 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11975 }
11976 }
11977 if (pollres & POLLPRI) {
11978 if (i->owner || i->subs[SUB_REAL].owner) {
11979 #ifdef HAVE_PRI
11980 if (!i->pri)
11981 #endif
11982 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11983 continue;
11984 }
11985 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11986 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11987
11988 ast_mutex_unlock(&iflock);
11989 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11990 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11991 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11992 else
11993 doomed = handle_init_event(i, res);
11994 }
11995 ast_mutex_lock(&iflock);
11996 }
11997 }
11998 }
11999 ast_mutex_unlock(&iflock);
12000 }
12001
12002 return NULL;
12003
12004 }
12005
12006 static int restart_monitor(void)
12007 {
12008
12009 if (monitor_thread == AST_PTHREADT_STOP)
12010 return 0;
12011 ast_mutex_lock(&monlock);
12012 if (monitor_thread == pthread_self()) {
12013 ast_mutex_unlock(&monlock);
12014 ast_log(LOG_WARNING, "Cannot kill myself\n");
12015 return -1;
12016 }
12017 if (monitor_thread != AST_PTHREADT_NULL) {
12018
12019 pthread_kill(monitor_thread, SIGURG);
12020 } else {
12021
12022 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
12023 ast_mutex_unlock(&monlock);
12024 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
12025 return -1;
12026 }
12027 }
12028 ast_mutex_unlock(&monlock);
12029 return 0;
12030 }
12031
12032 #if defined(HAVE_PRI)
12033 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
12034 {
12035 int x;
12036 int trunkgroup;
12037
12038 trunkgroup = pris[*span].mastertrunkgroup;
12039 if (trunkgroup) {
12040
12041 for (x = 0; x < NUM_SPANS; x++) {
12042 if (pris[x].pri.trunkgroup == trunkgroup) {
12043 *span = x;
12044 return 0;
12045 }
12046 }
12047 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
12048 *span = -1;
12049 } else {
12050 if (pris[*span].pri.trunkgroup) {
12051 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);
12052 *span = -1;
12053 } else if (pris[*span].mastertrunkgroup) {
12054 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12055 *span = -1;
12056 } else {
12057 if (si->totalchans == 31) {
12058
12059 pris[*span].dchannels[0] = 16 + offset;
12060 } else if (si->totalchans == 24) {
12061
12062 pris[*span].dchannels[0] = 24 + offset;
12063 } else if (si->totalchans == 3) {
12064
12065 pris[*span].dchannels[0] = 3 + offset;
12066 } else {
12067 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);
12068 *span = -1;
12069 return 0;
12070 }
12071 pris[*span].pri.span = *span + 1;
12072 }
12073 }
12074 return 0;
12075 }
12076 #endif
12077
12078 #if defined(HAVE_PRI)
12079 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12080 {
12081 struct dahdi_spaninfo si;
12082 struct dahdi_params p;
12083 int fd;
12084 int span;
12085 int ospan=0;
12086 int x,y;
12087 for (x = 0; x < NUM_SPANS; x++) {
12088 if (pris[x].pri.trunkgroup == trunkgroup) {
12089 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12090 return -1;
12091 }
12092 }
12093 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12094 if (!channels[y])
12095 break;
12096 memset(&si, 0, sizeof(si));
12097 memset(&p, 0, sizeof(p));
12098 fd = open("/dev/dahdi/channel", O_RDWR);
12099 if (fd < 0) {
12100 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12101 return -1;
12102 }
12103 x = channels[y];
12104 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12105 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12106 close(fd);
12107 return -1;
12108 }
12109 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12110 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12111 return -1;
12112 }
12113 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12114 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12115 close(fd);
12116 return -1;
12117 }
12118 span = p.spanno - 1;
12119 if (pris[span].pri.trunkgroup) {
12120 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12121 close(fd);
12122 return -1;
12123 }
12124 if (pris[span].pri.pvts[0]) {
12125 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12126 close(fd);
12127 return -1;
12128 }
12129 if (!y) {
12130 pris[span].pri.trunkgroup = trunkgroup;
12131 ospan = span;
12132 }
12133 pris[ospan].dchannels[y] = channels[y];
12134 pris[span].pri.span = span + 1;
12135 close(fd);
12136 }
12137 return 0;
12138 }
12139 #endif
12140
12141 #if defined(HAVE_PRI)
12142 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12143 {
12144 if (pris[span].mastertrunkgroup) {
12145 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);
12146 return -1;
12147 }
12148 pris[span].mastertrunkgroup = trunkgroup;
12149 pris[span].prilogicalspan = logicalspan;
12150 return 0;
12151 }
12152 #endif
12153
12154 #if defined(HAVE_SS7)
12155 static unsigned int parse_pointcode(const char *pcstring)
12156 {
12157 unsigned int code1, code2, code3;
12158 int numvals;
12159
12160 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12161 if (numvals == 1)
12162 return code1;
12163 if (numvals == 3)
12164 return (code1 << 16) | (code2 << 8) | code3;
12165
12166 return 0;
12167 }
12168 #endif
12169
12170 #if defined(HAVE_SS7)
12171 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12172 {
12173 if ((linkset < 0) || (linkset >= NUM_SPANS))
12174 return NULL;
12175 else
12176 return &linksets[linkset - 1];
12177 }
12178 #endif
12179
12180 #ifdef HAVE_OPENR2
12181 static void dahdi_r2_destroy_links(void)
12182 {
12183 int i = 0;
12184 if (!r2links) {
12185 return;
12186 }
12187 for (; i < r2links_count; i++) {
12188 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12189 pthread_cancel(r2links[i]->r2master);
12190 pthread_join(r2links[i]->r2master, NULL);
12191 openr2_context_delete(r2links[i]->protocol_context);
12192 }
12193 ast_free(r2links[i]);
12194 }
12195 ast_free(r2links);
12196 r2links = NULL;
12197 r2links_count = 0;
12198 }
12199
12200 #define R2_LINK_CAPACITY 10
12201 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12202 {
12203 struct dahdi_mfcr2 *new_r2link = NULL;
12204 struct dahdi_mfcr2 **new_r2links = NULL;
12205
12206
12207 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12208 new_r2link = ast_calloc(1, sizeof(**r2links));
12209 if (!new_r2link) {
12210 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12211 return NULL;
12212 }
12213 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12214 if (!new_r2links) {
12215 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12216 ast_free(new_r2link);
12217 return NULL;
12218 }
12219 r2links = new_r2links;
12220 new_r2link->r2master = AST_PTHREADT_NULL;
12221 r2links[r2links_count] = new_r2link;
12222 r2links_count++;
12223 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12224 }
12225 return r2links[r2links_count - 1];
12226 }
12227
12228 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12229 {
12230 char tmplogdir[] = "/tmp";
12231 char logdir[OR2_MAX_PATH];
12232 int threshold = 0;
12233 int snres = 0;
12234 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12235 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12236 conf->mfcr2.max_dnis);
12237 if (!r2_link->protocol_context) {
12238 return -1;
12239 }
12240 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12241 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12242 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12243 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12244 #endif
12245 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12246 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12247 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12248 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12249 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12250 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12251 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12252 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12253 }
12254 } else {
12255 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12256 if (snres >= sizeof(logdir)) {
12257 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12258 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12259 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12260 }
12261 } else {
12262 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12263 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12264 }
12265 }
12266 }
12267 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12268 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12269 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12270 }
12271 }
12272 r2_link->monitored_count = 0;
12273 return 0;
12274 }
12275 #endif
12276
12277
12278
12279
12280
12281
12282 static int sigtype_to_signalling(int sigtype)
12283 {
12284 return sigtype;
12285 }
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12300 {
12301 struct stat stbuf;
12302 int num;
12303
12304 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12305 if (stat(path, &stbuf) < 0) {
12306 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12307 return -errno;
12308 }
12309 if (!S_ISCHR(stbuf.st_mode)) {
12310 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12311 return -EINVAL;
12312 }
12313 num = minor(stbuf.st_rdev);
12314 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12315 return num;
12316
12317 }
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12334 {
12335
12336 struct dahdi_pvt *tmp;
12337 char fn[80];
12338 struct dahdi_bufferinfo bi;
12339
12340 int res;
12341 #if defined(HAVE_PRI)
12342 int span = 0;
12343 #endif
12344 int here = 0;
12345 int x;
12346 struct analog_pvt *analog_p = NULL;
12347 struct dahdi_params p;
12348 #if defined(HAVE_PRI)
12349 struct dahdi_spaninfo si;
12350 struct sig_pri_chan *pri_chan = NULL;
12351 #endif
12352 #if defined(HAVE_SS7)
12353 struct sig_ss7_chan *ss7_chan = NULL;
12354 #endif
12355
12356
12357 for (tmp = iflist; tmp; tmp = tmp->next) {
12358 if (!tmp->destroy) {
12359 if (tmp->channel == channel) {
12360
12361 here = 1;
12362 break;
12363 }
12364 if (tmp->channel > channel) {
12365
12366 tmp = NULL;
12367 break;
12368 }
12369 }
12370 }
12371
12372 if (!here && reloading != 1) {
12373 tmp = ast_calloc(1, sizeof(*tmp));
12374 if (!tmp) {
12375 return NULL;
12376 }
12377 tmp->cc_params = ast_cc_config_params_init();
12378 if (!tmp->cc_params) {
12379 ast_free(tmp);
12380 return NULL;
12381 }
12382 ast_mutex_init(&tmp->lock);
12383 ifcount++;
12384 for (x = 0; x < 3; x++)
12385 tmp->subs[x].dfd = -1;
12386 tmp->channel = channel;
12387 tmp->priindication_oob = conf->chan.priindication_oob;
12388 }
12389
12390 if (tmp) {
12391 int chan_sig = conf->chan.sig;
12392
12393
12394 if (reloading && tmp->vars) {
12395 ast_variables_destroy(tmp->vars);
12396 tmp->vars = NULL;
12397 }
12398
12399
12400 if (!here) {
12401
12402 if ((channel != CHAN_PSEUDO)) {
12403 int count = 0;
12404
12405 snprintf(fn, sizeof(fn), "%d", channel);
12406
12407 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12408 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12409 usleep(1);
12410 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12411 count++;
12412 }
12413
12414 if (tmp->subs[SUB_REAL].dfd < 0) {
12415 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);
12416 destroy_dahdi_pvt(tmp);
12417 return NULL;
12418 }
12419 memset(&p, 0, sizeof(p));
12420 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12421 if (res < 0) {
12422 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12423 destroy_dahdi_pvt(tmp);
12424 return NULL;
12425 }
12426 if (conf->is_sig_auto)
12427 chan_sig = sigtype_to_signalling(p.sigtype);
12428 if (p.sigtype != (chan_sig & 0x3ffff)) {
12429 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));
12430 destroy_dahdi_pvt(tmp);
12431 return NULL;
12432 }
12433 tmp->law_default = p.curlaw;
12434 tmp->law = p.curlaw;
12435 tmp->span = p.spanno;
12436 #if defined(HAVE_PRI)
12437 span = p.spanno - 1;
12438 #endif
12439 } else {
12440 chan_sig = 0;
12441 }
12442 tmp->sig = chan_sig;
12443 tmp->outsigmod = conf->chan.outsigmod;
12444
12445 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12446 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12447 if (!analog_p) {
12448 destroy_dahdi_pvt(tmp);
12449 return NULL;
12450 }
12451 tmp->sig_pvt = analog_p;
12452 }
12453 #if defined(HAVE_SS7)
12454 if (chan_sig == SIG_SS7) {
12455 struct dahdi_ss7 *ss7;
12456 int clear = 0;
12457
12458 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12459 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12460 destroy_dahdi_pvt(tmp);
12461 return NULL;
12462 }
12463
12464 ss7 = ss7_resolve_linkset(cur_linkset);
12465 if (!ss7) {
12466 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12467 destroy_dahdi_pvt(tmp);
12468 return NULL;
12469 }
12470 ss7->ss7.span = cur_linkset;
12471 if (cur_cicbeginswith < 0) {
12472 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12473 destroy_dahdi_pvt(tmp);
12474 return NULL;
12475 }
12476 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12477 if (!ss7_chan) {
12478 destroy_dahdi_pvt(tmp);
12479 return NULL;
12480 }
12481 tmp->sig_pvt = ss7_chan;
12482 tmp->ss7 = &ss7->ss7;
12483
12484 ss7_chan->channel = tmp->channel;
12485 ss7_chan->cic = cur_cicbeginswith++;
12486
12487
12488 ss7_chan->dpc = cur_defaultdpc;
12489
12490 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12491
12492 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12493 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12494 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12495 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12496
12497 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12498 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12499 }
12500 #endif
12501 #ifdef HAVE_OPENR2
12502 if (chan_sig == SIG_MFCR2) {
12503 struct dahdi_mfcr2 *r2_link;
12504 r2_link = dahdi_r2_get_link();
12505 if (!r2_link) {
12506 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12507 destroy_dahdi_pvt(tmp);
12508 return NULL;
12509 }
12510 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12511 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12512 destroy_dahdi_pvt(tmp);
12513 return NULL;
12514 }
12515 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12516 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12517 destroy_dahdi_pvt(tmp);
12518 return NULL;
12519 }
12520 r2_link->pvts[r2_link->numchans++] = tmp;
12521 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12522 tmp->subs[SUB_REAL].dfd,
12523 NULL, NULL);
12524 if (!tmp->r2chan) {
12525 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12526 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12527 destroy_dahdi_pvt(tmp);
12528 return NULL;
12529 }
12530 tmp->mfcr2 = r2_link;
12531 if (conf->mfcr2.call_files) {
12532 openr2_chan_enable_call_files(tmp->r2chan);
12533 }
12534 openr2_chan_set_client_data(tmp->r2chan, tmp);
12535
12536 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12537 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12538 tmp->mfcr2_category = conf->mfcr2.category;
12539 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12540 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12541 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12542 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12543 tmp->mfcr2call = 0;
12544 tmp->mfcr2_dnis_index = 0;
12545 tmp->mfcr2_ani_index = 0;
12546 r2_link->monitored_count++;
12547 }
12548 #endif
12549 #ifdef HAVE_PRI
12550 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12551 int offset;
12552 int matchesdchan;
12553 int x,y;
12554 int myswitchtype = 0;
12555
12556 offset = 0;
12557 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12558 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12559 destroy_dahdi_pvt(tmp);
12560 return NULL;
12561 }
12562 if (span >= NUM_SPANS) {
12563 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12564 destroy_dahdi_pvt(tmp);
12565 return NULL;
12566 } else {
12567 si.spanno = 0;
12568 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12569 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12570 destroy_dahdi_pvt(tmp);
12571 return NULL;
12572 }
12573
12574 tmp->logicalspan = pris[span].prilogicalspan;
12575 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12576 if (span < 0) {
12577 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12578 destroy_dahdi_pvt(tmp);
12579 return NULL;
12580 }
12581 myswitchtype = conf->pri.pri.switchtype;
12582
12583 matchesdchan=0;
12584 for (x = 0; x < NUM_SPANS; x++) {
12585 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12586 if (pris[x].dchannels[y] == tmp->channel) {
12587 matchesdchan = 1;
12588 break;
12589 }
12590 }
12591 }
12592 if (!matchesdchan) {
12593 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12594 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12595 destroy_dahdi_pvt(tmp);
12596 return NULL;
12597 }
12598 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12599 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12600 destroy_dahdi_pvt(tmp);
12601 return NULL;
12602 }
12603 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12604 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));
12605 destroy_dahdi_pvt(tmp);
12606 return NULL;
12607 }
12608 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12609 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12610 destroy_dahdi_pvt(tmp);
12611 return NULL;
12612 }
12613 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12614 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12615 destroy_dahdi_pvt(tmp);
12616 return NULL;
12617 }
12618 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12619 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12620 destroy_dahdi_pvt(tmp);
12621 return NULL;
12622 }
12623 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12624 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12625 destroy_dahdi_pvt(tmp);
12626 return NULL;
12627 }
12628 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12629 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12630 pris[span].pri.trunkgroup);
12631 destroy_dahdi_pvt(tmp);
12632 return NULL;
12633 }
12634
12635 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12636 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12637 if (!pri_chan) {
12638 destroy_dahdi_pvt(tmp);
12639 return NULL;
12640 }
12641 tmp->sig_pvt = pri_chan;
12642 tmp->pri = &pris[span].pri;
12643
12644 tmp->priexclusive = conf->chan.priexclusive;
12645
12646 if (!tmp->pri->cc_params) {
12647 tmp->pri->cc_params = ast_cc_config_params_init();
12648 if (!tmp->pri->cc_params) {
12649 destroy_dahdi_pvt(tmp);
12650 return NULL;
12651 }
12652 }
12653 ast_cc_copy_config_params(tmp->pri->cc_params,
12654 conf->chan.cc_params);
12655
12656 pris[span].pri.sig = chan_sig;
12657 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12658 pris[span].pri.switchtype = myswitchtype;
12659 pris[span].pri.nsf = conf->pri.pri.nsf;
12660 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12661 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12662 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12663 pris[span].pri.minunused = conf->pri.pri.minunused;
12664 pris[span].pri.minidle = conf->pri.pri.minidle;
12665 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12666 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12667 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12668 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12669 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12670 #endif
12671 #ifdef HAVE_PRI_INBANDDISCONNECT
12672 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12673 #endif
12674 #if defined(HAVE_PRI_CALL_HOLD)
12675 pris[span].pri.hold_disconnect_transfer =
12676 conf->pri.pri.hold_disconnect_transfer;
12677 #endif
12678 #if defined(HAVE_PRI_CCSS)
12679 pris[span].pri.cc_ptmp_recall_mode =
12680 conf->pri.pri.cc_ptmp_recall_mode;
12681 pris[span].pri.cc_qsig_signaling_link_req =
12682 conf->pri.pri.cc_qsig_signaling_link_req;
12683 pris[span].pri.cc_qsig_signaling_link_rsp =
12684 conf->pri.pri.cc_qsig_signaling_link_rsp;
12685 #endif
12686 #if defined(HAVE_PRI_CALL_WAITING)
12687 pris[span].pri.max_call_waiting_calls =
12688 conf->pri.pri.max_call_waiting_calls;
12689 pris[span].pri.allow_call_waiting_calls =
12690 conf->pri.pri.allow_call_waiting_calls;
12691 #endif
12692 pris[span].pri.transfer = conf->chan.transfer;
12693 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12694 #if defined(HAVE_PRI_L2_PERSISTENCE)
12695 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12696 #endif
12697 #if defined(HAVE_PRI_AOC_EVENTS)
12698 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12699 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12700 #endif
12701 if (chan_sig == SIG_BRI_PTMP) {
12702 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12703 } else {
12704
12705 pris[span].pri.layer1_ignored = 0;
12706 }
12707 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12708 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12709 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12710 #if defined(HAVE_PRI_MWI)
12711 ast_copy_string(pris[span].pri.mwi_mailboxes,
12712 conf->pri.pri.mwi_mailboxes,
12713 sizeof(pris[span].pri.mwi_mailboxes));
12714 #endif
12715 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12716 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12717 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12718 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12719 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12720 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12721 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12722 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12723
12724 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12725 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12726 }
12727
12728 #if defined(HAVE_PRI_CALL_WAITING)
12729
12730 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12731 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12732 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12733 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12734 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12735 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12736 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12737 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12738 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12739 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12740 #endif
12741 } else {
12742 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12743 destroy_dahdi_pvt(tmp);
12744 return NULL;
12745 }
12746 }
12747 }
12748 #endif
12749 } else {
12750
12751 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));
12752 chan_sig = tmp->sig;
12753 if (tmp->subs[SUB_REAL].dfd > -1) {
12754 memset(&p, 0, sizeof(p));
12755 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12756 }
12757 }
12758
12759 switch (chan_sig) {
12760 case SIG_FXSKS:
12761 case SIG_FXSLS:
12762 case SIG_EM:
12763 case SIG_EM_E1:
12764 case SIG_EMWINK:
12765 case SIG_FEATD:
12766 case SIG_FEATDMF:
12767 case SIG_FEATDMF_TA:
12768 case SIG_FEATB:
12769 case SIG_E911:
12770 case SIG_SF:
12771 case SIG_SFWINK:
12772 case SIG_FGC_CAMA:
12773 case SIG_FGC_CAMAMF:
12774 case SIG_SF_FEATD:
12775 case SIG_SF_FEATDMF:
12776 case SIG_SF_FEATB:
12777 p.starttime = 250;
12778 break;
12779 }
12780
12781 if (tmp->radio) {
12782
12783 p.channo = channel;
12784 p.rxwinktime = 1;
12785 p.rxflashtime = 1;
12786 p.starttime = 1;
12787 p.debouncetime = 5;
12788 } else {
12789 p.channo = channel;
12790
12791 if (conf->timing.prewinktime >= 0)
12792 p.prewinktime = conf->timing.prewinktime;
12793 if (conf->timing.preflashtime >= 0)
12794 p.preflashtime = conf->timing.preflashtime;
12795 if (conf->timing.winktime >= 0)
12796 p.winktime = conf->timing.winktime;
12797 if (conf->timing.flashtime >= 0)
12798 p.flashtime = conf->timing.flashtime;
12799 if (conf->timing.starttime >= 0)
12800 p.starttime = conf->timing.starttime;
12801 if (conf->timing.rxwinktime >= 0)
12802 p.rxwinktime = conf->timing.rxwinktime;
12803 if (conf->timing.rxflashtime >= 0)
12804 p.rxflashtime = conf->timing.rxflashtime;
12805 if (conf->timing.debouncetime >= 0)
12806 p.debouncetime = conf->timing.debouncetime;
12807 }
12808
12809
12810 if (tmp->subs[SUB_REAL].dfd >= 0)
12811 {
12812 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12813 if (res < 0) {
12814 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12815 destroy_dahdi_pvt(tmp);
12816 return NULL;
12817 }
12818 }
12819 #if 1
12820 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12821 memset(&bi, 0, sizeof(bi));
12822 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12823 if (!res) {
12824 bi.txbufpolicy = conf->chan.buf_policy;
12825 bi.rxbufpolicy = conf->chan.buf_policy;
12826 bi.numbufs = conf->chan.buf_no;
12827 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12828 if (res < 0) {
12829 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12830 }
12831 } else {
12832 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12833 }
12834 tmp->buf_policy = conf->chan.buf_policy;
12835 tmp->buf_no = conf->chan.buf_no;
12836 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12837 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12838 tmp->faxbuf_no = conf->chan.faxbuf_no;
12839
12840
12841
12842
12843 tmp->bufsize = bi.bufsize;
12844 }
12845 #endif
12846 tmp->immediate = conf->chan.immediate;
12847 tmp->transfertobusy = conf->chan.transfertobusy;
12848 if (chan_sig & __DAHDI_SIG_FXS) {
12849 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12850 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12851 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12852 }
12853 tmp->ringt_base = ringt_base;
12854 tmp->firstradio = 0;
12855 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12856 tmp->permcallwaiting = conf->chan.callwaiting;
12857 else
12858 tmp->permcallwaiting = 0;
12859
12860 tmp->destroy = 0;
12861 tmp->drings = conf->chan.drings;
12862
12863
12864 if (tmp->drings.ringnum[0].range == 0)
12865 tmp->drings.ringnum[0].range = 10;
12866 if (tmp->drings.ringnum[1].range == 0)
12867 tmp->drings.ringnum[1].range = 10;
12868 if (tmp->drings.ringnum[2].range == 0)
12869 tmp->drings.ringnum[2].range = 10;
12870
12871 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12872 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12873 tmp->threewaycalling = conf->chan.threewaycalling;
12874 tmp->adsi = conf->chan.adsi;
12875 tmp->use_smdi = conf->chan.use_smdi;
12876 tmp->permhidecallerid = conf->chan.hidecallerid;
12877 tmp->hidecalleridname = conf->chan.hidecalleridname;
12878 tmp->callreturn = conf->chan.callreturn;
12879 tmp->echocancel = conf->chan.echocancel;
12880 tmp->echotraining = conf->chan.echotraining;
12881 tmp->pulse = conf->chan.pulse;
12882 if (tmp->echocancel.head.tap_length) {
12883 tmp->echocanbridged = conf->chan.echocanbridged;
12884 } else {
12885 if (conf->chan.echocanbridged)
12886 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12887 tmp->echocanbridged = 0;
12888 }
12889 tmp->busydetect = conf->chan.busydetect;
12890 tmp->busycount = conf->chan.busycount;
12891 tmp->busycompare = conf->chan.busycompare;
12892 tmp->busytonelength = conf->chan.busytonelength;
12893 tmp->busyquietlength = conf->chan.busyquietlength;
12894 tmp->busyfuzziness = conf->chan.busyfuzziness;
12895 tmp->silencethreshold = conf->chan.silencethreshold;
12896 tmp->callprogress = conf->chan.callprogress;
12897 tmp->waitfordialtone = conf->chan.waitfordialtone;
12898 tmp->cancallforward = conf->chan.cancallforward;
12899 tmp->dtmfrelax = conf->chan.dtmfrelax;
12900 tmp->callwaiting = tmp->permcallwaiting;
12901 tmp->hidecallerid = tmp->permhidecallerid;
12902 tmp->channel = channel;
12903 tmp->stripmsd = conf->chan.stripmsd;
12904 tmp->use_callerid = conf->chan.use_callerid;
12905 tmp->cid_signalling = conf->chan.cid_signalling;
12906 tmp->cid_start = conf->chan.cid_start;
12907 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12908 tmp->restrictcid = conf->chan.restrictcid;
12909 tmp->use_callingpres = conf->chan.use_callingpres;
12910 if (tmp->usedistinctiveringdetection) {
12911 if (!tmp->use_callerid) {
12912 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12913 tmp->use_callerid = 1;
12914 }
12915 }
12916
12917 if (tmp->cid_signalling == CID_SIG_SMDI) {
12918 if (!tmp->use_smdi) {
12919 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12920 tmp->use_smdi = 1;
12921 }
12922 }
12923 if (tmp->use_smdi) {
12924 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12925 if (!(tmp->smdi_iface)) {
12926 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12927 tmp->use_smdi = 0;
12928 }
12929 }
12930
12931 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12932 tmp->amaflags = conf->chan.amaflags;
12933 if (!here) {
12934 tmp->confno = -1;
12935 tmp->propconfno = -1;
12936 }
12937 tmp->canpark = conf->chan.canpark;
12938 tmp->transfer = conf->chan.transfer;
12939 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12940 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12941 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12942 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12943 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12944 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12945 tmp->cid_ton = 0;
12946 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12947 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12948 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12949 } else {
12950 tmp->cid_num[0] = '\0';
12951 tmp->cid_name[0] = '\0';
12952 }
12953 #if defined(HAVE_PRI)
12954 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12955 tmp->cid_tag[0] = '\0';
12956 } else
12957 #endif
12958 {
12959 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12960 }
12961 tmp->cid_subaddr[0] = '\0';
12962 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12963 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12964 char *mailbox, *context;
12965 mailbox = context = ast_strdupa(tmp->mailbox);
12966 strsep(&context, "@");
12967 if (ast_strlen_zero(context))
12968 context = "default";
12969 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12970 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12971 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12972 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12973 AST_EVENT_IE_END);
12974 }
12975 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12976 tmp->mwisend_setting = conf->chan.mwisend_setting;
12977 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12978 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12979 #endif
12980
12981 tmp->group = conf->chan.group;
12982 tmp->callgroup = conf->chan.callgroup;
12983 tmp->pickupgroup= conf->chan.pickupgroup;
12984 if (conf->chan.vars) {
12985 struct ast_variable *v, *tmpvar;
12986 for (v = conf->chan.vars ; v ; v = v->next) {
12987 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12988 tmpvar->next = tmp->vars;
12989 tmp->vars = tmpvar;
12990 }
12991 }
12992 }
12993 tmp->cid_rxgain = conf->chan.cid_rxgain;
12994 tmp->rxgain = conf->chan.rxgain;
12995 tmp->txgain = conf->chan.txgain;
12996 tmp->txdrc = conf->chan.txdrc;
12997 tmp->rxdrc = conf->chan.rxdrc;
12998 tmp->tonezone = conf->chan.tonezone;
12999 if (tmp->subs[SUB_REAL].dfd > -1) {
13000 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
13001 if (tmp->dsp)
13002 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
13003 update_conf(tmp);
13004 if (!here) {
13005 switch (chan_sig) {
13006 case SIG_PRI_LIB_HANDLE_CASES:
13007 case SIG_SS7:
13008 case SIG_MFCR2:
13009 break;
13010 default:
13011
13012 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
13013 break;
13014 }
13015 }
13016 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
13017 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
13018
13019 switch (tmp->sig) {
13020 #ifdef HAVE_PRI
13021 case SIG_PRI_LIB_HANDLE_CASES:
13022 sig_pri_set_alarm(tmp->sig_pvt, 1);
13023 break;
13024 #endif
13025 #if defined(HAVE_SS7)
13026 case SIG_SS7:
13027 sig_ss7_set_alarm(tmp->sig_pvt, 1);
13028 break;
13029 #endif
13030 default:
13031
13032 analog_p = tmp->sig_pvt;
13033 if (analog_p) {
13034 analog_p->inalarm = 1;
13035 }
13036 tmp->inalarm = 1;
13037 break;
13038 }
13039 handle_alarms(tmp, res);
13040 }
13041 }
13042
13043 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13044 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13045 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13046 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
13047 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
13048
13049 if (!here) {
13050 tmp->locallyblocked = 0;
13051 tmp->remotelyblocked = 0;
13052 switch (tmp->sig) {
13053 #if defined(HAVE_PRI)
13054 case SIG_PRI_LIB_HANDLE_CASES:
13055 tmp->inservice = 1;
13056 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13057 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13058 if (chan_sig == SIG_PRI) {
13059 char db_chan_name[20];
13060 char db_answer[5];
13061
13062
13063
13064
13065
13066 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13067 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13068 unsigned *why;
13069
13070 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13071 if (tmp->pri->enable_service_message_support) {
13072 char state;
13073
13074 sscanf(db_answer, "%1c:%30u", &state, why);
13075
13076
13077 *why &= (SRVST_NEAREND | SRVST_FAREND);
13078 }
13079 if (!*why) {
13080 ast_db_del(db_chan_name, SRVST_DBKEY);
13081 }
13082 }
13083 }
13084 #endif
13085 break;
13086 #endif
13087 #if defined(HAVE_SS7)
13088 case SIG_SS7:
13089 tmp->inservice = 0;
13090 break;
13091 #endif
13092 default:
13093
13094 tmp->inservice = 1;
13095 break;
13096 }
13097 }
13098
13099 switch (tmp->sig) {
13100 #if defined(HAVE_PRI)
13101 case SIG_PRI_LIB_HANDLE_CASES:
13102 if (pri_chan) {
13103 pri_chan->channel = tmp->channel;
13104 pri_chan->hidecallerid = tmp->hidecallerid;
13105 pri_chan->hidecalleridname = tmp->hidecalleridname;
13106 pri_chan->immediate = tmp->immediate;
13107 pri_chan->inalarm = tmp->inalarm;
13108 pri_chan->priexclusive = tmp->priexclusive;
13109 pri_chan->priindication_oob = tmp->priindication_oob;
13110 pri_chan->use_callerid = tmp->use_callerid;
13111 pri_chan->use_callingpres = tmp->use_callingpres;
13112 ast_copy_string(pri_chan->context, tmp->context,
13113 sizeof(pri_chan->context));
13114 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13115 sizeof(pri_chan->mohinterpret));
13116 pri_chan->stripmsd = tmp->stripmsd;
13117 }
13118 break;
13119 #endif
13120 #if defined(HAVE_SS7)
13121 case SIG_SS7:
13122 if (ss7_chan) {
13123 ss7_chan->inalarm = tmp->inalarm;
13124
13125 ss7_chan->stripmsd = tmp->stripmsd;
13126 ss7_chan->hidecallerid = tmp->hidecallerid;
13127 ss7_chan->use_callerid = tmp->use_callerid;
13128 ss7_chan->use_callingpres = tmp->use_callingpres;
13129 ss7_chan->immediate = tmp->immediate;
13130 ss7_chan->locallyblocked = tmp->locallyblocked;
13131 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13132 ast_copy_string(ss7_chan->context, tmp->context,
13133 sizeof(ss7_chan->context));
13134 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13135 sizeof(ss7_chan->mohinterpret));
13136 }
13137 break;
13138 #endif
13139 default:
13140
13141 analog_p = tmp->sig_pvt;
13142 if (analog_p) {
13143 analog_p->channel = tmp->channel;
13144 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13145 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13146 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13147 analog_p->permcallwaiting = conf->chan.callwaiting;
13148 analog_p->callreturn = conf->chan.callreturn;
13149 analog_p->cancallforward = conf->chan.cancallforward;
13150 analog_p->canpark = conf->chan.canpark;
13151 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13152 analog_p->immediate = conf->chan.immediate;
13153 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13154 analog_p->pulse = conf->chan.pulse;
13155 analog_p->threewaycalling = conf->chan.threewaycalling;
13156 analog_p->transfer = conf->chan.transfer;
13157 analog_p->transfertobusy = conf->chan.transfertobusy;
13158 analog_p->use_callerid = tmp->use_callerid;
13159 analog_p->use_smdi = tmp->use_smdi;
13160 analog_p->smdi_iface = tmp->smdi_iface;
13161 analog_p->outsigmod = ANALOG_SIG_NONE;
13162 analog_p->echotraining = conf->chan.echotraining;
13163 analog_p->cid_signalling = conf->chan.cid_signalling;
13164 analog_p->stripmsd = conf->chan.stripmsd;
13165 switch (conf->chan.cid_start) {
13166 case CID_START_POLARITY:
13167 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13168 break;
13169 case CID_START_POLARITY_IN:
13170 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13171 break;
13172 case CID_START_DTMF_NOALERT:
13173 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13174 break;
13175 default:
13176 analog_p->cid_start = ANALOG_CID_START_RING;
13177 break;
13178 }
13179 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13180 analog_p->ringt = conf->chan.ringt;
13181 analog_p->ringt_base = ringt_base;
13182 analog_p->onhooktime = time(NULL);
13183 if (chan_sig & __DAHDI_SIG_FXO) {
13184 memset(&p, 0, sizeof(p));
13185 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13186 if (!res) {
13187 analog_p->fxsoffhookstate = p.rxisoffhook;
13188 }
13189 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13190 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13191 #endif
13192 }
13193 analog_p->msgstate = -1;
13194
13195 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13196 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13197 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13198
13199 analog_config_complete(analog_p);
13200 }
13201 break;
13202 }
13203 #if defined(HAVE_PRI)
13204 if (tmp->channel == CHAN_PSEUDO) {
13205
13206
13207
13208
13209 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13210 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13211 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13212 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13213 }
13214 #endif
13215 }
13216 if (tmp && !here) {
13217
13218 dahdi_iflist_insert(tmp);
13219 }
13220 return tmp;
13221 }
13222
13223 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13224 {
13225 #if defined(HAVE_PRI)
13226 if (0 < span) {
13227
13228 if (!p->pri || p->pri->span != span) {
13229 return 0;
13230 }
13231 if (!groupmatch && channelmatch == -1) {
13232
13233 *groupmatched = 1;
13234 return 1;
13235 }
13236 }
13237 #endif
13238
13239 if (groupmatch) {
13240 if ((p->group & groupmatch) != groupmatch)
13241
13242 return 0;
13243 *groupmatched = 1;
13244 }
13245
13246 if (channelmatch != -1) {
13247 if (p->channel != channelmatch)
13248
13249 return 0;
13250 *channelmatched = 1;
13251 }
13252
13253 return 1;
13254 }
13255
13256 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13257 {
13258 struct dahdi_pvt *p = *pvt;
13259
13260 if (p->inalarm)
13261 return 0;
13262
13263 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13264 return analog_available(p->sig_pvt);
13265
13266 switch (p->sig) {
13267 #if defined(HAVE_PRI)
13268 case SIG_PRI_LIB_HANDLE_CASES:
13269 {
13270 struct sig_pri_chan *pvt_chan;
13271 int res;
13272
13273 pvt_chan = p->sig_pvt;
13274 res = sig_pri_available(&pvt_chan, is_specific_channel);
13275 *pvt = pvt_chan->chan_pvt;
13276 return res;
13277 }
13278 #endif
13279 #if defined(HAVE_SS7)
13280 case SIG_SS7:
13281 return sig_ss7_available(p->sig_pvt);
13282 #endif
13283 default:
13284 break;
13285 }
13286
13287 if (p->locallyblocked || p->remotelyblocked) {
13288 return 0;
13289 }
13290
13291
13292 if (!p->owner) {
13293 #ifdef HAVE_OPENR2
13294
13295 if (p->mfcr2) {
13296 if (p->mfcr2call) {
13297 return 0;
13298 } else {
13299 return 1;
13300 }
13301 }
13302 #endif
13303 return 1;
13304 }
13305
13306 return 0;
13307 }
13308
13309 #if defined(HAVE_PRI)
13310 #if defined(HAVE_PRI_CALL_WAITING)
13311
13312
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322
13323 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13324 {
13325 struct dahdi_pvt *pvt = priv;
13326
13327 pvt->stripmsd = pri->ch_cfg.stripmsd;
13328 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13329 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13330 pvt->immediate = pri->ch_cfg.immediate;
13331 pvt->priexclusive = pri->ch_cfg.priexclusive;
13332 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13333 pvt->use_callerid = pri->ch_cfg.use_callerid;
13334 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13335 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13336 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13337 }
13338 #endif
13339 #endif
13340
13341 #if defined(HAVE_PRI)
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13355 {
13356 int pvt_idx;
13357 int res;
13358 unsigned idx;
13359 struct dahdi_pvt *pvt;
13360 struct sig_pri_chan *chan;
13361 struct dahdi_bufferinfo bi;
13362
13363 static int nobch_channel = CHAN_PSEUDO;
13364
13365
13366 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13367 if (!pri->pvts[pvt_idx]) {
13368 break;
13369 }
13370 }
13371 if (pri->numchans == pvt_idx) {
13372 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13373 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13374 return -1;
13375 }
13376
13377
13378 pri->pvts[pvt_idx] = NULL;
13379 ++pri->numchans;
13380 }
13381
13382 pvt = ast_calloc(1, sizeof(*pvt));
13383 if (!pvt) {
13384 return -1;
13385 }
13386 pvt->cc_params = ast_cc_config_params_init();
13387 if (!pvt->cc_params) {
13388 ast_free(pvt);
13389 return -1;
13390 }
13391 ast_mutex_init(&pvt->lock);
13392 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13393 pvt->subs[idx].dfd = -1;
13394 }
13395 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13396 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13397 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13398 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13399
13400 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13401 if (!chan) {
13402 destroy_dahdi_pvt(pvt);
13403 return -1;
13404 }
13405 chan->no_b_channel = 1;
13406
13407
13408
13409
13410
13411
13412 pvt->law_default = DAHDI_LAW_ALAW;
13413
13414 pvt->sig = pri->sig;
13415 pvt->outsigmod = -1;
13416 pvt->pri = pri;
13417 pvt->sig_pvt = chan;
13418 pri->pvts[pvt_idx] = chan;
13419
13420 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13421 if (pvt->subs[SUB_REAL].dfd < 0) {
13422 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13423 strerror(errno));
13424 destroy_dahdi_pvt(pvt);
13425 return -1;
13426 }
13427 memset(&bi, 0, sizeof(bi));
13428 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13429 if (!res) {
13430 pvt->bufsize = bi.bufsize;
13431 bi.txbufpolicy = pvt->buf_policy;
13432 bi.rxbufpolicy = pvt->buf_policy;
13433 bi.numbufs = pvt->buf_no;
13434 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13435 if (res < 0) {
13436 ast_log(LOG_WARNING,
13437 "Unable to set buffer policy on no B channel interface: %s\n",
13438 strerror(errno));
13439 }
13440 } else
13441 ast_log(LOG_WARNING,
13442 "Unable to check buffer policy on no B channel interface: %s\n",
13443 strerror(errno));
13444
13445 --nobch_channel;
13446 if (CHAN_PSEUDO < nobch_channel) {
13447 nobch_channel = CHAN_PSEUDO - 1;
13448 }
13449 pvt->channel = nobch_channel;
13450 pvt->span = pri->span;
13451 chan->channel = pvt->channel;
13452
13453 dahdi_nobch_insert(pri, pvt);
13454
13455 return pvt_idx;
13456 }
13457 #endif
13458
13459
13460
13461
13462
13463
13464 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13465 {
13466 struct dahdi_pvt *p;
13467 struct dahdi_bufferinfo bi;
13468 int res;
13469
13470 p = ast_malloc(sizeof(*p));
13471 if (!p) {
13472 return NULL;
13473 }
13474 *p = *src;
13475
13476
13477 p->cc_params = ast_cc_config_params_init();
13478 if (!p->cc_params) {
13479 ast_free(p);
13480 return NULL;
13481 }
13482 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13483
13484 p->which_iflist = DAHDI_IFLIST_NONE;
13485 p->next = NULL;
13486 p->prev = NULL;
13487 ast_mutex_init(&p->lock);
13488 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13489 if (p->subs[SUB_REAL].dfd < 0) {
13490 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13491 destroy_dahdi_pvt(p);
13492 return NULL;
13493 }
13494 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13495 if (!res) {
13496 bi.txbufpolicy = src->buf_policy;
13497 bi.rxbufpolicy = src->buf_policy;
13498 bi.numbufs = src->buf_no;
13499 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13500 if (res < 0) {
13501 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13502 }
13503 } else
13504 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13505 p->destroy = 1;
13506 dahdi_iflist_insert(p);
13507 return p;
13508 }
13509
13510 struct dahdi_starting_point {
13511
13512 ast_group_t groupmatch;
13513
13514 int channelmatch;
13515
13516 int rr_starting_point;
13517
13518 int span;
13519
13520 int cadance;
13521
13522 char opt;
13523
13524 char backwards;
13525
13526 char roundrobin;
13527 };
13528 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13529 {
13530 char *dest;
13531 char *s;
13532 int x;
13533 int res = 0;
13534 struct dahdi_pvt *p;
13535 char *subdir = NULL;
13536 AST_DECLARE_APP_ARGS(args,
13537 AST_APP_ARG(group);
13538
13539
13540 AST_APP_ARG(other);
13541 );
13542
13543
13544
13545
13546
13547
13548
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566 if (data) {
13567 dest = ast_strdupa(data);
13568 } else {
13569 ast_log(LOG_WARNING, "Channel requested with no data\n");
13570 return NULL;
13571 }
13572 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13573 if (!args.argc || ast_strlen_zero(args.group)) {
13574 ast_log(LOG_WARNING, "No channel/group specified\n");
13575 return NULL;
13576 }
13577
13578
13579 memset(param, 0, sizeof(*param));
13580 param->channelmatch = -1;
13581
13582 if (strchr(args.group, '!') != NULL) {
13583 char *prev = args.group;
13584 while ((s = strchr(prev, '!')) != NULL) {
13585 *s++ = '/';
13586 prev = s;
13587 }
13588 *(prev - 1) = '\0';
13589 subdir = args.group;
13590 args.group = prev;
13591 } else if (args.group[0] == 'i') {
13592
13593 res = sscanf(args.group + 1, "%30d", &x);
13594 if (res < 1) {
13595 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13596 return NULL;
13597 }
13598 param->span = x;
13599
13600
13601 s = strchr(args.group, '-');
13602 if (!s) {
13603
13604 return iflist;
13605 }
13606 args.group = s + 1;
13607 res = 0;
13608 }
13609 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13610
13611 s = args.group + 1;
13612 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13613 if (res < 1) {
13614 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13615 return NULL;
13616 }
13617 param->groupmatch = ((ast_group_t) 1 << x);
13618
13619 if (toupper(args.group[0]) == 'G') {
13620 if (args.group[0] == 'G') {
13621 param->backwards = 1;
13622 p = ifend;
13623 } else
13624 p = iflist;
13625 } else {
13626 if (ARRAY_LEN(round_robin) <= x) {
13627 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13628 x, data);
13629 return NULL;
13630 }
13631 if (args.group[0] == 'R') {
13632 param->backwards = 1;
13633 p = round_robin[x] ? round_robin[x]->prev : ifend;
13634 if (!p)
13635 p = ifend;
13636 } else {
13637 p = round_robin[x] ? round_robin[x]->next : iflist;
13638 if (!p)
13639 p = iflist;
13640 }
13641 param->roundrobin = 1;
13642 param->rr_starting_point = x;
13643 }
13644 } else {
13645 s = args.group;
13646 if (!strcasecmp(s, "pseudo")) {
13647
13648 x = CHAN_PSEUDO;
13649 param->channelmatch = x;
13650 } else {
13651 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13652 if (res < 1) {
13653 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13654 return NULL;
13655 } else {
13656 param->channelmatch = x;
13657 }
13658 }
13659 if (subdir) {
13660 char path[PATH_MAX];
13661 struct stat stbuf;
13662
13663 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13664 subdir, param->channelmatch);
13665 if (stat(path, &stbuf) < 0) {
13666 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13667 path, strerror(errno));
13668 return NULL;
13669 }
13670 if (!S_ISCHR(stbuf.st_mode)) {
13671 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13672 path);
13673 return NULL;
13674 }
13675 param->channelmatch = minor(stbuf.st_rdev);
13676 }
13677
13678 p = iflist;
13679 }
13680
13681 if (param->opt == 'r' && res < 3) {
13682 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13683 param->opt = '\0';
13684 }
13685
13686 return p;
13687 }
13688
13689 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13690 {
13691 int callwait = 0;
13692 struct dahdi_pvt *p;
13693 struct ast_channel *tmp = NULL;
13694 struct dahdi_pvt *exitpvt;
13695 int channelmatched = 0;
13696 int groupmatched = 0;
13697 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13698 int transcapdigital = 0;
13699 #endif
13700 struct dahdi_starting_point start;
13701
13702 ast_mutex_lock(&iflock);
13703 p = determine_starting_point(data, &start);
13704 if (!p) {
13705
13706 ast_mutex_unlock(&iflock);
13707 return NULL;
13708 }
13709
13710
13711 exitpvt = p;
13712 while (p && !tmp) {
13713 if (start.roundrobin)
13714 round_robin[start.rr_starting_point] = p;
13715
13716 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13717 && available(&p, channelmatched)) {
13718 ast_debug(1, "Using channel %d\n", p->channel);
13719
13720 callwait = (p->owner != NULL);
13721 #ifdef HAVE_OPENR2
13722 if (p->mfcr2) {
13723 ast_mutex_lock(&p->lock);
13724 if (p->mfcr2call) {
13725 ast_mutex_unlock(&p->lock);
13726 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13727 goto next;
13728 }
13729 p->mfcr2call = 1;
13730 ast_mutex_unlock(&p->lock);
13731 }
13732 #endif
13733 if (p->channel == CHAN_PSEUDO) {
13734 p = duplicate_pseudo(p);
13735 if (!p) {
13736 break;
13737 }
13738 }
13739
13740 p->distinctivering = 0;
13741
13742 switch (start.opt) {
13743 case '\0':
13744
13745 break;
13746 case 'c':
13747
13748 p->confirmanswer = 1;
13749 break;
13750 case 'r':
13751
13752 p->distinctivering = start.cadance;
13753 break;
13754 case 'd':
13755 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13756
13757 transcapdigital = AST_TRANS_CAP_DIGITAL;
13758 #endif
13759 break;
13760 default:
13761 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13762 break;
13763 }
13764
13765 p->outgoing = 1;
13766 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13767 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13768 #ifdef HAVE_PRI
13769 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13770
13771
13772
13773
13774
13775 ast_mutex_lock(&p->lock);
13776 ast_mutex_unlock(&p->lock);
13777
13778 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13779 sizeof(p->dnid));
13780 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13781 #endif
13782 #if defined(HAVE_SS7)
13783 } else if (p->sig == SIG_SS7) {
13784 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13785 #endif
13786 } else {
13787 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13788 }
13789 if (!tmp) {
13790 p->outgoing = 0;
13791 #if defined(HAVE_PRI)
13792 switch (p->sig) {
13793 case SIG_PRI_LIB_HANDLE_CASES:
13794 #if defined(HAVE_PRI_CALL_WAITING)
13795 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13796 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13797 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13798 }
13799 #endif
13800
13801
13802
13803
13804 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13805 break;
13806 default:
13807 break;
13808 }
13809 #endif
13810 } else {
13811 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13812 }
13813 break;
13814 }
13815 #ifdef HAVE_OPENR2
13816 next:
13817 #endif
13818 if (start.backwards) {
13819 p = p->prev;
13820 if (!p)
13821 p = ifend;
13822 } else {
13823 p = p->next;
13824 if (!p)
13825 p = iflist;
13826 }
13827
13828 if (p == exitpvt)
13829 break;
13830 }
13831 ast_mutex_unlock(&iflock);
13832 restart_monitor();
13833 if (cause && !tmp) {
13834 if (callwait || channelmatched) {
13835 *cause = AST_CAUSE_BUSY;
13836 } else if (groupmatched) {
13837 *cause = AST_CAUSE_CONGESTION;
13838 } else {
13839
13840
13841
13842
13843 }
13844 }
13845
13846 return tmp;
13847 }
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859 static int dahdi_devicestate(void *data)
13860 {
13861 #if defined(HAVE_PRI)
13862 char *device;
13863 unsigned span;
13864 int res;
13865
13866 device = data;
13867
13868 if (*device != 'I') {
13869
13870 return AST_DEVICE_UNKNOWN;
13871 }
13872 res = sscanf(device, "I%30u", &span);
13873 if (res != 1 || !span || NUM_SPANS < span) {
13874
13875 return AST_DEVICE_UNKNOWN;
13876 }
13877 device = strchr(device, '/');
13878 if (!device) {
13879
13880 return AST_DEVICE_UNKNOWN;
13881 }
13882
13883
13884
13885
13886
13887 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13888 ++device;
13889 if (!strcmp(device, "congestion"))
13890 #endif
13891 {
13892 return pris[span - 1].pri.congestion_devstate;
13893 }
13894 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13895 else if (!strcmp(device, "threshold")) {
13896 return pris[span - 1].pri.threshold_devstate;
13897 }
13898 return AST_DEVICE_UNKNOWN;
13899 #endif
13900 #else
13901 return AST_DEVICE_UNKNOWN;
13902 #endif
13903 }
13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918
13919
13920
13921 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13922 {
13923 struct dahdi_pvt *p;
13924 struct dahdi_pvt *exitpvt;
13925 struct dahdi_starting_point start;
13926 int groupmatched = 0;
13927 int channelmatched = 0;
13928
13929 ast_mutex_lock(&iflock);
13930 p = determine_starting_point(dest, &start);
13931 if (!p) {
13932 ast_mutex_unlock(&iflock);
13933 return -1;
13934 }
13935 exitpvt = p;
13936 for (;;) {
13937 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13938
13939 struct ast_str *device_name;
13940 char *dash;
13941 const char *monitor_type;
13942 char dialstring[AST_CHANNEL_NAME];
13943 char full_device_name[AST_CHANNEL_NAME];
13944
13945 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13946 case AST_CC_MONITOR_NEVER:
13947 break;
13948 case AST_CC_MONITOR_NATIVE:
13949 case AST_CC_MONITOR_ALWAYS:
13950 case AST_CC_MONITOR_GENERIC:
13951 #if defined(HAVE_PRI)
13952 if (dahdi_sig_pri_lib_handles(p->sig)) {
13953
13954
13955
13956
13957 snprintf(full_device_name, sizeof(full_device_name),
13958 "DAHDI/I%d/congestion", p->pri->span);
13959 } else
13960 #endif
13961 {
13962 #if defined(HAVE_PRI)
13963 device_name = create_channel_name(p, 1, "");
13964 #else
13965 device_name = create_channel_name(p);
13966 #endif
13967 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13968 device_name ? ast_str_buffer(device_name) : "");
13969 ast_free(device_name);
13970
13971
13972
13973
13974
13975 dash = strrchr(full_device_name, '-');
13976 if (dash) {
13977 *dash = '\0';
13978 }
13979 }
13980 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13981
13982
13983
13984
13985
13986
13987
13988 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13989 callback(inbound,
13990 #if defined(HAVE_PRI)
13991 p->pri ? p->pri->cc_params : p->cc_params,
13992 #else
13993 p->cc_params,
13994 #endif
13995 monitor_type, full_device_name, dialstring, NULL);
13996 break;
13997 }
13998 }
13999 p = start.backwards ? p->prev : p->next;
14000 if (!p) {
14001 p = start.backwards ? ifend : iflist;
14002 }
14003 if (p == exitpvt) {
14004 break;
14005 }
14006 }
14007 ast_mutex_unlock(&iflock);
14008 return 0;
14009 }
14010
14011 #if defined(HAVE_SS7)
14012 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
14013 {
14014 int i;
14015
14016 if (ss7) {
14017 for (i = 0; i < NUM_SPANS; i++) {
14018 if (linksets[i].ss7.ss7 == ss7) {
14019 ast_verbose("[%d] %s", i + 1, s);
14020 return;
14021 }
14022 }
14023 }
14024 ast_verbose("%s", s);
14025 }
14026 #endif
14027
14028 #if defined(HAVE_SS7)
14029 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
14030 {
14031 int i;
14032
14033 if (ss7) {
14034 for (i = 0; i < NUM_SPANS; i++) {
14035 if (linksets[i].ss7.ss7 == ss7) {
14036 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
14037 return;
14038 }
14039 }
14040 }
14041 ast_log(LOG_ERROR, "%s", s);
14042 }
14043 #endif
14044
14045 #if defined(HAVE_OPENR2)
14046 static void *mfcr2_monitor(void *data)
14047 {
14048 struct dahdi_mfcr2 *mfcr2 = data;
14049
14050
14051
14052
14053
14054 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
14055 int res = 0;
14056 int i = 0;
14057 int oldstate = 0;
14058 int quit_loop = 0;
14059 int maxsleep = 20;
14060 int was_idle = 0;
14061 int pollsize = 0;
14062
14063
14064 for (i = 0; i < mfcr2->numchans; i++) {
14065 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14066 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14067 }
14068 while (1) {
14069
14070
14071 pollsize = 0;
14072 for (i = 0; i < mfcr2->numchans; i++) {
14073 pollers[i].revents = 0;
14074 pollers[i].events = 0;
14075 if (mfcr2->pvts[i]->owner) {
14076 continue;
14077 }
14078 if (!mfcr2->pvts[i]->r2chan) {
14079 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14080 quit_loop = 1;
14081 break;
14082 }
14083 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14084 pollers[i].events = POLLIN | POLLPRI;
14085 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14086 pollsize++;
14087 }
14088 if (quit_loop) {
14089 break;
14090 }
14091 if (pollsize == 0) {
14092 if (!was_idle) {
14093 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14094 was_idle = 1;
14095 }
14096 poll(NULL, 0, maxsleep);
14097 continue;
14098 }
14099 was_idle = 0;
14100
14101
14102 pthread_testcancel();
14103 res = poll(pollers, mfcr2->numchans, maxsleep);
14104 pthread_testcancel();
14105 if ((res < 0) && (errno != EINTR)) {
14106 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14107 break;
14108 }
14109
14110 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14111 for (i = 0; i < mfcr2->numchans; i++) {
14112 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14113 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14114 }
14115 }
14116 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14117 }
14118 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14119 return 0;
14120 }
14121 #endif
14122
14123 #if defined(HAVE_PRI)
14124 static void dahdi_pri_message(struct pri *pri, char *s)
14125 {
14126 int x;
14127 int y;
14128 int dchan = -1;
14129 int span = -1;
14130 int dchancount = 0;
14131
14132 if (pri) {
14133 for (x = 0; x < NUM_SPANS; x++) {
14134 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14135 if (pris[x].pri.dchans[y]) {
14136 dchancount++;
14137 }
14138
14139 if (pris[x].pri.dchans[y] == pri) {
14140 dchan = y;
14141 }
14142 }
14143 if (dchan >= 0) {
14144 span = x;
14145 break;
14146 }
14147 dchancount = 0;
14148 }
14149 if (-1 < span) {
14150 if (1 < dchancount) {
14151 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14152 } else {
14153 ast_verbose("PRI Span: %d %s", span + 1, s);
14154 }
14155 } else {
14156 ast_verbose("PRI Span: ? %s", s);
14157 }
14158 } else {
14159 ast_verbose("PRI Span: ? %s", s);
14160 }
14161
14162 ast_mutex_lock(&pridebugfdlock);
14163
14164 if (pridebugfd >= 0) {
14165 if (write(pridebugfd, s, strlen(s)) < 0) {
14166 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14167 }
14168 }
14169
14170 ast_mutex_unlock(&pridebugfdlock);
14171 }
14172 #endif
14173
14174 #if defined(HAVE_PRI)
14175 static void dahdi_pri_error(struct pri *pri, char *s)
14176 {
14177 int x;
14178 int y;
14179 int dchan = -1;
14180 int span = -1;
14181 int dchancount = 0;
14182
14183 if (pri) {
14184 for (x = 0; x < NUM_SPANS; x++) {
14185 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14186 if (pris[x].pri.dchans[y]) {
14187 dchancount++;
14188 }
14189
14190 if (pris[x].pri.dchans[y] == pri) {
14191 dchan = y;
14192 }
14193 }
14194 if (dchan >= 0) {
14195 span = x;
14196 break;
14197 }
14198 dchancount = 0;
14199 }
14200 if (-1 < span) {
14201 if (1 < dchancount) {
14202 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14203 } else {
14204 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14205 }
14206 } else {
14207 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14208 }
14209 } else {
14210 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14211 }
14212
14213 ast_mutex_lock(&pridebugfdlock);
14214
14215 if (pridebugfd >= 0) {
14216 if (write(pridebugfd, s, strlen(s)) < 0) {
14217 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14218 }
14219 }
14220
14221 ast_mutex_unlock(&pridebugfdlock);
14222 }
14223 #endif
14224
14225 #if defined(HAVE_PRI)
14226 static int prepare_pri(struct dahdi_pri *pri)
14227 {
14228 int i, res, x;
14229 struct dahdi_params p;
14230 struct dahdi_bufferinfo bi;
14231 struct dahdi_spaninfo si;
14232
14233 pri->pri.calls = &dahdi_pri_callbacks;
14234
14235 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14236 if (!pri->dchannels[i])
14237 break;
14238 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14239 x = pri->dchannels[i];
14240 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14241 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14242 return -1;
14243 }
14244 memset(&p, 0, sizeof(p));
14245 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14246 if (res) {
14247 dahdi_close_pri_fd(pri, i);
14248 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14249 return -1;
14250 }
14251 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14252 dahdi_close_pri_fd(pri, i);
14253 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14254 return -1;
14255 }
14256 memset(&si, 0, sizeof(si));
14257 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14258 if (res) {
14259 dahdi_close_pri_fd(pri, i);
14260 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14261 }
14262 if (!si.alarms) {
14263 pri_event_noalarm(&pri->pri, i, 1);
14264 } else {
14265 pri_event_alarm(&pri->pri, i, 1);
14266 }
14267 memset(&bi, 0, sizeof(bi));
14268 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14269 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14270 bi.numbufs = 32;
14271 bi.bufsize = 1024;
14272 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14273 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14274 dahdi_close_pri_fd(pri, i);
14275 return -1;
14276 }
14277 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14278 }
14279 return 0;
14280 }
14281 #endif
14282
14283 #if defined(HAVE_PRI)
14284 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14285 {
14286 int which, span;
14287 char *ret = NULL;
14288
14289 if (pos != rpos)
14290 return ret;
14291
14292 for (which = span = 0; span < NUM_SPANS; span++) {
14293 if (pris[span].pri.pri && ++which > state) {
14294 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14295 ret = NULL;
14296 }
14297 break;
14298 }
14299 }
14300 return ret;
14301 }
14302 #endif
14303
14304 #if defined(HAVE_PRI)
14305 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14306 {
14307 return complete_span_helper(line,word,pos,state,3);
14308 }
14309 #endif
14310
14311 #if defined(HAVE_PRI)
14312 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14313 {
14314 int myfd;
14315 switch (cmd) {
14316 case CLI_INIT:
14317 e->command = "pri set debug file";
14318 e->usage = "Usage: pri set debug file [output-file]\n"
14319 " Sends PRI debug output to the specified output file\n";
14320 return NULL;
14321 case CLI_GENERATE:
14322 return NULL;
14323 }
14324 if (a->argc < 5)
14325 return CLI_SHOWUSAGE;
14326
14327 if (ast_strlen_zero(a->argv[4]))
14328 return CLI_SHOWUSAGE;
14329
14330 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14331 if (myfd < 0) {
14332 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14333 return CLI_SUCCESS;
14334 }
14335
14336 ast_mutex_lock(&pridebugfdlock);
14337
14338 if (pridebugfd >= 0)
14339 close(pridebugfd);
14340
14341 pridebugfd = myfd;
14342 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14343 ast_mutex_unlock(&pridebugfdlock);
14344 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14345 return CLI_SUCCESS;
14346 }
14347 #endif
14348
14349 #if defined(HAVE_PRI)
14350 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14351 {
14352 int span;
14353 int x;
14354 int level = 0;
14355 switch (cmd) {
14356 case CLI_INIT:
14357 e->command = "pri set debug {on|off|0|1|2} span";
14358 e->usage =
14359 "Usage: pri set debug {<level>|on|off} span <span>\n"
14360 " Enables debugging on a given PRI span\n";
14361 return NULL;
14362 case CLI_GENERATE:
14363 return complete_span_4(a->line, a->word, a->pos, a->n);
14364 }
14365 if (a->argc < 6) {
14366 return CLI_SHOWUSAGE;
14367 }
14368
14369 if (!strcasecmp(a->argv[3], "on")) {
14370 level = 1;
14371 } else if (!strcasecmp(a->argv[3], "off")) {
14372 level = 0;
14373 } else {
14374 level = atoi(a->argv[3]);
14375 }
14376 span = atoi(a->argv[5]);
14377 if ((span < 1) || (span > NUM_SPANS)) {
14378 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14379 return CLI_SUCCESS;
14380 }
14381 if (!pris[span-1].pri.pri) {
14382 ast_cli(a->fd, "No PRI running on span %d\n", span);
14383 return CLI_SUCCESS;
14384 }
14385
14386
14387 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14388 if (pris[span - 1].pri.dchans[x]) {
14389 switch (level) {
14390 case 0:
14391 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14392 break;
14393 case 1:
14394 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14395 break;
14396 default:
14397 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14398 break;
14399 }
14400 }
14401 }
14402 if (level == 0) {
14403
14404 ast_mutex_lock(&pridebugfdlock);
14405 if (0 <= pridebugfd) {
14406 close(pridebugfd);
14407 pridebugfd = -1;
14408 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14409 pridebugfilename);
14410 }
14411 ast_mutex_unlock(&pridebugfdlock);
14412 }
14413 pris[span - 1].pri.debug = (level) ? 1 : 0;
14414 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14415 return CLI_SUCCESS;
14416 }
14417 #endif
14418
14419 #if defined(HAVE_PRI)
14420 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14421 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14422 {
14423 unsigned *why;
14424 int channel;
14425 int trunkgroup;
14426 int x, y, fd = a->fd;
14427 int interfaceid = 0;
14428 char db_chan_name[20], db_answer[5];
14429 struct dahdi_pvt *tmp;
14430 struct dahdi_pri *pri;
14431
14432 if (a->argc < 5 || a->argc > 6)
14433 return CLI_SHOWUSAGE;
14434 if (strchr(a->argv[4], ':')) {
14435 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14436 return CLI_SHOWUSAGE;
14437 if ((trunkgroup < 1) || (channel < 1))
14438 return CLI_SHOWUSAGE;
14439 pri = NULL;
14440 for (x=0;x<NUM_SPANS;x++) {
14441 if (pris[x].pri.trunkgroup == trunkgroup) {
14442 pri = pris + x;
14443 break;
14444 }
14445 }
14446 if (!pri) {
14447 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14448 return CLI_FAILURE;
14449 }
14450 } else
14451 channel = atoi(a->argv[4]);
14452
14453 if (a->argc == 6)
14454 interfaceid = atoi(a->argv[5]);
14455
14456
14457 for (x = 0; x < NUM_SPANS; x++) {
14458 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14459 if (pris[x].dchannels[y] == channel) {
14460 pri = pris + x;
14461 if (pri->pri.enable_service_message_support) {
14462 ast_mutex_lock(&pri->pri.lock);
14463 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14464 ast_mutex_unlock(&pri->pri.lock);
14465 } else {
14466 ast_cli(fd,
14467 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14468 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14469 }
14470 return CLI_SUCCESS;
14471 }
14472 }
14473 }
14474
14475
14476 ast_mutex_lock(&iflock);
14477 for (tmp = iflist; tmp; tmp = tmp->next) {
14478 if (tmp->pri && tmp->channel == channel) {
14479 ast_mutex_unlock(&iflock);
14480 ast_mutex_lock(&tmp->pri->lock);
14481 if (!tmp->pri->enable_service_message_support) {
14482 ast_mutex_unlock(&tmp->pri->lock);
14483 ast_cli(fd,
14484 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14485 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14486 return CLI_SUCCESS;
14487 }
14488 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14489 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14490 switch(changestatus) {
14491 case 0:
14492
14493 ast_db_del(db_chan_name, SRVST_DBKEY);
14494 *why &= ~SRVST_NEAREND;
14495 if (*why) {
14496 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14497 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14498 } else {
14499 dahdi_pri_update_span_devstate(tmp->pri);
14500 }
14501 break;
14502
14503 case 2:
14504
14505 ast_db_del(db_chan_name, SRVST_DBKEY);
14506 *why |= SRVST_NEAREND;
14507 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14508 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14509 dahdi_pri_update_span_devstate(tmp->pri);
14510 break;
14511
14512
14513 default:
14514 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14515 break;
14516 }
14517 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14518 ast_mutex_unlock(&tmp->pri->lock);
14519 return CLI_SUCCESS;
14520 }
14521 }
14522 ast_mutex_unlock(&iflock);
14523
14524 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14525 return CLI_FAILURE;
14526 }
14527
14528 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14529 {
14530 switch (cmd) {
14531 case CLI_INIT:
14532 e->command = "pri service enable channel";
14533 e->usage =
14534 "Usage: pri service enable channel <channel> [<interface id>]\n"
14535 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14536 " to restore a channel to service, with optional interface id\n"
14537 " as agreed upon with remote switch operator\n";
14538 return NULL;
14539 case CLI_GENERATE:
14540 return NULL;
14541 }
14542 return handle_pri_service_generic(e, cmd, a, 0);
14543 }
14544
14545 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14546 {
14547 switch (cmd) {
14548 case CLI_INIT:
14549 e->command = "pri service disable channel";
14550 e->usage =
14551 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14552 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14553 " to remove a channel from service, with optional interface id\n"
14554 " as agreed upon with remote switch operator\n";
14555 return NULL;
14556 case CLI_GENERATE:
14557 return NULL;
14558 }
14559 return handle_pri_service_generic(e, cmd, a, 2);
14560 }
14561 #endif
14562 #endif
14563
14564 #if defined(HAVE_PRI)
14565 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14566 {
14567 int span;
14568
14569 switch (cmd) {
14570 case CLI_INIT:
14571 e->command = "pri show channels";
14572 e->usage =
14573 "Usage: pri show channels\n"
14574 " Displays PRI channel information such as the current mapping\n"
14575 " of DAHDI B channels to Asterisk channel names and which calls\n"
14576 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14577 " are not associated with any B channel.\n";
14578 return NULL;
14579 case CLI_GENERATE:
14580 return NULL;
14581 }
14582
14583 if (a->argc != 3)
14584 return CLI_SHOWUSAGE;
14585
14586 sig_pri_cli_show_channels_header(a->fd);
14587 for (span = 0; span < NUM_SPANS; ++span) {
14588 if (pris[span].pri.pri) {
14589 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14590 }
14591 }
14592 return CLI_SUCCESS;
14593 }
14594 #endif
14595
14596 #if defined(HAVE_PRI)
14597 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14598 {
14599 int span;
14600
14601 switch (cmd) {
14602 case CLI_INIT:
14603 e->command = "pri show spans";
14604 e->usage =
14605 "Usage: pri show spans\n"
14606 " Displays PRI span information\n";
14607 return NULL;
14608 case CLI_GENERATE:
14609 return NULL;
14610 }
14611
14612 if (a->argc != 3)
14613 return CLI_SHOWUSAGE;
14614
14615 for (span = 0; span < NUM_SPANS; span++) {
14616 if (pris[span].pri.pri) {
14617 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14618 }
14619 }
14620 return CLI_SUCCESS;
14621 }
14622 #endif
14623
14624 #if defined(HAVE_PRI)
14625 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14626 {
14627 int span;
14628
14629 switch (cmd) {
14630 case CLI_INIT:
14631 e->command = "pri show span";
14632 e->usage =
14633 "Usage: pri show span <span>\n"
14634 " Displays PRI Information on a given PRI span\n";
14635 return NULL;
14636 case CLI_GENERATE:
14637 return complete_span_4(a->line, a->word, a->pos, a->n);
14638 }
14639
14640 if (a->argc < 4)
14641 return CLI_SHOWUSAGE;
14642 span = atoi(a->argv[3]);
14643 if ((span < 1) || (span > NUM_SPANS)) {
14644 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14645 return CLI_SUCCESS;
14646 }
14647 if (!pris[span-1].pri.pri) {
14648 ast_cli(a->fd, "No PRI running on span %d\n", span);
14649 return CLI_SUCCESS;
14650 }
14651
14652 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14653
14654 return CLI_SUCCESS;
14655 }
14656 #endif
14657
14658 #if defined(HAVE_PRI)
14659 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14660 {
14661 int x;
14662 int span;
14663 int count=0;
14664 int debug;
14665
14666 switch (cmd) {
14667 case CLI_INIT:
14668 e->command = "pri show debug";
14669 e->usage =
14670 "Usage: pri show debug\n"
14671 " Show the debug state of pri spans\n";
14672 return NULL;
14673 case CLI_GENERATE:
14674 return NULL;
14675 }
14676
14677 for (span = 0; span < NUM_SPANS; span++) {
14678 if (pris[span].pri.pri) {
14679 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14680 if (pris[span].pri.dchans[x]) {
14681 debug = pri_get_debug(pris[span].pri.dchans[x]);
14682 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" );
14683 count++;
14684 }
14685 }
14686 }
14687
14688 }
14689 ast_mutex_lock(&pridebugfdlock);
14690 if (pridebugfd >= 0)
14691 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14692 ast_mutex_unlock(&pridebugfdlock);
14693
14694 if (!count)
14695 ast_cli(a->fd, "No PRI running\n");
14696 return CLI_SUCCESS;
14697 }
14698 #endif
14699
14700 #if defined(HAVE_PRI)
14701 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14702 {
14703 switch (cmd) {
14704 case CLI_INIT:
14705 e->command = "pri show version";
14706 e->usage =
14707 "Usage: pri show version\n"
14708 "Show libpri version information\n";
14709 return NULL;
14710 case CLI_GENERATE:
14711 return NULL;
14712 }
14713
14714 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14715
14716 return CLI_SUCCESS;
14717 }
14718 #endif
14719
14720 #if defined(HAVE_PRI)
14721 static struct ast_cli_entry dahdi_pri_cli[] = {
14722 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14723 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14724 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14725 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14726 #endif
14727 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14728 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14729 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14730 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14731 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14732 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14733 };
14734 #endif
14735
14736 #ifdef HAVE_OPENR2
14737
14738 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14739 {
14740 switch (cmd) {
14741 case CLI_INIT:
14742 e->command = "mfcr2 show version";
14743 e->usage =
14744 "Usage: mfcr2 show version\n"
14745 " Shows the version of the OpenR2 library being used.\n";
14746 return NULL;
14747 case CLI_GENERATE:
14748 return NULL;
14749 }
14750 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14751 return CLI_SUCCESS;
14752 }
14753
14754 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14755 {
14756 #define FORMAT "%4s %40s\n"
14757 int i = 0;
14758 int numvariants = 0;
14759 const openr2_variant_entry_t *variants;
14760 switch (cmd) {
14761 case CLI_INIT:
14762 e->command = "mfcr2 show variants";
14763 e->usage =
14764 "Usage: mfcr2 show variants\n"
14765 " Shows the list of MFC/R2 variants supported.\n";
14766 return NULL;
14767 case CLI_GENERATE:
14768 return NULL;
14769 }
14770 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14771 ast_cli(a->fd, "Failed to get list of variants.\n");
14772 return CLI_FAILURE;
14773 }
14774 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14775 for (i = 0; i < numvariants; i++) {
14776 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14777 }
14778 return CLI_SUCCESS;
14779 #undef FORMAT
14780 }
14781
14782 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14783 {
14784 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14785 int filtertype = 0;
14786 int targetnum = 0;
14787 char channo[5];
14788 char anino[5];
14789 char dnisno[5];
14790 struct dahdi_pvt *p;
14791 openr2_context_t *r2context;
14792 openr2_variant_t r2variant;
14793 switch (cmd) {
14794 case CLI_INIT:
14795 e->command = "mfcr2 show channels [group|context]";
14796 e->usage =
14797 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14798 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14799 return NULL;
14800 case CLI_GENERATE:
14801 return NULL;
14802 }
14803 if (!((a->argc == 3) || (a->argc == 5))) {
14804 return CLI_SHOWUSAGE;
14805 }
14806 if (a->argc == 5) {
14807 if (!strcasecmp(a->argv[3], "group")) {
14808 targetnum = atoi(a->argv[4]);
14809 if ((targetnum < 0) || (targetnum > 63))
14810 return CLI_SHOWUSAGE;
14811 targetnum = 1 << targetnum;
14812 filtertype = 1;
14813 } else if (!strcasecmp(a->argv[3], "context")) {
14814 filtertype = 2;
14815 } else {
14816 return CLI_SHOWUSAGE;
14817 }
14818 }
14819 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14820 ast_mutex_lock(&iflock);
14821 for (p = iflist; p; p = p->next) {
14822 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14823 continue;
14824 }
14825 if (filtertype) {
14826 switch(filtertype) {
14827 case 1:
14828 if (p->group != targetnum) {
14829 continue;
14830 }
14831 break;
14832 case 2:
14833 if (strcasecmp(p->context, a->argv[4])) {
14834 continue;
14835 }
14836 break;
14837 default:
14838 ;
14839 }
14840 }
14841 r2context = openr2_chan_get_context(p->r2chan);
14842 r2variant = openr2_context_get_variant(r2context);
14843 snprintf(channo, sizeof(channo), "%d", p->channel);
14844 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14845 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14846 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14847 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14848 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14849 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14850 }
14851 ast_mutex_unlock(&iflock);
14852 return CLI_SUCCESS;
14853 #undef FORMAT
14854 }
14855
14856 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14857 {
14858 struct dahdi_pvt *p = NULL;
14859 int channo = 0;
14860 char *toklevel = NULL;
14861 char *saveptr = NULL;
14862 char *logval = NULL;
14863 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14864 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14865 switch (cmd) {
14866 case CLI_INIT:
14867 e->command = "mfcr2 set debug";
14868 e->usage =
14869 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14870 " Set a new logging level for the specified channel.\n"
14871 " If no channel is specified the logging level will be applied to all channels.\n";
14872 return NULL;
14873 case CLI_GENERATE:
14874 return NULL;
14875 }
14876 if (a->argc < 4) {
14877 return CLI_SHOWUSAGE;
14878 }
14879 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14880 logval = ast_strdupa(a->argv[3]);
14881 toklevel = strtok_r(logval, ",", &saveptr);
14882 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14883 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14884 return CLI_FAILURE;
14885 } else if (OR2_LOG_NOTHING == tmplevel) {
14886 loglevel = tmplevel;
14887 } else {
14888 loglevel |= tmplevel;
14889 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14890 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14891 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14892 continue;
14893 }
14894 loglevel |= tmplevel;
14895 }
14896 }
14897 ast_mutex_lock(&iflock);
14898 for (p = iflist; p; p = p->next) {
14899 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14900 continue;
14901 }
14902 if ((channo != -1) && (p->channel != channo )) {
14903 continue;
14904 }
14905 openr2_chan_set_log_level(p->r2chan, loglevel);
14906 if (channo != -1) {
14907 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14908 break;
14909 }
14910 }
14911 if ((channo != -1) && !p) {
14912 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14913 }
14914 if (channo == -1) {
14915 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14916 }
14917 ast_mutex_unlock(&iflock);
14918 return CLI_SUCCESS;
14919 }
14920
14921 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14922 {
14923 struct dahdi_pvt *p = NULL;
14924 int channo = 0;
14925 switch (cmd) {
14926 case CLI_INIT:
14927 e->command = "mfcr2 call files [on|off]";
14928 e->usage =
14929 "Usage: mfcr2 call files [on|off] <channel>\n"
14930 " Enable call files creation on the specified channel.\n"
14931 " If no channel is specified call files creation policy will be applied to all channels.\n";
14932 return NULL;
14933 case CLI_GENERATE:
14934 return NULL;
14935 }
14936 if (a->argc < 4) {
14937 return CLI_SHOWUSAGE;
14938 }
14939 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14940 ast_mutex_lock(&iflock);
14941 for (p = iflist; p; p = p->next) {
14942 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14943 continue;
14944 }
14945 if ((channo != -1) && (p->channel != channo )) {
14946 continue;
14947 }
14948 if (ast_true(a->argv[3])) {
14949 openr2_chan_enable_call_files(p->r2chan);
14950 } else {
14951 openr2_chan_disable_call_files(p->r2chan);
14952 }
14953 if (channo != -1) {
14954 if (ast_true(a->argv[3])) {
14955 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14956 } else {
14957 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14958 }
14959 break;
14960 }
14961 }
14962 if ((channo != -1) && !p) {
14963 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14964 }
14965 if (channo == -1) {
14966 if (ast_true(a->argv[3])) {
14967 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14968 } else {
14969 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14970 }
14971 }
14972 ast_mutex_unlock(&iflock);
14973 return CLI_SUCCESS;
14974 }
14975
14976 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14977 {
14978 struct dahdi_pvt *p = NULL;
14979 int channo = 0;
14980 switch (cmd) {
14981 case CLI_INIT:
14982 e->command = "mfcr2 set idle";
14983 e->usage =
14984 "Usage: mfcr2 set idle <channel>\n"
14985 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14986 " Force the given channel into IDLE state.\n"
14987 " If no channel is specified, all channels will be set to IDLE.\n";
14988 return NULL;
14989 case CLI_GENERATE:
14990 return NULL;
14991 }
14992 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14993 ast_mutex_lock(&iflock);
14994 for (p = iflist; p; p = p->next) {
14995 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14996 continue;
14997 }
14998 if ((channo != -1) && (p->channel != channo )) {
14999 continue;
15000 }
15001 openr2_chan_set_idle(p->r2chan);
15002 ast_mutex_lock(&p->lock);
15003 p->locallyblocked = 0;
15004 p->mfcr2call = 0;
15005 ast_mutex_unlock(&p->lock);
15006 if (channo != -1) {
15007 break;
15008 }
15009 }
15010 if ((channo != -1) && !p) {
15011 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15012 }
15013 ast_mutex_unlock(&iflock);
15014 return CLI_SUCCESS;
15015 }
15016
15017 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15018 {
15019 struct dahdi_pvt *p = NULL;
15020 int channo = 0;
15021 switch (cmd) {
15022 case CLI_INIT:
15023 e->command = "mfcr2 set blocked";
15024 e->usage =
15025 "Usage: mfcr2 set blocked <channel>\n"
15026 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
15027 " Force the given channel into BLOCKED state.\n"
15028 " If no channel is specified, all channels will be set to BLOCKED.\n";
15029 return NULL;
15030 case CLI_GENERATE:
15031 return NULL;
15032 }
15033 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
15034 ast_mutex_lock(&iflock);
15035 for (p = iflist; p; p = p->next) {
15036 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
15037 continue;
15038 }
15039 if ((channo != -1) && (p->channel != channo )) {
15040 continue;
15041 }
15042 openr2_chan_set_blocked(p->r2chan);
15043 ast_mutex_lock(&p->lock);
15044 p->locallyblocked = 1;
15045 ast_mutex_unlock(&p->lock);
15046 if (channo != -1) {
15047 break;
15048 }
15049 }
15050 if ((channo != -1) && !p) {
15051 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
15052 }
15053 ast_mutex_unlock(&iflock);
15054 return CLI_SUCCESS;
15055 }
15056
15057 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15058 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15059 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15060 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15061 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15062 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15063 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15064 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15065 };
15066
15067 #endif
15068
15069 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15070 {
15071 int channel;
15072 int ret;
15073 switch (cmd) {
15074 case CLI_INIT:
15075 e->command = "dahdi destroy channel";
15076 e->usage =
15077 "Usage: dahdi destroy channel <chan num>\n"
15078 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15079 return NULL;
15080 case CLI_GENERATE:
15081 return NULL;
15082 }
15083 if (a->argc != 4)
15084 return CLI_SHOWUSAGE;
15085
15086 channel = atoi(a->argv[3]);
15087 ret = dahdi_destroy_channel_bynum(channel);
15088 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15089 }
15090
15091 static void dahdi_softhangup_all(void)
15092 {
15093 struct dahdi_pvt *p;
15094 retry:
15095 ast_mutex_lock(&iflock);
15096 for (p = iflist; p; p = p->next) {
15097 ast_mutex_lock(&p->lock);
15098 if (p->owner && !p->restartpending) {
15099 if (ast_channel_trylock(p->owner)) {
15100 if (option_debug > 2)
15101 ast_verbose("Avoiding deadlock\n");
15102
15103 ast_mutex_unlock(&p->lock);
15104 ast_mutex_unlock(&iflock);
15105 goto retry;
15106 }
15107 if (option_debug > 2)
15108 ast_verbose("Softhanging up on %s\n", p->owner->name);
15109 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15110 p->restartpending = 1;
15111 num_restart_pending++;
15112 ast_channel_unlock(p->owner);
15113 }
15114 ast_mutex_unlock(&p->lock);
15115 }
15116 ast_mutex_unlock(&iflock);
15117 }
15118
15119 static int setup_dahdi(int reload);
15120 static int dahdi_restart(void)
15121 {
15122 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15123 int i, j;
15124 #endif
15125 int cancel_code;
15126 struct dahdi_pvt *p;
15127
15128 ast_mutex_lock(&restart_lock);
15129 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15130 dahdi_softhangup_all();
15131 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15132 #ifdef HAVE_OPENR2
15133 dahdi_r2_destroy_links();
15134 #endif
15135
15136 #if defined(HAVE_PRI)
15137 for (i = 0; i < NUM_SPANS; i++) {
15138 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15139 cancel_code = pthread_cancel(pris[i].pri.master);
15140 pthread_kill(pris[i].pri.master, SIGURG);
15141 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);
15142 pthread_join(pris[i].pri.master, NULL);
15143 ast_debug(4, "Joined thread of span %d\n", i);
15144 }
15145 }
15146 #endif
15147
15148 #if defined(HAVE_SS7)
15149 for (i = 0; i < NUM_SPANS; i++) {
15150 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15151 cancel_code = pthread_cancel(linksets[i].ss7.master);
15152 pthread_kill(linksets[i].ss7.master, SIGURG);
15153 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);
15154 pthread_join(linksets[i].ss7.master, NULL);
15155 ast_debug(4, "Joined thread of span %d\n", i);
15156 }
15157 }
15158 #endif
15159
15160 ast_mutex_lock(&monlock);
15161 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15162 cancel_code = pthread_cancel(monitor_thread);
15163 pthread_kill(monitor_thread, SIGURG);
15164 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15165 pthread_join(monitor_thread, NULL);
15166 ast_debug(4, "Joined monitor thread\n");
15167 }
15168 monitor_thread = AST_PTHREADT_NULL;
15169
15170 ast_mutex_lock(&ss_thread_lock);
15171 while (ss_thread_count > 0) {
15172 int x = DAHDI_FLASH;
15173 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15174
15175 ast_mutex_lock(&iflock);
15176 for (p = iflist; p; p = p->next) {
15177 if (p->owner) {
15178
15179 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15180 }
15181 }
15182 ast_mutex_unlock(&iflock);
15183 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15184 }
15185
15186
15187 dahdi_softhangup_all();
15188 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15189 destroy_all_channels();
15190 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15191
15192 ast_mutex_unlock(&monlock);
15193
15194 #ifdef HAVE_PRI
15195 for (i = 0; i < NUM_SPANS; i++) {
15196 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15197 dahdi_close_pri_fd(&(pris[i]), j);
15198 }
15199
15200 memset(pris, 0, sizeof(pris));
15201 for (i = 0; i < NUM_SPANS; i++) {
15202 sig_pri_init_pri(&pris[i].pri);
15203 }
15204 pri_set_error(dahdi_pri_error);
15205 pri_set_message(dahdi_pri_message);
15206 #endif
15207 #if defined(HAVE_SS7)
15208 for (i = 0; i < NUM_SPANS; i++) {
15209 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15210 dahdi_close_ss7_fd(&(linksets[i]), j);
15211 }
15212
15213 memset(linksets, 0, sizeof(linksets));
15214 for (i = 0; i < NUM_SPANS; i++) {
15215 sig_ss7_init_linkset(&linksets[i].ss7);
15216 }
15217 ss7_set_error(dahdi_ss7_error);
15218 ss7_set_message(dahdi_ss7_message);
15219 #endif
15220
15221 if (setup_dahdi(2) != 0) {
15222 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15223 ast_mutex_unlock(&ss_thread_lock);
15224 return 1;
15225 }
15226 ast_mutex_unlock(&ss_thread_lock);
15227 ast_mutex_unlock(&restart_lock);
15228 return 0;
15229 }
15230
15231 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15232 {
15233 switch (cmd) {
15234 case CLI_INIT:
15235 e->command = "dahdi restart";
15236 e->usage =
15237 "Usage: dahdi restart\n"
15238 " Restarts the DAHDI channels: destroys them all and then\n"
15239 " re-reads them from chan_dahdi.conf.\n"
15240 " Note that this will STOP any running CALL on DAHDI channels.\n"
15241 "";
15242 return NULL;
15243 case CLI_GENERATE:
15244 return NULL;
15245 }
15246 if (a->argc != 2)
15247 return CLI_SHOWUSAGE;
15248
15249 if (dahdi_restart() != 0)
15250 return CLI_FAILURE;
15251 return CLI_SUCCESS;
15252 }
15253
15254 static int action_dahdirestart(struct mansession *s, const struct message *m)
15255 {
15256 if (dahdi_restart() != 0) {
15257 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15258 return 1;
15259 }
15260 astman_send_ack(s, m, "DAHDIRestart: Success");
15261 return 0;
15262 }
15263
15264 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15265 {
15266 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15267 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15268 ast_group_t targetnum = 0;
15269 int filtertype = 0;
15270 struct dahdi_pvt *tmp = NULL;
15271 char tmps[20] = "";
15272 char statestr[20] = "";
15273 char blockstr[20] = "";
15274
15275 switch (cmd) {
15276 case CLI_INIT:
15277 e->command = "dahdi show channels [group|context]";
15278 e->usage =
15279 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15280 " Shows a list of available channels with optional filtering\n"
15281 " <group> must be a number between 0 and 63\n";
15282 return NULL;
15283 case CLI_GENERATE:
15284 return NULL;
15285 }
15286
15287
15288
15289 if (!((a->argc == 3) || (a->argc == 5)))
15290 return CLI_SHOWUSAGE;
15291
15292 if (a->argc == 5) {
15293 if (!strcasecmp(a->argv[3], "group")) {
15294 targetnum = atoi(a->argv[4]);
15295 if (63 < targetnum) {
15296 return CLI_SHOWUSAGE;
15297 }
15298 targetnum = ((ast_group_t) 1) << targetnum;
15299 filtertype = 1;
15300 } else if (!strcasecmp(a->argv[3], "context")) {
15301 filtertype = 2;
15302 }
15303 }
15304
15305 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15306 ast_mutex_lock(&iflock);
15307 for (tmp = iflist; tmp; tmp = tmp->next) {
15308 if (filtertype) {
15309 switch(filtertype) {
15310 case 1:
15311 if (!(tmp->group & targetnum)) {
15312 continue;
15313 }
15314 break;
15315 case 2:
15316 if (strcasecmp(tmp->context, a->argv[4])) {
15317 continue;
15318 }
15319 break;
15320 default:
15321 break;
15322 }
15323 }
15324 if (tmp->channel > 0) {
15325 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15326 } else
15327 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15328
15329 if (tmp->locallyblocked)
15330 blockstr[0] = 'L';
15331 else
15332 blockstr[0] = ' ';
15333
15334 if (tmp->remotelyblocked)
15335 blockstr[1] = 'R';
15336 else
15337 blockstr[1] = ' ';
15338
15339 blockstr[2] = '\0';
15340
15341 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15342
15343 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15344 }
15345 ast_mutex_unlock(&iflock);
15346 return CLI_SUCCESS;
15347 #undef FORMAT
15348 #undef FORMAT2
15349 }
15350
15351 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15352 {
15353 int channel;
15354 struct dahdi_pvt *tmp = NULL;
15355 struct dahdi_confinfo ci;
15356 struct dahdi_params ps;
15357 int x;
15358
15359 switch (cmd) {
15360 case CLI_INIT:
15361 e->command = "dahdi show channel";
15362 e->usage =
15363 "Usage: dahdi show channel <chan num>\n"
15364 " Detailed information about a given channel\n";
15365 return NULL;
15366 case CLI_GENERATE:
15367 return NULL;
15368 }
15369
15370 if (a->argc != 4)
15371 return CLI_SHOWUSAGE;
15372
15373 channel = atoi(a->argv[3]);
15374
15375 ast_mutex_lock(&iflock);
15376 for (tmp = iflist; tmp; tmp = tmp->next) {
15377 if (tmp->channel == channel) {
15378 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15379 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15380 ast_cli(a->fd, "Span: %d\n", tmp->span);
15381 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15382 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15383 ast_cli(a->fd, "Context: %s\n", tmp->context);
15384 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15385 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15386 #if defined(HAVE_PRI)
15387 #if defined(HAVE_PRI_SUBADDR)
15388 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15389 #endif
15390 #endif
15391 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15392 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15393 if (tmp->vars) {
15394 struct ast_variable *v;
15395 ast_cli(a->fd, "Variables:\n");
15396 for (v = tmp->vars ; v ; v = v->next)
15397 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15398 }
15399 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15400 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15401 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15402 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15403 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15404 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
15405 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
15406 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
15407 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15408 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15409 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15410 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15411 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15412 if (tmp->busydetect) {
15413 #if defined(BUSYDETECT_TONEONLY)
15414 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15415 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15416 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15417 #endif
15418 #ifdef BUSYDETECT_DEBUG
15419 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15420 #endif
15421 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15422 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
15423 }
15424 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15425 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15426 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15427 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15428 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15429 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15430 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15431 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15432 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15433 ast_cli(a->fd, "Echo Cancellation:\n");
15434
15435 if (tmp->echocancel.head.tap_length) {
15436 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15437 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15438 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15439 }
15440 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15441 } else {
15442 ast_cli(a->fd, "\tnone\n");
15443 }
15444 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15445 if (tmp->master)
15446 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15447 for (x = 0; x < MAX_SLAVES; x++) {
15448 if (tmp->slaves[x])
15449 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15450 }
15451 #ifdef HAVE_OPENR2
15452 if (tmp->mfcr2) {
15453 char calldir[OR2_MAX_PATH];
15454 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15455 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15456 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15457 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15458 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15459 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15460 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15461 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15462 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15463 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15464 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15465 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15466 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15467 #endif
15468 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15469 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15470 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15471 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15472 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15473 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15474 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15475 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15476 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15477 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15478 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15479 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15480 }
15481 #endif
15482 #if defined(HAVE_SS7)
15483 if (tmp->ss7) {
15484 struct sig_ss7_chan *chan = tmp->sig_pvt;
15485
15486 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15487 }
15488 #endif
15489 #ifdef HAVE_PRI
15490 if (tmp->pri) {
15491 struct sig_pri_chan *chan = tmp->sig_pvt;
15492
15493 ast_cli(a->fd, "PRI Flags: ");
15494 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15495 ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15496 }
15497 if (chan->call)
15498 ast_cli(a->fd, "Call ");
15499 if (chan->allocated) {
15500 ast_cli(a->fd, "Allocated ");
15501 }
15502 ast_cli(a->fd, "\n");
15503 if (tmp->logicalspan)
15504 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15505 else
15506 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15507 }
15508 #endif
15509 memset(&ci, 0, sizeof(ci));
15510 ps.channo = tmp->channel;
15511 if (tmp->subs[SUB_REAL].dfd > -1) {
15512 memset(&ci, 0, sizeof(ci));
15513 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15514 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15515 }
15516 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15517 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15518 }
15519 memset(&ps, 0, sizeof(ps));
15520 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15521 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15522 } else {
15523 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15524 }
15525 }
15526 if (ISTRUNK(tmp)) {
15527 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
15528 if (!ast_strlen_zero(progzone))
15529 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15530 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
15531 if(tmp->busydetect) {
15532 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15533 if(tmp->busytonelength > 0) {
15534 ast_cli(a->fd, "Busy Pattern:\n");
15535 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15536 if (tmp->busyquietlength > 0)
15537 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15538 else
15539 ast_cli(a->fd, " -- Detect Tone Only\n");
15540 if(tmp->busyfuzziness > 0)
15541 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15542 }
15543 }
15544 }
15545 ast_mutex_unlock(&iflock);
15546 return CLI_SUCCESS;
15547 }
15548 }
15549 ast_mutex_unlock(&iflock);
15550
15551 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15552 return CLI_FAILURE;
15553 }
15554
15555 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15556 {
15557 int i, j;
15558 switch (cmd) {
15559 case CLI_INIT:
15560 e->command = "dahdi show cadences";
15561 e->usage =
15562 "Usage: dahdi show cadences\n"
15563 " Shows all cadences currently defined\n";
15564 return NULL;
15565 case CLI_GENERATE:
15566 return NULL;
15567 }
15568 for (i = 0; i < num_cadence; i++) {
15569 char output[1024];
15570 char tmp[16], tmp2[64];
15571 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15572 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15573
15574 for (j = 0; j < 16; j++) {
15575 if (cadences[i].ringcadence[j] == 0)
15576 break;
15577 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15578 if (cidrings[i] * 2 - 1 == j)
15579 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15580 else
15581 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15582 if (j != 0)
15583 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15584 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15585 }
15586 ast_cli(a->fd,"%s\n",output);
15587 }
15588 return CLI_SUCCESS;
15589 }
15590
15591
15592 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15593 {
15594 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15595 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15596 int span;
15597 int res;
15598 char alarmstr[50];
15599
15600 int ctl;
15601 struct dahdi_spaninfo s;
15602
15603 switch (cmd) {
15604 case CLI_INIT:
15605 e->command = "dahdi show status";
15606 e->usage =
15607 "Usage: dahdi show status\n"
15608 " Shows a list of DAHDI cards with status\n";
15609 return NULL;
15610 case CLI_GENERATE:
15611 return NULL;
15612 }
15613 ctl = open("/dev/dahdi/ctl", O_RDWR);
15614 if (ctl < 0) {
15615 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15616 return CLI_FAILURE;
15617 }
15618 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15619
15620 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15621 s.spanno = span;
15622 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15623 if (res) {
15624 continue;
15625 }
15626 alarmstr[0] = '\0';
15627 if (s.alarms > 0) {
15628 if (s.alarms & DAHDI_ALARM_BLUE)
15629 strcat(alarmstr, "BLU/");
15630 if (s.alarms & DAHDI_ALARM_YELLOW)
15631 strcat(alarmstr, "YEL/");
15632 if (s.alarms & DAHDI_ALARM_RED)
15633 strcat(alarmstr, "RED/");
15634 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15635 strcat(alarmstr, "LB/");
15636 if (s.alarms & DAHDI_ALARM_RECOVER)
15637 strcat(alarmstr, "REC/");
15638 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15639 strcat(alarmstr, "NOP/");
15640 if (!strlen(alarmstr))
15641 strcat(alarmstr, "UUU/");
15642 if (strlen(alarmstr)) {
15643
15644 alarmstr[strlen(alarmstr) - 1] = '\0';
15645 }
15646 } else {
15647 if (s.numchans)
15648 strcpy(alarmstr, "OK");
15649 else
15650 strcpy(alarmstr, "UNCONFIGURED");
15651 }
15652
15653 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15654 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15655 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15656 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15657 "CAS",
15658 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15659 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15660 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15661 "Unk",
15662 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15663 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15664 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15665 lbostr[s.lbo]
15666 );
15667 }
15668 close(ctl);
15669
15670 return CLI_SUCCESS;
15671 #undef FORMAT
15672 #undef FORMAT2
15673 }
15674
15675 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15676 {
15677 int pseudo_fd = -1;
15678 struct dahdi_versioninfo vi;
15679
15680 switch (cmd) {
15681 case CLI_INIT:
15682 e->command = "dahdi show version";
15683 e->usage =
15684 "Usage: dahdi show version\n"
15685 " Shows the DAHDI version in use\n";
15686 return NULL;
15687 case CLI_GENERATE:
15688 return NULL;
15689 }
15690 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15691 ast_cli(a->fd, "Failed to open control file to get version.\n");
15692 return CLI_SUCCESS;
15693 }
15694
15695 strcpy(vi.version, "Unknown");
15696 strcpy(vi.echo_canceller, "Unknown");
15697
15698 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15699 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15700 else
15701 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15702
15703 close(pseudo_fd);
15704
15705 return CLI_SUCCESS;
15706 }
15707
15708 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15709 {
15710 int channel;
15711 int gain;
15712 int tx;
15713 struct dahdi_hwgain hwgain;
15714 struct dahdi_pvt *tmp = NULL;
15715
15716 switch (cmd) {
15717 case CLI_INIT:
15718 e->command = "dahdi set hwgain";
15719 e->usage =
15720 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15721 " Sets the hardware gain on a a given channel, overriding the\n"
15722 " value provided at module loadtime, whether the channel is in\n"
15723 " use or not. Changes take effect immediately.\n"
15724 " <rx|tx> which direction do you want to change (relative to our module)\n"
15725 " <chan num> is the channel number relative to the device\n"
15726 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15727 return NULL;
15728 case CLI_GENERATE:
15729 return NULL;
15730 }
15731
15732 if (a->argc != 6)
15733 return CLI_SHOWUSAGE;
15734
15735 if (!strcasecmp("rx", a->argv[3]))
15736 tx = 0;
15737 else if (!strcasecmp("tx", a->argv[3]))
15738 tx = 1;
15739 else
15740 return CLI_SHOWUSAGE;
15741
15742 channel = atoi(a->argv[4]);
15743 gain = atof(a->argv[5])*10.0;
15744
15745 ast_mutex_lock(&iflock);
15746
15747 for (tmp = iflist; tmp; tmp = tmp->next) {
15748
15749 if (tmp->channel != channel)
15750 continue;
15751
15752 if (tmp->subs[SUB_REAL].dfd == -1)
15753 break;
15754
15755 hwgain.newgain = gain;
15756 hwgain.tx = tx;
15757 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15758 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15759 ast_mutex_unlock(&iflock);
15760 return CLI_FAILURE;
15761 }
15762 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15763 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15764 break;
15765 }
15766
15767 ast_mutex_unlock(&iflock);
15768
15769 if (tmp)
15770 return CLI_SUCCESS;
15771
15772 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15773 return CLI_FAILURE;
15774
15775 }
15776
15777 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15778 {
15779 int channel;
15780 float gain;
15781 int tx;
15782 int res;
15783 struct dahdi_pvt *tmp = NULL;
15784
15785 switch (cmd) {
15786 case CLI_INIT:
15787 e->command = "dahdi set swgain";
15788 e->usage =
15789 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15790 " Sets the software gain on a a given channel, overriding the\n"
15791 " value provided at module loadtime, whether the channel is in\n"
15792 " use or not. Changes take effect immediately.\n"
15793 " <rx|tx> which direction do you want to change (relative to our module)\n"
15794 " <chan num> is the channel number relative to the device\n"
15795 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15796 return NULL;
15797 case CLI_GENERATE:
15798 return NULL;
15799 }
15800
15801 if (a->argc != 6)
15802 return CLI_SHOWUSAGE;
15803
15804 if (!strcasecmp("rx", a->argv[3]))
15805 tx = 0;
15806 else if (!strcasecmp("tx", a->argv[3]))
15807 tx = 1;
15808 else
15809 return CLI_SHOWUSAGE;
15810
15811 channel = atoi(a->argv[4]);
15812 gain = atof(a->argv[5]);
15813
15814 ast_mutex_lock(&iflock);
15815 for (tmp = iflist; tmp; tmp = tmp->next) {
15816
15817 if (tmp->channel != channel)
15818 continue;
15819
15820 if (tmp->subs[SUB_REAL].dfd == -1)
15821 break;
15822
15823 if (tx)
15824 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15825 else
15826 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15827
15828 if (res) {
15829 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15830 ast_mutex_unlock(&iflock);
15831 return CLI_FAILURE;
15832 }
15833
15834 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15835 tx ? "tx" : "rx", gain, channel);
15836 break;
15837 }
15838 ast_mutex_unlock(&iflock);
15839
15840 if (tmp)
15841 return CLI_SUCCESS;
15842
15843 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15844 return CLI_FAILURE;
15845
15846 }
15847
15848 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15849 {
15850 int channel;
15851 int on;
15852 struct dahdi_pvt *dahdi_chan = NULL;
15853
15854 switch (cmd) {
15855 case CLI_INIT:
15856 e->command = "dahdi set dnd";
15857 e->usage =
15858 "Usage: dahdi set dnd <chan#> <on|off>\n"
15859 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15860 " Changes take effect immediately.\n"
15861 " <chan num> is the channel number\n"
15862 " <on|off> Enable or disable DND mode?\n"
15863 ;
15864 return NULL;
15865 case CLI_GENERATE:
15866 return NULL;
15867 }
15868
15869 if (a->argc != 5)
15870 return CLI_SHOWUSAGE;
15871
15872 if ((channel = atoi(a->argv[3])) <= 0) {
15873 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15874 return CLI_SHOWUSAGE;
15875 }
15876
15877 if (ast_true(a->argv[4]))
15878 on = 1;
15879 else if (ast_false(a->argv[4]))
15880 on = 0;
15881 else {
15882 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15883 return CLI_SHOWUSAGE;
15884 }
15885
15886 ast_mutex_lock(&iflock);
15887 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15888 if (dahdi_chan->channel != channel)
15889 continue;
15890
15891
15892 dahdi_dnd(dahdi_chan, on);
15893 break;
15894 }
15895 ast_mutex_unlock(&iflock);
15896
15897 if (!dahdi_chan) {
15898 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15899 return CLI_FAILURE;
15900 }
15901
15902 return CLI_SUCCESS;
15903 }
15904
15905 static struct ast_cli_entry dahdi_cli[] = {
15906 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15907 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15908 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15909 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15910 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15911 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15912 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15913 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15914 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15915 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15916 };
15917
15918 #define TRANSFER 0
15919 #define HANGUP 1
15920
15921 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15922 {
15923 if (p) {
15924 switch (mode) {
15925 case TRANSFER:
15926 p->fake_event = DAHDI_EVENT_WINKFLASH;
15927 break;
15928 case HANGUP:
15929 p->fake_event = DAHDI_EVENT_ONHOOK;
15930 break;
15931 default:
15932 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15933 }
15934 }
15935 return 0;
15936 }
15937 static struct dahdi_pvt *find_channel(int channel)
15938 {
15939 struct dahdi_pvt *p;
15940
15941 ast_mutex_lock(&iflock);
15942 for (p = iflist; p; p = p->next) {
15943 if (p->channel == channel) {
15944 break;
15945 }
15946 }
15947 ast_mutex_unlock(&iflock);
15948 return p;
15949 }
15950
15951
15952
15953
15954
15955
15956
15957
15958
15959
15960 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15961 {
15962 int chan_num;
15963
15964 if (sscanf(channel, "%30d", &chan_num) != 1) {
15965
15966 return NULL;
15967 }
15968
15969 return find_channel(chan_num);
15970 }
15971
15972 static int action_dahdidndon(struct mansession *s, const struct message *m)
15973 {
15974 struct dahdi_pvt *p;
15975 const char *channel = astman_get_header(m, "DAHDIChannel");
15976
15977 if (ast_strlen_zero(channel)) {
15978 astman_send_error(s, m, "No channel specified");
15979 return 0;
15980 }
15981 p = find_channel_from_str(channel);
15982 if (!p) {
15983 astman_send_error(s, m, "No such channel");
15984 return 0;
15985 }
15986 dahdi_dnd(p, 1);
15987 astman_send_ack(s, m, "DND Enabled");
15988 return 0;
15989 }
15990
15991 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15992 {
15993 struct dahdi_pvt *p;
15994 const char *channel = astman_get_header(m, "DAHDIChannel");
15995
15996 if (ast_strlen_zero(channel)) {
15997 astman_send_error(s, m, "No channel specified");
15998 return 0;
15999 }
16000 p = find_channel_from_str(channel);
16001 if (!p) {
16002 astman_send_error(s, m, "No such channel");
16003 return 0;
16004 }
16005 dahdi_dnd(p, 0);
16006 astman_send_ack(s, m, "DND Disabled");
16007 return 0;
16008 }
16009
16010 static int action_transfer(struct mansession *s, const struct message *m)
16011 {
16012 struct dahdi_pvt *p;
16013 const char *channel = astman_get_header(m, "DAHDIChannel");
16014
16015 if (ast_strlen_zero(channel)) {
16016 astman_send_error(s, m, "No channel specified");
16017 return 0;
16018 }
16019 p = find_channel_from_str(channel);
16020 if (!p) {
16021 astman_send_error(s, m, "No such channel");
16022 return 0;
16023 }
16024 if (!analog_lib_handles(p->sig, 0, 0)) {
16025 astman_send_error(s, m, "Channel signaling is not analog");
16026 return 0;
16027 }
16028 dahdi_fake_event(p,TRANSFER);
16029 astman_send_ack(s, m, "DAHDITransfer");
16030 return 0;
16031 }
16032
16033 static int action_transferhangup(struct mansession *s, const struct message *m)
16034 {
16035 struct dahdi_pvt *p;
16036 const char *channel = astman_get_header(m, "DAHDIChannel");
16037
16038 if (ast_strlen_zero(channel)) {
16039 astman_send_error(s, m, "No channel specified");
16040 return 0;
16041 }
16042 p = find_channel_from_str(channel);
16043 if (!p) {
16044 astman_send_error(s, m, "No such channel");
16045 return 0;
16046 }
16047 if (!analog_lib_handles(p->sig, 0, 0)) {
16048 astman_send_error(s, m, "Channel signaling is not analog");
16049 return 0;
16050 }
16051 dahdi_fake_event(p,HANGUP);
16052 astman_send_ack(s, m, "DAHDIHangup");
16053 return 0;
16054 }
16055
16056 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
16057 {
16058 struct dahdi_pvt *p;
16059 const char *channel = astman_get_header(m, "DAHDIChannel");
16060 const char *number = astman_get_header(m, "Number");
16061 int i;
16062
16063 if (ast_strlen_zero(channel)) {
16064 astman_send_error(s, m, "No channel specified");
16065 return 0;
16066 }
16067 if (ast_strlen_zero(number)) {
16068 astman_send_error(s, m, "No number specified");
16069 return 0;
16070 }
16071 p = find_channel_from_str(channel);
16072 if (!p) {
16073 astman_send_error(s, m, "No such channel");
16074 return 0;
16075 }
16076 if (!p->owner) {
16077 astman_send_error(s, m, "Channel does not have it's owner");
16078 return 0;
16079 }
16080 for (i = 0; i < strlen(number); i++) {
16081 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16082 dahdi_queue_frame(p, &f);
16083 }
16084 astman_send_ack(s, m, "DAHDIDialOffhook");
16085 return 0;
16086 }
16087
16088 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16089 {
16090 struct dahdi_pvt *tmp = NULL;
16091 const char *id = astman_get_header(m, "ActionID");
16092 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16093 char idText[256] = "";
16094 int channels = 0;
16095 int dahdichanquery;
16096
16097 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16098
16099 dahdichanquery = -1;
16100 }
16101
16102 astman_send_ack(s, m, "DAHDI channel status will follow");
16103 if (!ast_strlen_zero(id))
16104 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16105
16106 ast_mutex_lock(&iflock);
16107
16108 for (tmp = iflist; tmp; tmp = tmp->next) {
16109 if (tmp->channel > 0) {
16110 int alm;
16111
16112
16113 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16114 continue;
16115
16116 alm = get_alarms(tmp);
16117 channels++;
16118 if (tmp->owner) {
16119
16120 astman_append(s,
16121 "Event: DAHDIShowChannels\r\n"
16122 "DAHDIChannel: %d\r\n"
16123 "Channel: %s\r\n"
16124 "Uniqueid: %s\r\n"
16125 "AccountCode: %s\r\n"
16126 "Signalling: %s\r\n"
16127 "SignallingCode: %d\r\n"
16128 "Context: %s\r\n"
16129 "DND: %s\r\n"
16130 "Alarm: %s\r\n"
16131 "%s"
16132 "\r\n",
16133 tmp->channel,
16134 tmp->owner->name,
16135 tmp->owner->uniqueid,
16136 tmp->owner->accountcode,
16137 sig2str(tmp->sig),
16138 tmp->sig,
16139 tmp->context,
16140 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16141 alarm2str(alm), idText);
16142 } else {
16143 astman_append(s,
16144 "Event: DAHDIShowChannels\r\n"
16145 "DAHDIChannel: %d\r\n"
16146 "Signalling: %s\r\n"
16147 "SignallingCode: %d\r\n"
16148 "Context: %s\r\n"
16149 "DND: %s\r\n"
16150 "Alarm: %s\r\n"
16151 "%s"
16152 "\r\n",
16153 tmp->channel, sig2str(tmp->sig), tmp->sig,
16154 tmp->context,
16155 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16156 alarm2str(alm), idText);
16157 }
16158 }
16159 }
16160
16161 ast_mutex_unlock(&iflock);
16162
16163 astman_append(s,
16164 "Event: DAHDIShowChannelsComplete\r\n"
16165 "%s"
16166 "Items: %d\r\n"
16167 "\r\n",
16168 idText,
16169 channels);
16170 return 0;
16171 }
16172
16173 #if defined(HAVE_SS7)
16174 static int linkset_addsigchan(int sigchan)
16175 {
16176 struct dahdi_ss7 *link;
16177 int res;
16178 int curfd;
16179 struct dahdi_params params;
16180 struct dahdi_bufferinfo bi;
16181 struct dahdi_spaninfo si;
16182
16183 if (sigchan < 0) {
16184 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16185 return -1;
16186 }
16187 if (cur_ss7type < 0) {
16188 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16189 return -1;
16190 }
16191 if (cur_pointcode < 0) {
16192 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16193 return -1;
16194 }
16195 if (cur_adjpointcode < 0) {
16196 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16197 return -1;
16198 }
16199 if (cur_defaultdpc < 0) {
16200 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16201 return -1;
16202 }
16203 if (cur_networkindicator < 0) {
16204 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16205 return -1;
16206 }
16207 link = ss7_resolve_linkset(cur_linkset);
16208 if (!link) {
16209 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16210 return -1;
16211 }
16212 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16213 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16214 return -1;
16215 }
16216
16217 curfd = link->ss7.numsigchans;
16218
16219
16220 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16221 if (link->ss7.fds[curfd] < 0) {
16222 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16223 strerror(errno));
16224 return -1;
16225 }
16226 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16227 dahdi_close_ss7_fd(link, curfd);
16228 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16229 strerror(errno));
16230 return -1;
16231 }
16232
16233
16234 memset(¶ms, 0, sizeof(params));
16235 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16236 if (res) {
16237 dahdi_close_ss7_fd(link, curfd);
16238 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16239 strerror(errno));
16240 return -1;
16241 }
16242 if (params.sigtype != DAHDI_SIG_HDLCFCS
16243 && params.sigtype != DAHDI_SIG_HARDHDLC
16244 && params.sigtype != DAHDI_SIG_MTP2) {
16245 dahdi_close_ss7_fd(link, curfd);
16246 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16247 return -1;
16248 }
16249
16250
16251 memset(&bi, 0, sizeof(bi));
16252 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16253 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16254 bi.numbufs = 32;
16255 bi.bufsize = 512;
16256 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16257 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16258 sigchan, strerror(errno));
16259 dahdi_close_ss7_fd(link, curfd);
16260 return -1;
16261 }
16262
16263
16264 memset(&si, 0, sizeof(si));
16265 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16266 if (res) {
16267 dahdi_close_ss7_fd(link, curfd);
16268 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16269 strerror(errno));
16270 }
16271
16272 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16273 (params.sigtype == DAHDI_SIG_MTP2)
16274 ? SS7_TRANSPORT_DAHDIMTP2
16275 : SS7_TRANSPORT_DAHDIDCHAN,
16276 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16277 if (res) {
16278 dahdi_close_ss7_fd(link, curfd);
16279 return -1;
16280 }
16281
16282 ++link->ss7.numsigchans;
16283
16284 return 0;
16285 }
16286 #endif
16287
16288 #if defined(HAVE_SS7)
16289 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16290 {
16291 int span;
16292 switch (cmd) {
16293 case CLI_INIT:
16294 e->command = "ss7 set debug {on|off} linkset";
16295 e->usage =
16296 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16297 " Enables debugging on a given SS7 linkset\n";
16298 return NULL;
16299 case CLI_GENERATE:
16300 return NULL;
16301 }
16302 if (a->argc < 6)
16303 return CLI_SHOWUSAGE;
16304 span = atoi(a->argv[5]);
16305 if ((span < 1) || (span > NUM_SPANS)) {
16306 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16307 return CLI_SUCCESS;
16308 }
16309 if (!linksets[span-1].ss7.ss7) {
16310 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16311 } else {
16312 if (!strcasecmp(a->argv[3], "on")) {
16313 linksets[span - 1].ss7.debug = 1;
16314 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16315 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16316 } else {
16317 linksets[span - 1].ss7.debug = 0;
16318 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16319 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16320 }
16321 }
16322
16323 return CLI_SUCCESS;
16324 }
16325 #endif
16326
16327 #if defined(HAVE_SS7)
16328 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16329 {
16330 int linkset, cic;
16331 int blocked = -1, i;
16332 switch (cmd) {
16333 case CLI_INIT:
16334 e->command = "ss7 block cic";
16335 e->usage =
16336 "Usage: ss7 block cic <linkset> <CIC>\n"
16337 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16338 return NULL;
16339 case CLI_GENERATE:
16340 return NULL;
16341 }
16342 if (a->argc == 5)
16343 linkset = atoi(a->argv[3]);
16344 else
16345 return CLI_SHOWUSAGE;
16346
16347 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16348 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16349 return CLI_SUCCESS;
16350 }
16351
16352 if (!linksets[linkset-1].ss7.ss7) {
16353 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16354 return CLI_SUCCESS;
16355 }
16356
16357 cic = atoi(a->argv[4]);
16358
16359 if (cic < 1) {
16360 ast_cli(a->fd, "Invalid CIC specified!\n");
16361 return CLI_SUCCESS;
16362 }
16363
16364 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16365 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16366 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16367 if (!blocked) {
16368 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16369 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16370 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16371 }
16372 }
16373 }
16374
16375 if (blocked < 0) {
16376 ast_cli(a->fd, "Invalid CIC specified!\n");
16377 return CLI_SUCCESS;
16378 }
16379
16380 if (!blocked)
16381 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16382 else
16383 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16384
16385
16386 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16387
16388 return CLI_SUCCESS;
16389 }
16390 #endif
16391
16392 #if defined(HAVE_SS7)
16393 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16394 {
16395 int linkset;
16396 int i;
16397 switch (cmd) {
16398 case CLI_INIT:
16399 e->command = "ss7 block linkset";
16400 e->usage =
16401 "Usage: ss7 block linkset <linkset number>\n"
16402 " Sends a remote blocking request for all CICs on the given linkset\n";
16403 return NULL;
16404 case CLI_GENERATE:
16405 return NULL;
16406 }
16407 if (a->argc == 4)
16408 linkset = atoi(a->argv[3]);
16409 else
16410 return CLI_SHOWUSAGE;
16411
16412 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16413 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16414 return CLI_SUCCESS;
16415 }
16416
16417 if (!linksets[linkset-1].ss7.ss7) {
16418 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16419 return CLI_SUCCESS;
16420 }
16421
16422 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16423 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16424 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16425 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16426 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16427 }
16428
16429
16430 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16431
16432 return CLI_SUCCESS;
16433 }
16434 #endif
16435
16436 #if defined(HAVE_SS7)
16437 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16438 {
16439 int linkset, cic;
16440 int i, blocked = -1;
16441 switch (cmd) {
16442 case CLI_INIT:
16443 e->command = "ss7 unblock cic";
16444 e->usage =
16445 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16446 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16447 return NULL;
16448 case CLI_GENERATE:
16449 return NULL;
16450 }
16451
16452 if (a->argc == 5)
16453 linkset = atoi(a->argv[3]);
16454 else
16455 return CLI_SHOWUSAGE;
16456
16457 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16458 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16459 return CLI_SUCCESS;
16460 }
16461
16462 if (!linksets[linkset-1].ss7.ss7) {
16463 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16464 return CLI_SUCCESS;
16465 }
16466
16467 cic = atoi(a->argv[4]);
16468
16469 if (cic < 1) {
16470 ast_cli(a->fd, "Invalid CIC specified!\n");
16471 return CLI_SUCCESS;
16472 }
16473
16474 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16475 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16476 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16477 if (blocked) {
16478 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16479 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16480 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16481 }
16482 }
16483 }
16484
16485 if (blocked > 0)
16486 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16487
16488
16489 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16490
16491 return CLI_SUCCESS;
16492 }
16493 #endif
16494
16495 #if defined(HAVE_SS7)
16496 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16497 {
16498 int linkset;
16499 int i;
16500 switch (cmd) {
16501 case CLI_INIT:
16502 e->command = "ss7 unblock linkset";
16503 e->usage =
16504 "Usage: ss7 unblock linkset <linkset number>\n"
16505 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16506 return NULL;
16507 case CLI_GENERATE:
16508 return NULL;
16509 }
16510
16511 if (a->argc == 4)
16512 linkset = atoi(a->argv[3]);
16513 else
16514 return CLI_SHOWUSAGE;
16515
16516 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16517 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16518 return CLI_SUCCESS;
16519 }
16520
16521 if (!linksets[linkset-1].ss7.ss7) {
16522 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16523 return CLI_SUCCESS;
16524 }
16525
16526 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16527 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16528 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16529 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16530 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16531 }
16532
16533
16534 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16535
16536 return CLI_SUCCESS;
16537 }
16538 #endif
16539
16540 #if defined(HAVE_SS7)
16541 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16542 {
16543 int linkset;
16544 struct sig_ss7_linkset *ss7;
16545 switch (cmd) {
16546 case CLI_INIT:
16547 e->command = "ss7 show linkset";
16548 e->usage =
16549 "Usage: ss7 show linkset <span>\n"
16550 " Shows the status of an SS7 linkset.\n";
16551 return NULL;
16552 case CLI_GENERATE:
16553 return NULL;
16554 }
16555
16556 if (a->argc < 4)
16557 return CLI_SHOWUSAGE;
16558 linkset = atoi(a->argv[3]);
16559 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16560 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16561 return CLI_SUCCESS;
16562 }
16563 ss7 = &linksets[linkset - 1].ss7;
16564 if (!ss7->ss7) {
16565 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16566 return CLI_SUCCESS;
16567 }
16568
16569 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16570
16571 return CLI_SUCCESS;
16572 }
16573 #endif
16574
16575 #if defined(HAVE_SS7)
16576 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16577 {
16578 int linkset;
16579
16580 switch (cmd) {
16581 case CLI_INIT:
16582 e->command = "ss7 show channels";
16583 e->usage =
16584 "Usage: ss7 show channels\n"
16585 " Displays SS7 channel information at a glance.\n";
16586 return NULL;
16587 case CLI_GENERATE:
16588 return NULL;
16589 }
16590
16591 if (a->argc != 3)
16592 return CLI_SHOWUSAGE;
16593
16594 sig_ss7_cli_show_channels_header(a->fd);
16595 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16596 if (linksets[linkset].ss7.ss7) {
16597 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16598 }
16599 }
16600 return CLI_SUCCESS;
16601 }
16602 #endif
16603
16604 #if defined(HAVE_SS7)
16605 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16606 {
16607 switch (cmd) {
16608 case CLI_INIT:
16609 e->command = "ss7 show version";
16610 e->usage =
16611 "Usage: ss7 show version\n"
16612 " Show the libss7 version\n";
16613 return NULL;
16614 case CLI_GENERATE:
16615 return NULL;
16616 }
16617
16618 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16619
16620 return CLI_SUCCESS;
16621 }
16622 #endif
16623
16624 #if defined(HAVE_SS7)
16625 static struct ast_cli_entry dahdi_ss7_cli[] = {
16626 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16627 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16628 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16629 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16630 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16631 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16632 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16633 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16634 };
16635 #endif
16636
16637 #if defined(HAVE_PRI)
16638 #if defined(HAVE_PRI_CCSS)
16639
16640
16641
16642
16643
16644
16645
16646
16647
16648
16649
16650
16651
16652
16653
16654
16655
16656 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16657 {
16658 struct dahdi_pvt *pvt;
16659 struct sig_pri_chan *pvt_chan;
16660 int res;
16661
16662 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16663
16664 pvt = chan->tech_pvt;
16665 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16666 pvt_chan = pvt->sig_pvt;
16667 } else {
16668 pvt_chan = NULL;
16669 }
16670 if (!pvt_chan) {
16671 return -1;
16672 }
16673
16674 ast_module_ref(ast_module_info->self);
16675
16676 res = sig_pri_cc_agent_init(agent, pvt_chan);
16677 if (res) {
16678 ast_module_unref(ast_module_info->self);
16679 }
16680 return res;
16681 }
16682 #endif
16683 #endif
16684
16685 #if defined(HAVE_PRI)
16686 #if defined(HAVE_PRI_CCSS)
16687
16688
16689
16690
16691
16692
16693
16694
16695
16696
16697
16698
16699
16700 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16701 {
16702 sig_pri_cc_agent_destructor(agent);
16703
16704 ast_module_unref(ast_module_info->self);
16705 }
16706 #endif
16707 #endif
16708
16709 #if defined(HAVE_PRI)
16710 #if defined(HAVE_PRI_CCSS)
16711 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16712 .type = dahdi_pri_cc_type,
16713 .init = dahdi_pri_cc_agent_init,
16714 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16715 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16716 .respond = sig_pri_cc_agent_req_rsp,
16717 .status_request = sig_pri_cc_agent_status_req,
16718 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16719 .party_b_free = sig_pri_cc_agent_party_b_free,
16720 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16721 .callee_available = sig_pri_cc_agent_callee_available,
16722 .destructor = dahdi_pri_cc_agent_destructor,
16723 };
16724 #endif
16725 #endif
16726
16727 #if defined(HAVE_PRI)
16728 #if defined(HAVE_PRI_CCSS)
16729 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16730 .type = dahdi_pri_cc_type,
16731 .request_cc = sig_pri_cc_monitor_req_cc,
16732 .suspend = sig_pri_cc_monitor_suspend,
16733 .unsuspend = sig_pri_cc_monitor_unsuspend,
16734 .status_response = sig_pri_cc_monitor_status_rsp,
16735 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16736 .destructor = sig_pri_cc_monitor_destructor,
16737 };
16738 #endif
16739 #endif
16740
16741 static int __unload_module(void)
16742 {
16743 struct dahdi_pvt *p;
16744 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16745 int i, j;
16746 #endif
16747
16748 #ifdef HAVE_PRI
16749 for (i = 0; i < NUM_SPANS; i++) {
16750 if (pris[i].pri.master != AST_PTHREADT_NULL)
16751 pthread_cancel(pris[i].pri.master);
16752 }
16753 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16754 ast_unregister_application(dahdi_send_keypad_facility_app);
16755 #ifdef HAVE_PRI_PROG_W_CAUSE
16756 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16757 #endif
16758 #endif
16759 #if defined(HAVE_SS7)
16760 for (i = 0; i < NUM_SPANS; i++) {
16761 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16762 pthread_cancel(linksets[i].ss7.master);
16763 }
16764 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16765 #endif
16766 #if defined(HAVE_OPENR2)
16767 dahdi_r2_destroy_links();
16768 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16769 ast_unregister_application(dahdi_accept_r2_call_app);
16770 #endif
16771
16772 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16773 ast_manager_unregister("DAHDIDialOffhook");
16774 ast_manager_unregister("DAHDIHangup");
16775 ast_manager_unregister("DAHDITransfer");
16776 ast_manager_unregister("DAHDIDNDoff");
16777 ast_manager_unregister("DAHDIDNDon");
16778 ast_manager_unregister("DAHDIShowChannels");
16779 ast_manager_unregister("DAHDIRestart");
16780 ast_data_unregister(NULL);
16781 ast_channel_unregister(&dahdi_tech);
16782
16783
16784 ast_mutex_lock(&iflock);
16785 for (p = iflist; p; p = p->next) {
16786 if (p->owner)
16787 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16788 }
16789 ast_mutex_unlock(&iflock);
16790
16791 ast_mutex_lock(&monlock);
16792 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16793 pthread_cancel(monitor_thread);
16794 pthread_kill(monitor_thread, SIGURG);
16795 pthread_join(monitor_thread, NULL);
16796 }
16797 monitor_thread = AST_PTHREADT_STOP;
16798 ast_mutex_unlock(&monlock);
16799
16800 destroy_all_channels();
16801
16802 #if defined(HAVE_PRI)
16803 for (i = 0; i < NUM_SPANS; i++) {
16804 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16805 pthread_join(pris[i].pri.master, NULL);
16806 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16807 dahdi_close_pri_fd(&(pris[i]), j);
16808 }
16809 sig_pri_stop_pri(&pris[i].pri);
16810 }
16811 #if defined(HAVE_PRI_CCSS)
16812 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16813 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16814 #endif
16815 sig_pri_unload();
16816 #endif
16817
16818 #if defined(HAVE_SS7)
16819 for (i = 0; i < NUM_SPANS; i++) {
16820 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16821 pthread_join(linksets[i].ss7.master, NULL);
16822 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16823 dahdi_close_ss7_fd(&(linksets[i]), j);
16824 }
16825 }
16826 #endif
16827 ast_cond_destroy(&ss_thread_complete);
16828 return 0;
16829 }
16830
16831 static int unload_module(void)
16832 {
16833 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16834 int y;
16835 #endif
16836 #ifdef HAVE_PRI
16837 for (y = 0; y < NUM_SPANS; y++)
16838 ast_mutex_destroy(&pris[y].pri.lock);
16839 #endif
16840 #if defined(HAVE_SS7)
16841 for (y = 0; y < NUM_SPANS; y++)
16842 ast_mutex_destroy(&linksets[y].ss7.lock);
16843 #endif
16844 return __unload_module();
16845 }
16846
16847 static void string_replace(char *str, int char1, int char2)
16848 {
16849 for (; *str; str++) {
16850 if (*str == char1) {
16851 *str = char2;
16852 }
16853 }
16854 }
16855
16856 static char *parse_spanchan(char *chanstr, char **subdir)
16857 {
16858 char *p;
16859
16860 if ((p = strrchr(chanstr, '!')) == NULL) {
16861 *subdir = NULL;
16862 return chanstr;
16863 }
16864 *p++ = '\0';
16865 string_replace(chanstr, '!', '/');
16866 *subdir = chanstr;
16867 return p;
16868 }
16869
16870 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16871 {
16872 char *c, *chan;
16873 char *subdir;
16874 int x, start, finish;
16875 struct dahdi_pvt *tmp;
16876
16877 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16878 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16879 return -1;
16880 }
16881
16882 c = ast_strdupa(value);
16883 c = parse_spanchan(c, &subdir);
16884
16885 while ((chan = strsep(&c, ","))) {
16886 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16887
16888 } else if (sscanf(chan, "%30d", &start)) {
16889
16890 finish = start;
16891 } else if (!strcasecmp(chan, "pseudo")) {
16892 finish = start = CHAN_PSEUDO;
16893 if (found_pseudo)
16894 *found_pseudo = 1;
16895 } else {
16896 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16897 return -1;
16898 }
16899 if (finish < start) {
16900 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16901 x = finish;
16902 finish = start;
16903 start = x;
16904 }
16905
16906 for (x = start; x <= finish; x++) {
16907 char fn[PATH_MAX];
16908 int real_channel = x;
16909
16910 if (!ast_strlen_zero(subdir)) {
16911 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16912 if (real_channel < 0) {
16913 if (conf->ignore_failed_channels) {
16914 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16915 subdir, x, real_channel);
16916 continue;
16917 } else {
16918 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16919 subdir, x, real_channel);
16920 return -1;
16921 }
16922 }
16923 }
16924 tmp = mkintf(real_channel, conf, reload);
16925
16926 if (tmp) {
16927 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16928 } else {
16929 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16930 (reload == 1) ? "reconfigure" : "register", value);
16931 return -1;
16932 }
16933 }
16934 }
16935
16936 return 0;
16937 }
16938
16939
16940
16941 #define MAX_CHANLIST_LEN 80
16942
16943 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16944 {
16945 char *parse = ast_strdupa(data);
16946 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16947 unsigned int param_count;
16948 unsigned int x;
16949
16950 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16951 return;
16952
16953 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16954
16955
16956
16957 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16958
16959 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16960 confp->chan.echocancel.head.tap_length = x;
16961 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16962 confp->chan.echocancel.head.tap_length = 128;
16963
16964
16965
16966 for (x = 1; x < param_count; x++) {
16967 struct {
16968 char *name;
16969 char *value;
16970 } param;
16971
16972 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16973 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16974 continue;
16975 }
16976
16977 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16978 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16979 continue;
16980 }
16981
16982 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16983
16984 if (param.value) {
16985 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16986 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16987 continue;
16988 }
16989 }
16990 confp->chan.echocancel.head.param_count++;
16991 }
16992 }
16993
16994
16995 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16996
16997 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16998
16999 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
17000 {
17001 struct dahdi_pvt *tmp;
17002 int y;
17003 int found_pseudo = 0;
17004 struct ast_variable *dahdichan = NULL;
17005
17006 for (; v; v = v->next) {
17007 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
17008 continue;
17009
17010
17011 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
17012 if (options & PROC_DAHDI_OPT_NOCHAN) {
17013 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
17014 continue;
17015 }
17016 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
17017 if (confp->ignore_failed_channels) {
17018 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
17019 continue;
17020 } else {
17021 return -1;
17022 }
17023 }
17024 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
17025 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
17026 confp->ignore_failed_channels = ast_true(v->value);
17027 } else if (!strcasecmp(v->name, "buffers")) {
17028 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
17029 ast_log(LOG_WARNING, "Using default buffer policy.\n");
17030 confp->chan.buf_no = numbufs;
17031 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
17032 }
17033 } else if (!strcasecmp(v->name, "faxbuffers")) {
17034 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
17035 confp->chan.usefaxbuffers = 1;
17036 }
17037 } else if (!strcasecmp(v->name, "dahdichan")) {
17038
17039 dahdichan = v;
17040 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
17041 usedistinctiveringdetection = ast_true(v->value);
17042 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
17043 distinctiveringaftercid = ast_true(v->value);
17044 } else if (!strcasecmp(v->name, "dring1context")) {
17045 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
17046 } else if (!strcasecmp(v->name, "dring2context")) {
17047 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
17048 } else if (!strcasecmp(v->name, "dring3context")) {
17049 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
17050 } else if (!strcasecmp(v->name, "dring1range")) {
17051 confp->chan.drings.ringnum[0].range = atoi(v->value);
17052 } else if (!strcasecmp(v->name, "dring2range")) {
17053 confp->chan.drings.ringnum[1].range = atoi(v->value);
17054 } else if (!strcasecmp(v->name, "dring3range")) {
17055 confp->chan.drings.ringnum[2].range = atoi(v->value);
17056 } else if (!strcasecmp(v->name, "dring1")) {
17057 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]);
17058 } else if (!strcasecmp(v->name, "dring2")) {
17059 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]);
17060 } else if (!strcasecmp(v->name, "dring3")) {
17061 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]);
17062 } else if (!strcasecmp(v->name, "usecallerid")) {
17063 confp->chan.use_callerid = ast_true(v->value);
17064 } else if (!strcasecmp(v->name, "cidsignalling")) {
17065 if (!strcasecmp(v->value, "bell"))
17066 confp->chan.cid_signalling = CID_SIG_BELL;
17067 else if (!strcasecmp(v->value, "v23"))
17068 confp->chan.cid_signalling = CID_SIG_V23;
17069 else if (!strcasecmp(v->value, "dtmf"))
17070 confp->chan.cid_signalling = CID_SIG_DTMF;
17071 else if (!strcasecmp(v->value, "smdi"))
17072 confp->chan.cid_signalling = CID_SIG_SMDI;
17073 else if (!strcasecmp(v->value, "v23_jp"))
17074 confp->chan.cid_signalling = CID_SIG_V23_JP;
17075 else if (ast_true(v->value))
17076 confp->chan.cid_signalling = CID_SIG_BELL;
17077 } else if (!strcasecmp(v->name, "cidstart")) {
17078 if (!strcasecmp(v->value, "ring"))
17079 confp->chan.cid_start = CID_START_RING;
17080 else if (!strcasecmp(v->value, "polarity_in"))
17081 confp->chan.cid_start = CID_START_POLARITY_IN;
17082 else if (!strcasecmp(v->value, "polarity"))
17083 confp->chan.cid_start = CID_START_POLARITY;
17084 else if (!strcasecmp(v->value, "dtmf"))
17085 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17086 else if (ast_true(v->value))
17087 confp->chan.cid_start = CID_START_RING;
17088 } else if (!strcasecmp(v->name, "threewaycalling")) {
17089 confp->chan.threewaycalling = ast_true(v->value);
17090 } else if (!strcasecmp(v->name, "cancallforward")) {
17091 confp->chan.cancallforward = ast_true(v->value);
17092 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17093 if (ast_true(v->value))
17094 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17095 else
17096 confp->chan.dtmfrelax = 0;
17097 } else if (!strcasecmp(v->name, "mailbox")) {
17098 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17099 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17100 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17101 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17102 }
17103 } else if (!strcasecmp(v->name, "adsi")) {
17104 confp->chan.adsi = ast_true(v->value);
17105 } else if (!strcasecmp(v->name, "usesmdi")) {
17106 confp->chan.use_smdi = ast_true(v->value);
17107 } else if (!strcasecmp(v->name, "smdiport")) {
17108 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17109 } else if (!strcasecmp(v->name, "transfer")) {
17110 confp->chan.transfer = ast_true(v->value);
17111 } else if (!strcasecmp(v->name, "canpark")) {
17112 confp->chan.canpark = ast_true(v->value);
17113 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17114 confp->chan.echocanbridged = ast_true(v->value);
17115 } else if (!strcasecmp(v->name, "busydetect")) {
17116 confp->chan.busydetect = ast_true(v->value);
17117 } else if (!strcasecmp(v->name, "busycount")) {
17118 confp->chan.busycount = atoi(v->value);
17119 } else if (!strcasecmp(v->name, "silencethreshold")) {
17120 confp->chan.silencethreshold = atoi(v->value);
17121 } else if (!strcasecmp(v->name, "busycompare")) {
17122 confp->chan.busycompare = ast_true(v->value);
17123 } else if (!strcasecmp(v->name, "busypattern")) {
17124 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
17125 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17126 }
17127 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
17128 if (count == 1)
17129 confp->chan.busyquietlength = 0;
17130 else if (count < 1)
17131 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
17132 } else if (!strcasecmp(v->name, "busyfuzziness")) {
17133 confp->chan.busyfuzziness = atoi(v->value);
17134 } else if (!strcasecmp(v->name, "callprogress")) {
17135 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17136 if (ast_true(v->value))
17137 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17138 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17139 confp->chan.waitfordialtone = atoi(v->value);
17140 } else if (!strcasecmp(v->name, "faxdetect")) {
17141 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17142 if (!strcasecmp(v->value, "incoming")) {
17143 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17144 } else if (!strcasecmp(v->value, "outgoing")) {
17145 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17146 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17147 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17148 } else if (!strcasecmp(v->name, "echocancel")) {
17149 process_echocancel(confp, v->value, v->lineno);
17150 } else if (!strcasecmp(v->name, "echotraining")) {
17151 if (sscanf(v->value, "%30d", &y) == 1) {
17152 if ((y < 10) || (y > 4000)) {
17153 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17154 } else {
17155 confp->chan.echotraining = y;
17156 }
17157 } else if (ast_true(v->value)) {
17158 confp->chan.echotraining = 400;
17159 } else
17160 confp->chan.echotraining = 0;
17161 } else if (!strcasecmp(v->name, "hidecallerid")) {
17162 confp->chan.hidecallerid = ast_true(v->value);
17163 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17164 confp->chan.hidecalleridname = ast_true(v->value);
17165 } else if (!strcasecmp(v->name, "pulsedial")) {
17166 confp->chan.pulse = ast_true(v->value);
17167 } else if (!strcasecmp(v->name, "callreturn")) {
17168 confp->chan.callreturn = ast_true(v->value);
17169 } else if (!strcasecmp(v->name, "callwaiting")) {
17170 confp->chan.callwaiting = ast_true(v->value);
17171 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17172 confp->chan.callwaitingcallerid = ast_true(v->value);
17173 } else if (!strcasecmp(v->name, "context")) {
17174 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17175 } else if (!strcasecmp(v->name, "language")) {
17176 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17177 } else if (!strcasecmp(v->name, "progzone")) {
17178 ast_copy_string(progzone, v->value, sizeof(progzone));
17179 } else if (!strcasecmp(v->name, "mohinterpret")
17180 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17181 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17182 } else if (!strcasecmp(v->name, "mohsuggest")) {
17183 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17184 } else if (!strcasecmp(v->name, "parkinglot")) {
17185 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17186 } else if (!strcasecmp(v->name, "stripmsd")) {
17187 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17188 confp->chan.stripmsd = atoi(v->value);
17189 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17190 numbufs = atoi(v->value);
17191 } else if (!strcasecmp(v->name, "group")) {
17192 confp->chan.group = ast_get_group(v->value);
17193 } else if (!strcasecmp(v->name, "callgroup")) {
17194 if (!strcasecmp(v->value, "none"))
17195 confp->chan.callgroup = 0;
17196 else
17197 confp->chan.callgroup = ast_get_group(v->value);
17198 } else if (!strcasecmp(v->name, "pickupgroup")) {
17199 if (!strcasecmp(v->value, "none"))
17200 confp->chan.pickupgroup = 0;
17201 else
17202 confp->chan.pickupgroup = ast_get_group(v->value);
17203 } else if (!strcasecmp(v->name, "setvar")) {
17204 char *varname = ast_strdupa(v->value), *varval = NULL;
17205 struct ast_variable *tmpvar;
17206 if (varname && (varval = strchr(varname, '='))) {
17207 *varval++ = '\0';
17208 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17209 tmpvar->next = confp->chan.vars;
17210 confp->chan.vars = tmpvar;
17211 }
17212 }
17213 } else if (!strcasecmp(v->name, "immediate")) {
17214 confp->chan.immediate = ast_true(v->value);
17215 } else if (!strcasecmp(v->name, "transfertobusy")) {
17216 confp->chan.transfertobusy = ast_true(v->value);
17217 } else if (!strcasecmp(v->name, "mwimonitor")) {
17218 confp->chan.mwimonitor_neon = 0;
17219 confp->chan.mwimonitor_fsk = 0;
17220 confp->chan.mwimonitor_rpas = 0;
17221 if (strcasestr(v->value, "fsk")) {
17222 confp->chan.mwimonitor_fsk = 1;
17223 }
17224 if (strcasestr(v->value, "rpas")) {
17225 confp->chan.mwimonitor_rpas = 1;
17226 }
17227 if (strcasestr(v->value, "neon")) {
17228 confp->chan.mwimonitor_neon = 1;
17229 }
17230
17231 if (ast_true(v->value)) {
17232 confp->chan.mwimonitor_fsk = 1;
17233 }
17234 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17235 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17236 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17237 }
17238 } else if (!strcasecmp(v->name, "rxgain")) {
17239 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17240 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17241 }
17242 } else if (!strcasecmp(v->name, "txgain")) {
17243 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17244 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17245 }
17246 } else if (!strcasecmp(v->name, "txdrc")) {
17247 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17248 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17249 }
17250 } else if (!strcasecmp(v->name, "rxdrc")) {
17251 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17252 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17253 }
17254 } else if (!strcasecmp(v->name, "tonezone")) {
17255 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17256 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17257 }
17258 } else if (!strcasecmp(v->name, "callerid")) {
17259 if (!strcasecmp(v->value, "asreceived")) {
17260 confp->chan.cid_num[0] = '\0';
17261 confp->chan.cid_name[0] = '\0';
17262 } else {
17263 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17264 }
17265 } else if (!strcasecmp(v->name, "fullname")) {
17266 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17267 } else if (!strcasecmp(v->name, "cid_number")) {
17268 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17269 } else if (!strcasecmp(v->name, "cid_tag")) {
17270 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17271 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17272 confp->chan.dahditrcallerid = ast_true(v->value);
17273 } else if (!strcasecmp(v->name, "restrictcid")) {
17274 confp->chan.restrictcid = ast_true(v->value);
17275 } else if (!strcasecmp(v->name, "usecallingpres")) {
17276 confp->chan.use_callingpres = ast_true(v->value);
17277 } else if (!strcasecmp(v->name, "accountcode")) {
17278 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17279 } else if (!strcasecmp(v->name, "amaflags")) {
17280 y = ast_cdr_amaflags2int(v->value);
17281 if (y < 0)
17282 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17283 else
17284 confp->chan.amaflags = y;
17285 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17286 confp->chan.polarityonanswerdelay = atoi(v->value);
17287 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17288 confp->chan.answeronpolarityswitch = ast_true(v->value);
17289 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17290 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17291 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17292 confp->chan.sendcalleridafter = atoi(v->value);
17293 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17294 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17295 } else if (ast_cc_is_config_param(v->name)) {
17296 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17297 } else if (!strcasecmp(v->name, "mwisendtype")) {
17298 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17299 if (!strcasecmp(v->value, "rpas")) {
17300 mwisend_rpas = 1;
17301 } else {
17302 mwisend_rpas = 0;
17303 }
17304 #else
17305
17306 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17307 if (strcasestr(v->value, "nofsk")) {
17308 confp->chan.mwisend_fsk = 0;
17309 } else {
17310 confp->chan.mwisend_fsk = 1;
17311 }
17312 if (strcasestr(v->value, "rpas")) {
17313 confp->chan.mwisend_rpas = 1;
17314 } else {
17315 confp->chan.mwisend_rpas = 0;
17316 }
17317 if (strcasestr(v->value, "lrev")) {
17318 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17319 }
17320 if (strcasestr(v->value, "hvdc")) {
17321 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17322 }
17323 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17324 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17325 }
17326 #endif
17327 } else if (reload != 1) {
17328 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17329 int orig_radio = confp->chan.radio;
17330 int orig_outsigmod = confp->chan.outsigmod;
17331 int orig_auto = confp->is_sig_auto;
17332
17333 confp->chan.radio = 0;
17334 confp->chan.outsigmod = -1;
17335 confp->is_sig_auto = 0;
17336 if (!strcasecmp(v->value, "em")) {
17337 confp->chan.sig = SIG_EM;
17338 } else if (!strcasecmp(v->value, "em_e1")) {
17339 confp->chan.sig = SIG_EM_E1;
17340 } else if (!strcasecmp(v->value, "em_w")) {
17341 confp->chan.sig = SIG_EMWINK;
17342 } else if (!strcasecmp(v->value, "fxs_ls")) {
17343 confp->chan.sig = SIG_FXSLS;
17344 } else if (!strcasecmp(v->value, "fxs_gs")) {
17345 confp->chan.sig = SIG_FXSGS;
17346 } else if (!strcasecmp(v->value, "fxs_ks")) {
17347 confp->chan.sig = SIG_FXSKS;
17348 } else if (!strcasecmp(v->value, "fxo_ls")) {
17349 confp->chan.sig = SIG_FXOLS;
17350 } else if (!strcasecmp(v->value, "fxo_gs")) {
17351 confp->chan.sig = SIG_FXOGS;
17352 } else if (!strcasecmp(v->value, "fxo_ks")) {
17353 confp->chan.sig = SIG_FXOKS;
17354 } else if (!strcasecmp(v->value, "fxs_rx")) {
17355 confp->chan.sig = SIG_FXSKS;
17356 confp->chan.radio = 1;
17357 } else if (!strcasecmp(v->value, "fxo_rx")) {
17358 confp->chan.sig = SIG_FXOLS;
17359 confp->chan.radio = 1;
17360 } else if (!strcasecmp(v->value, "fxs_tx")) {
17361 confp->chan.sig = SIG_FXSLS;
17362 confp->chan.radio = 1;
17363 } else if (!strcasecmp(v->value, "fxo_tx")) {
17364 confp->chan.sig = SIG_FXOGS;
17365 confp->chan.radio = 1;
17366 } else if (!strcasecmp(v->value, "em_rx")) {
17367 confp->chan.sig = SIG_EM;
17368 confp->chan.radio = 1;
17369 } else if (!strcasecmp(v->value, "em_tx")) {
17370 confp->chan.sig = SIG_EM;
17371 confp->chan.radio = 1;
17372 } else if (!strcasecmp(v->value, "em_rxtx")) {
17373 confp->chan.sig = SIG_EM;
17374 confp->chan.radio = 2;
17375 } else if (!strcasecmp(v->value, "em_txrx")) {
17376 confp->chan.sig = SIG_EM;
17377 confp->chan.radio = 2;
17378 } else if (!strcasecmp(v->value, "sf")) {
17379 confp->chan.sig = SIG_SF;
17380 } else if (!strcasecmp(v->value, "sf_w")) {
17381 confp->chan.sig = SIG_SFWINK;
17382 } else if (!strcasecmp(v->value, "sf_featd")) {
17383 confp->chan.sig = SIG_FEATD;
17384 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17385 confp->chan.sig = SIG_FEATDMF;
17386 } else if (!strcasecmp(v->value, "sf_featb")) {
17387 confp->chan.sig = SIG_SF_FEATB;
17388 } else if (!strcasecmp(v->value, "sf")) {
17389 confp->chan.sig = SIG_SF;
17390 } else if (!strcasecmp(v->value, "sf_rx")) {
17391 confp->chan.sig = SIG_SF;
17392 confp->chan.radio = 1;
17393 } else if (!strcasecmp(v->value, "sf_tx")) {
17394 confp->chan.sig = SIG_SF;
17395 confp->chan.radio = 1;
17396 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17397 confp->chan.sig = SIG_SF;
17398 confp->chan.radio = 2;
17399 } else if (!strcasecmp(v->value, "sf_txrx")) {
17400 confp->chan.sig = SIG_SF;
17401 confp->chan.radio = 2;
17402 } else if (!strcasecmp(v->value, "featd")) {
17403 confp->chan.sig = SIG_FEATD;
17404 } else if (!strcasecmp(v->value, "featdmf")) {
17405 confp->chan.sig = SIG_FEATDMF;
17406 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17407 confp->chan.sig = SIG_FEATDMF_TA;
17408 } else if (!strcasecmp(v->value, "e911")) {
17409 confp->chan.sig = SIG_E911;
17410 } else if (!strcasecmp(v->value, "fgccama")) {
17411 confp->chan.sig = SIG_FGC_CAMA;
17412 } else if (!strcasecmp(v->value, "fgccamamf")) {
17413 confp->chan.sig = SIG_FGC_CAMAMF;
17414 } else if (!strcasecmp(v->value, "featb")) {
17415 confp->chan.sig = SIG_FEATB;
17416 #ifdef HAVE_PRI
17417 } else if (!strcasecmp(v->value, "pri_net")) {
17418 confp->chan.sig = SIG_PRI;
17419 confp->pri.pri.nodetype = PRI_NETWORK;
17420 } else if (!strcasecmp(v->value, "pri_cpe")) {
17421 confp->chan.sig = SIG_PRI;
17422 confp->pri.pri.nodetype = PRI_CPE;
17423 } else if (!strcasecmp(v->value, "bri_cpe")) {
17424 confp->chan.sig = SIG_BRI;
17425 confp->pri.pri.nodetype = PRI_CPE;
17426 } else if (!strcasecmp(v->value, "bri_net")) {
17427 confp->chan.sig = SIG_BRI;
17428 confp->pri.pri.nodetype = PRI_NETWORK;
17429 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17430 confp->chan.sig = SIG_BRI_PTMP;
17431 confp->pri.pri.nodetype = PRI_CPE;
17432 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17433 #if defined(HAVE_PRI_CALL_HOLD)
17434 confp->chan.sig = SIG_BRI_PTMP;
17435 confp->pri.pri.nodetype = PRI_NETWORK;
17436 #else
17437 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17438 #endif
17439 #endif
17440 #if defined(HAVE_SS7)
17441 } else if (!strcasecmp(v->value, "ss7")) {
17442 confp->chan.sig = SIG_SS7;
17443 #endif
17444 #ifdef HAVE_OPENR2
17445 } else if (!strcasecmp(v->value, "mfcr2")) {
17446 confp->chan.sig = SIG_MFCR2;
17447 #endif
17448 } else if (!strcasecmp(v->value, "auto")) {
17449 confp->is_sig_auto = 1;
17450 } else {
17451 confp->chan.outsigmod = orig_outsigmod;
17452 confp->chan.radio = orig_radio;
17453 confp->is_sig_auto = orig_auto;
17454 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17455 }
17456 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17457 if (!strcasecmp(v->value, "em")) {
17458 confp->chan.outsigmod = SIG_EM;
17459 } else if (!strcasecmp(v->value, "em_e1")) {
17460 confp->chan.outsigmod = SIG_EM_E1;
17461 } else if (!strcasecmp(v->value, "em_w")) {
17462 confp->chan.outsigmod = SIG_EMWINK;
17463 } else if (!strcasecmp(v->value, "sf")) {
17464 confp->chan.outsigmod = SIG_SF;
17465 } else if (!strcasecmp(v->value, "sf_w")) {
17466 confp->chan.outsigmod = SIG_SFWINK;
17467 } else if (!strcasecmp(v->value, "sf_featd")) {
17468 confp->chan.outsigmod = SIG_FEATD;
17469 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17470 confp->chan.outsigmod = SIG_FEATDMF;
17471 } else if (!strcasecmp(v->value, "sf_featb")) {
17472 confp->chan.outsigmod = SIG_SF_FEATB;
17473 } else if (!strcasecmp(v->value, "sf")) {
17474 confp->chan.outsigmod = SIG_SF;
17475 } else if (!strcasecmp(v->value, "featd")) {
17476 confp->chan.outsigmod = SIG_FEATD;
17477 } else if (!strcasecmp(v->value, "featdmf")) {
17478 confp->chan.outsigmod = SIG_FEATDMF;
17479 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17480 confp->chan.outsigmod = SIG_FEATDMF_TA;
17481 } else if (!strcasecmp(v->value, "e911")) {
17482 confp->chan.outsigmod = SIG_E911;
17483 } else if (!strcasecmp(v->value, "fgccama")) {
17484 confp->chan.outsigmod = SIG_FGC_CAMA;
17485 } else if (!strcasecmp(v->value, "fgccamamf")) {
17486 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17487 } else if (!strcasecmp(v->value, "featb")) {
17488 confp->chan.outsigmod = SIG_FEATB;
17489 } else {
17490 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17491 }
17492 #ifdef HAVE_PRI
17493 } else if (!strcasecmp(v->name, "pridialplan")) {
17494 if (!strcasecmp(v->value, "national")) {
17495 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17496 } else if (!strcasecmp(v->value, "unknown")) {
17497 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17498 } else if (!strcasecmp(v->value, "private")) {
17499 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17500 } else if (!strcasecmp(v->value, "international")) {
17501 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17502 } else if (!strcasecmp(v->value, "local")) {
17503 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17504 } else if (!strcasecmp(v->value, "dynamic")) {
17505 confp->pri.pri.dialplan = -1;
17506 } else if (!strcasecmp(v->value, "redundant")) {
17507 confp->pri.pri.dialplan = -2;
17508 } else {
17509 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17510 }
17511 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17512 if (!strcasecmp(v->value, "national")) {
17513 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17514 } else if (!strcasecmp(v->value, "unknown")) {
17515 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17516 } else if (!strcasecmp(v->value, "private")) {
17517 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17518 } else if (!strcasecmp(v->value, "international")) {
17519 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17520 } else if (!strcasecmp(v->value, "local")) {
17521 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17522 } else if (!strcasecmp(v->value, "dynamic")) {
17523 confp->pri.pri.localdialplan = -1;
17524 } else if (!strcasecmp(v->value, "redundant")) {
17525 confp->pri.pri.localdialplan = -2;
17526 } else {
17527 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17528 }
17529 } else if (!strcasecmp(v->name, "switchtype")) {
17530 if (!strcasecmp(v->value, "national"))
17531 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17532 else if (!strcasecmp(v->value, "ni1"))
17533 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17534 else if (!strcasecmp(v->value, "dms100"))
17535 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17536 else if (!strcasecmp(v->value, "4ess"))
17537 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17538 else if (!strcasecmp(v->value, "5ess"))
17539 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17540 else if (!strcasecmp(v->value, "euroisdn"))
17541 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17542 else if (!strcasecmp(v->value, "qsig"))
17543 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17544 else {
17545 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17546 return -1;
17547 }
17548 } else if (!strcasecmp(v->name, "msn")) {
17549 ast_copy_string(confp->pri.pri.msn_list, v->value,
17550 sizeof(confp->pri.pri.msn_list));
17551 } else if (!strcasecmp(v->name, "nsf")) {
17552 if (!strcasecmp(v->value, "sdn"))
17553 confp->pri.pri.nsf = PRI_NSF_SDN;
17554 else if (!strcasecmp(v->value, "megacom"))
17555 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17556 else if (!strcasecmp(v->value, "tollfreemegacom"))
17557 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17558 else if (!strcasecmp(v->value, "accunet"))
17559 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17560 else if (!strcasecmp(v->value, "none"))
17561 confp->pri.pri.nsf = PRI_NSF_NONE;
17562 else {
17563 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17564 confp->pri.pri.nsf = PRI_NSF_NONE;
17565 }
17566 } else if (!strcasecmp(v->name, "priindication")) {
17567 if (!strcasecmp(v->value, "outofband"))
17568 confp->chan.priindication_oob = 1;
17569 else if (!strcasecmp(v->value, "inband"))
17570 confp->chan.priindication_oob = 0;
17571 else
17572 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17573 v->value, v->lineno);
17574 } else if (!strcasecmp(v->name, "priexclusive")) {
17575 confp->chan.priexclusive = ast_true(v->value);
17576 } else if (!strcasecmp(v->name, "internationalprefix")) {
17577 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17578 } else if (!strcasecmp(v->name, "nationalprefix")) {
17579 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17580 } else if (!strcasecmp(v->name, "localprefix")) {
17581 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17582 } else if (!strcasecmp(v->name, "privateprefix")) {
17583 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17584 } else if (!strcasecmp(v->name, "unknownprefix")) {
17585 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17586 } else if (!strcasecmp(v->name, "resetinterval")) {
17587 if (!strcasecmp(v->value, "never"))
17588 confp->pri.pri.resetinterval = -1;
17589 else if (atoi(v->value) >= 60)
17590 confp->pri.pri.resetinterval = atoi(v->value);
17591 else
17592 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17593 v->value, v->lineno);
17594 } else if (!strcasecmp(v->name, "minunused")) {
17595 confp->pri.pri.minunused = atoi(v->value);
17596 } else if (!strcasecmp(v->name, "minidle")) {
17597 confp->pri.pri.minidle = atoi(v->value);
17598 } else if (!strcasecmp(v->name, "idleext")) {
17599 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17600 } else if (!strcasecmp(v->name, "idledial")) {
17601 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17602 } else if (!strcasecmp(v->name, "overlapdial")) {
17603 if (ast_true(v->value)) {
17604 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17605 } else if (!strcasecmp(v->value, "incoming")) {
17606 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17607 } else if (!strcasecmp(v->value, "outgoing")) {
17608 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17609 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17610 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17611 } else {
17612 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17613 }
17614 #ifdef HAVE_PRI_PROG_W_CAUSE
17615 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17616 if (!strcasecmp(v->value, "logical")) {
17617 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17618 } else if (!strcasecmp(v->value, "physical")) {
17619 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17620 } else {
17621 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17622 }
17623 #endif
17624 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17625 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17626 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17627 } else if (!strcasecmp(v->name, "service_message_support")) {
17628
17629 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17630 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17631 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17632 confp->pri.pri.enable_service_message_support = 1;
17633 } else {
17634 confp->pri.pri.enable_service_message_support = 0;
17635 }
17636 #endif
17637 #ifdef HAVE_PRI_INBANDDISCONNECT
17638 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17639 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17640 #endif
17641 } else if (!strcasecmp(v->name, "pritimer")) {
17642 #ifdef PRI_GETSET_TIMERS
17643 char tmp[20];
17644 char *timerc;
17645 char *c;
17646 int timer;
17647 int timeridx;
17648
17649 ast_copy_string(tmp, v->value, sizeof(tmp));
17650 c = tmp;
17651 timerc = strsep(&c, ",");
17652 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17653 timeridx = pri_timer2idx(timerc);
17654 timer = atoi(c);
17655 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17656 ast_log(LOG_WARNING,
17657 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17658 v->lineno);
17659 } else if (!timer) {
17660 ast_log(LOG_WARNING,
17661 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17662 c, timerc, v->lineno);
17663 } else {
17664 confp->pri.pri.pritimers[timeridx] = timer;
17665 }
17666 } else {
17667 ast_log(LOG_WARNING,
17668 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17669 v->value, v->lineno);
17670 }
17671 #endif
17672 } else if (!strcasecmp(v->name, "facilityenable")) {
17673 confp->pri.pri.facilityenable = ast_true(v->value);
17674 #if defined(HAVE_PRI_AOC_EVENTS)
17675 } else if (!strcasecmp(v->name, "aoc_enable")) {
17676 confp->pri.pri.aoc_passthrough_flag = 0;
17677 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17678 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17679 }
17680 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17681 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17682 }
17683 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17684 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17685 }
17686 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17687 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17688 #endif
17689 #if defined(HAVE_PRI_CALL_HOLD)
17690 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17691 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17692 #endif
17693 #if defined(HAVE_PRI_CCSS)
17694 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17695 if (!strcasecmp(v->value, "global")) {
17696 confp->pri.pri.cc_ptmp_recall_mode = 0;
17697 } else if (!strcasecmp(v->value, "specific")) {
17698 confp->pri.pri.cc_ptmp_recall_mode = 1;
17699 } else {
17700 confp->pri.pri.cc_ptmp_recall_mode = 1;
17701 }
17702 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17703 if (!strcasecmp(v->value, "release")) {
17704 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17705 } else if (!strcasecmp(v->value, "retain")) {
17706 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17707 } else if (!strcasecmp(v->value, "do_not_care")) {
17708 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17709 } else {
17710 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17711 }
17712 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17713 if (!strcasecmp(v->value, "release")) {
17714 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17715 } else if (!strcasecmp(v->value, "retain")) {
17716 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17717 } else {
17718 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17719 }
17720 #endif
17721 #if defined(HAVE_PRI_CALL_WAITING)
17722 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17723 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17724 if (confp->pri.pri.max_call_waiting_calls < 0) {
17725
17726 confp->pri.pri.max_call_waiting_calls = 0;
17727 }
17728 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17729 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17730 #endif
17731 #if defined(HAVE_PRI_MWI)
17732 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17733 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17734 sizeof(confp->pri.pri.mwi_mailboxes));
17735 #endif
17736 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17737 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17738 } else if (!strcasecmp(v->name, "layer1_presence")) {
17739 if (!strcasecmp(v->value, "required")) {
17740 confp->pri.pri.layer1_ignored = 0;
17741 } else if (!strcasecmp(v->value, "ignore")) {
17742 confp->pri.pri.layer1_ignored = 1;
17743 } else {
17744
17745 confp->pri.pri.layer1_ignored = 0;
17746 }
17747 #if defined(HAVE_PRI_L2_PERSISTENCE)
17748 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17749 if (!strcasecmp(v->value, "keep_up")) {
17750 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17751 } else if (!strcasecmp(v->value, "leave_down")) {
17752 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17753 } else {
17754 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17755 }
17756 #endif
17757 #endif
17758 #if defined(HAVE_SS7)
17759 } else if (!strcasecmp(v->name, "ss7type")) {
17760 if (!strcasecmp(v->value, "itu")) {
17761 cur_ss7type = SS7_ITU;
17762 } else if (!strcasecmp(v->value, "ansi")) {
17763 cur_ss7type = SS7_ANSI;
17764 } else
17765 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17766 } else if (!strcasecmp(v->name, "linkset")) {
17767 cur_linkset = atoi(v->value);
17768 } else if (!strcasecmp(v->name, "pointcode")) {
17769 cur_pointcode = parse_pointcode(v->value);
17770 } else if (!strcasecmp(v->name, "adjpointcode")) {
17771 cur_adjpointcode = parse_pointcode(v->value);
17772 } else if (!strcasecmp(v->name, "defaultdpc")) {
17773 cur_defaultdpc = parse_pointcode(v->value);
17774 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17775 cur_cicbeginswith = atoi(v->value);
17776 } else if (!strcasecmp(v->name, "networkindicator")) {
17777 if (!strcasecmp(v->value, "national"))
17778 cur_networkindicator = SS7_NI_NAT;
17779 else if (!strcasecmp(v->value, "national_spare"))
17780 cur_networkindicator = SS7_NI_NAT_SPARE;
17781 else if (!strcasecmp(v->value, "international"))
17782 cur_networkindicator = SS7_NI_INT;
17783 else if (!strcasecmp(v->value, "international_spare"))
17784 cur_networkindicator = SS7_NI_INT_SPARE;
17785 else
17786 cur_networkindicator = -1;
17787 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17788 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17789 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17790 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17791 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17792 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17793 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17794 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17795 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17796 if (!strcasecmp(v->value, "national")) {
17797 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17798 } else if (!strcasecmp(v->value, "international")) {
17799 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17800 } else if (!strcasecmp(v->value, "subscriber")) {
17801 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17802 } else if (!strcasecmp(v->value, "unknown")) {
17803 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17804 } else if (!strcasecmp(v->value, "dynamic")) {
17805 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17806 } else {
17807 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17808 }
17809 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17810 if (!strcasecmp(v->value, "national")) {
17811 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17812 } else if (!strcasecmp(v->value, "international")) {
17813 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17814 } else if (!strcasecmp(v->value, "subscriber")) {
17815 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17816 } else if (!strcasecmp(v->value, "unknown")) {
17817 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17818 } else if (!strcasecmp(v->value, "dynamic")) {
17819 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17820 } else {
17821 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17822 }
17823 } else if (!strcasecmp(v->name, "sigchan")) {
17824 int sigchan, res;
17825 sigchan = atoi(v->value);
17826 res = linkset_addsigchan(sigchan);
17827 if (res < 0)
17828 return -1;
17829
17830 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17831 struct dahdi_ss7 *link;
17832 link = ss7_resolve_linkset(cur_linkset);
17833 if (!link) {
17834 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17835 return -1;
17836 }
17837 if (ast_true(v->value))
17838 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17839 #endif
17840 #ifdef HAVE_OPENR2
17841 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17842 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17843 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);
17844 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17845 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17846 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17847 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17848 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17849 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17850 confp->mfcr2.variant = OR2_VAR_ITU;
17851 }
17852 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17853 confp->mfcr2.mfback_timeout = atoi(v->value);
17854 if (!confp->mfcr2.mfback_timeout) {
17855 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17856 confp->mfcr2.mfback_timeout = -1;
17857 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17858 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17859 }
17860 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17861 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17862 if (confp->mfcr2.metering_pulse_timeout > 500) {
17863 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17864 }
17865 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17866 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17867 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17868 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17869 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17870 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17871 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17872 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17873 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17874 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17875 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17876 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17877 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17878 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17879 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17880 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17881 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17882 #endif
17883 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17884 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17885 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17886 confp->mfcr2.max_ani = atoi(v->value);
17887 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17888 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17889 }
17890 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17891 confp->mfcr2.max_dnis = atoi(v->value);
17892 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17893 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17894 }
17895 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17896 confp->mfcr2.category = openr2_proto_get_category(v->value);
17897 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17898 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17899 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17900 v->value, v->lineno);
17901 }
17902 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17903 openr2_log_level_t tmplevel;
17904 char *clevel;
17905 char *logval = ast_strdupa(v->value);
17906 while (logval) {
17907 clevel = strsep(&logval,",");
17908 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17909 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17910 continue;
17911 }
17912 confp->mfcr2.loglevel |= tmplevel;
17913 }
17914 #endif
17915 } else if (!strcasecmp(v->name, "cadence")) {
17916
17917 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17918 int i;
17919 struct dahdi_ring_cadence new_cadence;
17920 int cid_location = -1;
17921 int firstcadencepos = 0;
17922 char original_args[80];
17923 int cadence_is_ok = 1;
17924
17925 ast_copy_string(original_args, v->value, sizeof(original_args));
17926
17927 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]);
17928
17929
17930 if (element_count % 2 == 1) {
17931 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17932 cadence_is_ok = 0;
17933 }
17934
17935
17936 for (i = 0; i < element_count; i++) {
17937 if (c[i] == 0) {
17938 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17939 cadence_is_ok = 0;
17940 break;
17941 } else if (c[i] < 0) {
17942 if (i % 2 == 1) {
17943
17944 if (cid_location == -1) {
17945 cid_location = i;
17946 c[i] *= -1;
17947 } else {
17948 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17949 cadence_is_ok = 0;
17950 break;
17951 }
17952 } else {
17953 if (firstcadencepos == 0) {
17954 firstcadencepos = i;
17955
17956 } else {
17957 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17958 cadence_is_ok = 0;
17959 break;
17960 }
17961 }
17962 }
17963 }
17964
17965
17966 for (i = 0; i < 16; i++) {
17967 new_cadence.ringcadence[i] = c[i];
17968 }
17969
17970 if (cadence_is_ok) {
17971
17972 if (element_count < 2) {
17973 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17974 } else {
17975 if (cid_location == -1) {
17976
17977 cid_location = 1;
17978 } else {
17979
17980 cid_location = (cid_location + 1) / 2;
17981 }
17982
17983 if (!user_has_defined_cadences++)
17984
17985 num_cadence = 0;
17986 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17987 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17988 else {
17989 cadences[num_cadence] = new_cadence;
17990 cidrings[num_cadence++] = cid_location;
17991 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17992 }
17993 }
17994 }
17995 } else if (!strcasecmp(v->name, "ringtimeout")) {
17996 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17997 } else if (!strcasecmp(v->name, "prewink")) {
17998 confp->timing.prewinktime = atoi(v->value);
17999 } else if (!strcasecmp(v->name, "preflash")) {
18000 confp->timing.preflashtime = atoi(v->value);
18001 } else if (!strcasecmp(v->name, "wink")) {
18002 confp->timing.winktime = atoi(v->value);
18003 } else if (!strcasecmp(v->name, "flash")) {
18004 confp->timing.flashtime = atoi(v->value);
18005 } else if (!strcasecmp(v->name, "start")) {
18006 confp->timing.starttime = atoi(v->value);
18007 } else if (!strcasecmp(v->name, "rxwink")) {
18008 confp->timing.rxwinktime = atoi(v->value);
18009 } else if (!strcasecmp(v->name, "rxflash")) {
18010 confp->timing.rxflashtime = atoi(v->value);
18011 } else if (!strcasecmp(v->name, "debounce")) {
18012 confp->timing.debouncetime = atoi(v->value);
18013 } else if (!strcasecmp(v->name, "toneduration")) {
18014 int toneduration;
18015 int ctlfd;
18016 int res;
18017 struct dahdi_dialparams dps;
18018
18019 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
18020 if (ctlfd == -1) {
18021 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
18022 return -1;
18023 }
18024
18025 toneduration = atoi(v->value);
18026 if (toneduration > -1) {
18027 memset(&dps, 0, sizeof(dps));
18028
18029 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
18030 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
18031 if (res < 0) {
18032 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
18033 close(ctlfd);
18034 return -1;
18035 }
18036 }
18037 close(ctlfd);
18038 } else if (!strcasecmp(v->name, "defaultcic")) {
18039 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
18040 } else if (!strcasecmp(v->name, "defaultozz")) {
18041 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
18042 } else if (!strcasecmp(v->name, "mwilevel")) {
18043 mwilevel = atoi(v->value);
18044 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
18045 dtmfcid_level = atoi(v->value);
18046 } else if (!strcasecmp(v->name, "reportalarms")) {
18047 if (!strcasecmp(v->value, "all"))
18048 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
18049 if (!strcasecmp(v->value, "none"))
18050 report_alarms = 0;
18051 else if (!strcasecmp(v->value, "channels"))
18052 report_alarms = REPORT_CHANNEL_ALARMS;
18053 else if (!strcasecmp(v->value, "spans"))
18054 report_alarms = REPORT_SPAN_ALARMS;
18055 }
18056 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
18057 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
18058 }
18059
18060
18061 if (confp->chan.vars) {
18062 ast_variables_destroy(confp->chan.vars);
18063 confp->chan.vars = NULL;
18064 }
18065
18066 if (dahdichan) {
18067
18068 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
18069 &found_pseudo)) {
18070 if (confp->ignore_failed_channels) {
18071 ast_log(LOG_WARNING,
18072 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
18073 dahdichan->value);
18074 } else {
18075 return -1;
18076 }
18077 }
18078 }
18079
18080
18081 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
18082 if (!tmp->destroy && tmp->span != y) {
18083 tmp->manages_span_alarms = 1;
18084 y = tmp->span;
18085 } else {
18086 tmp->manages_span_alarms = 0;
18087 }
18088 }
18089
18090
18091
18092 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18093
18094
18095
18096
18097 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18098
18099 if (conf.chan.cc_params) {
18100 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18101 } else {
18102 tmp = NULL;
18103 }
18104 if (tmp) {
18105 ast_verb(3, "Automatically generated pseudo channel\n");
18106 } else {
18107 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18108 }
18109 ast_cc_config_params_destroy(conf.chan.cc_params);
18110 }
18111 return 0;
18112 }
18113
18114
18115
18116
18117
18118
18119
18120
18121
18122
18123
18124 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18125 {
18126 struct ast_cc_config_params *cc_params;
18127
18128 cc_params = dest->chan.cc_params;
18129 *dest = *src;
18130 dest->chan.cc_params = cc_params;
18131 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18132 }
18133
18134
18135
18136
18137
18138
18139
18140
18141
18142
18143
18144
18145
18146 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18147 {
18148 struct ast_config *cfg;
18149 struct ast_config *ucfg;
18150 struct ast_variable *v;
18151 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18152 const char *chans;
18153 const char *cat;
18154 int res;
18155
18156 #ifdef HAVE_PRI
18157 char *c;
18158 int spanno;
18159 int i;
18160 int logicalspan;
18161 int trunkgroup;
18162 int dchannels[SIG_PRI_NUM_DCHANS];
18163 #endif
18164 int have_cfg_now;
18165 static int had_cfg_before = 1;
18166
18167 cfg = ast_config_load(config, config_flags);
18168 have_cfg_now = !!cfg;
18169 if (!cfg) {
18170
18171 if (had_cfg_before) {
18172 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18173 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18174 }
18175 cfg = ast_config_new();
18176 if (!cfg) {
18177 return 0;
18178 }
18179 ucfg = ast_config_load("users.conf", config_flags);
18180 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18181 ast_config_destroy(cfg);
18182 return 0;
18183 }
18184 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18185 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18186 ast_config_destroy(cfg);
18187 return 0;
18188 }
18189 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18190 ucfg = ast_config_load("users.conf", config_flags);
18191 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18192 return 0;
18193 }
18194 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18195 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18196 return 0;
18197 }
18198 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18199 cfg = ast_config_load(config, config_flags);
18200 have_cfg_now = !!cfg;
18201 if (!cfg) {
18202 if (had_cfg_before) {
18203
18204 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18205 ast_config_destroy(ucfg);
18206 return 0;
18207 }
18208 cfg = ast_config_new();
18209 if (!cfg) {
18210 ast_config_destroy(ucfg);
18211 return 0;
18212 }
18213 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18214 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18215 ast_config_destroy(ucfg);
18216 return 0;
18217 }
18218 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18219 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18220 return 0;
18221 } else {
18222 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18223 ucfg = ast_config_load("users.conf", config_flags);
18224 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18225 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18226 ast_config_destroy(cfg);
18227 return 0;
18228 }
18229 }
18230 had_cfg_before = have_cfg_now;
18231
18232
18233 ast_mutex_lock(&iflock);
18234 #ifdef HAVE_PRI
18235 if (reload != 1) {
18236
18237 v = ast_variable_browse(cfg, "trunkgroups");
18238 while (v) {
18239 if (!strcasecmp(v->name, "trunkgroup")) {
18240 trunkgroup = atoi(v->value);
18241 if (trunkgroup > 0) {
18242 if ((c = strchr(v->value, ','))) {
18243 i = 0;
18244 memset(dchannels, 0, sizeof(dchannels));
18245 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18246 dchannels[i] = atoi(c + 1);
18247 if (dchannels[i] < 0) {
18248 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);
18249 } else
18250 i++;
18251 c = strchr(c + 1, ',');
18252 }
18253 if (i) {
18254 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18255 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);
18256 } else
18257 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");
18258 } else
18259 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18260 } else
18261 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18262 } else
18263 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18264 } else if (!strcasecmp(v->name, "spanmap")) {
18265 spanno = atoi(v->value);
18266 if (spanno > 0) {
18267 if ((c = strchr(v->value, ','))) {
18268 trunkgroup = atoi(c + 1);
18269 if (trunkgroup > 0) {
18270 if ((c = strchr(c + 1, ',')))
18271 logicalspan = atoi(c + 1);
18272 else
18273 logicalspan = 0;
18274 if (logicalspan >= 0) {
18275 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18276 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18277 } else
18278 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18279 } else
18280 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);
18281 } else
18282 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18283 } else
18284 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18285 } else
18286 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18287 } else {
18288 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18289 }
18290 v = v->next;
18291 }
18292 }
18293 #endif
18294
18295
18296 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18297
18298 mwimonitornotify[0] = '\0';
18299
18300 v = ast_variable_browse(cfg, "channels");
18301 if ((res = process_dahdi(base_conf,
18302 "" ,
18303 v, reload, 0))) {
18304 ast_mutex_unlock(&iflock);
18305 ast_config_destroy(cfg);
18306 if (ucfg) {
18307 ast_config_destroy(ucfg);
18308 }
18309 return res;
18310 }
18311
18312
18313 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18314
18315
18316
18317 if (!strcasecmp(cat, "general") ||
18318 !strcasecmp(cat, "trunkgroups") ||
18319 !strcasecmp(cat, "globals") ||
18320 !strcasecmp(cat, "channels")) {
18321 continue;
18322 }
18323
18324 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18325 if (ast_strlen_zero(chans)) {
18326
18327 continue;
18328 }
18329
18330
18331 deep_copy_dahdi_chan_conf(conf, base_conf);
18332
18333 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18334 ast_mutex_unlock(&iflock);
18335 ast_config_destroy(cfg);
18336 if (ucfg) {
18337 ast_config_destroy(ucfg);
18338 }
18339 return res;
18340 }
18341 }
18342
18343 ast_config_destroy(cfg);
18344
18345 if (ucfg) {
18346
18347 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18348 process_dahdi(base_conf,
18349 "" ,
18350 ast_variable_browse(ucfg, "general"), 1, 0);
18351
18352 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18353 if (!strcasecmp(cat, "general")) {
18354 continue;
18355 }
18356
18357 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18358 if (ast_strlen_zero(chans)) {
18359
18360 continue;
18361 }
18362
18363
18364 deep_copy_dahdi_chan_conf(conf, base_conf);
18365
18366 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18367 ast_config_destroy(ucfg);
18368 ast_mutex_unlock(&iflock);
18369 return res;
18370 }
18371 }
18372 ast_config_destroy(ucfg);
18373 }
18374 ast_mutex_unlock(&iflock);
18375
18376 #ifdef HAVE_PRI
18377 if (reload != 1) {
18378 int x;
18379 for (x = 0; x < NUM_SPANS; x++) {
18380 if (pris[x].pri.pvts[0]) {
18381 prepare_pri(pris + x);
18382 if (sig_pri_start_pri(&pris[x].pri)) {
18383 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18384 return -1;
18385 } else
18386 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18387 }
18388 }
18389 }
18390 #endif
18391 #if defined(HAVE_SS7)
18392 if (reload != 1) {
18393 int x;
18394 for (x = 0; x < NUM_SPANS; x++) {
18395 if (linksets[x].ss7.ss7) {
18396 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18397 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18398 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18399 return -1;
18400 } else
18401 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18402 }
18403 }
18404 }
18405 #endif
18406 #ifdef HAVE_OPENR2
18407 if (reload != 1) {
18408 int x;
18409 for (x = 0; x < r2links_count; x++) {
18410 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18411 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18412 return -1;
18413 } else {
18414 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18415 }
18416 }
18417 }
18418 #endif
18419
18420 restart_monitor();
18421 return 0;
18422 }
18423
18424
18425
18426
18427
18428
18429
18430
18431
18432
18433 static int setup_dahdi(int reload)
18434 {
18435 int res;
18436 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18437 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18438 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18439
18440 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18441 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18442 } else {
18443 res = -1;
18444 }
18445 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18446 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18447 ast_cc_config_params_destroy(conf.chan.cc_params);
18448
18449 return res;
18450 }
18451
18452
18453
18454
18455
18456
18457
18458
18459 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18460 struct ast_data *data_root)
18461 {
18462 int ctl, res, span;
18463 struct ast_data *data_span, *data_alarms;
18464 struct dahdi_spaninfo s;
18465
18466 ctl = open("/dev/dahdi/ctl", O_RDWR);
18467 if (ctl < 0) {
18468 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18469 return -1;
18470 }
18471 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18472 s.spanno = span;
18473 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18474 if (res) {
18475 continue;
18476 }
18477
18478 data_span = ast_data_add_node(data_root, "span");
18479 if (!data_span) {
18480 continue;
18481 }
18482 ast_data_add_str(data_span, "description", s.desc);
18483
18484
18485 data_alarms = ast_data_add_node(data_span, "alarms");
18486 if (!data_alarms) {
18487 continue;
18488 }
18489
18490 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18491 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18492 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18493 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18494 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18495 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18496
18497 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18498 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18499 ast_data_add_int(data_span, "crc4", s.crc4count);
18500 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18501 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18502 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18503 "CAS");
18504 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18505 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18506 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18507 "Unknown");
18508 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18509 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18510 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18511 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18512
18513
18514 if (!ast_data_search_match(search, data_span)) {
18515 ast_data_remove_node(data_root, data_span);
18516 }
18517 }
18518 close(ctl);
18519
18520 return 0;
18521 }
18522
18523
18524
18525
18526
18527
18528
18529
18530 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18531 struct ast_data *data_root)
18532 {
18533 struct dahdi_pvt *tmp;
18534 struct ast_data *data_channel;
18535
18536 ast_mutex_lock(&iflock);
18537 for (tmp = iflist; tmp; tmp = tmp->next) {
18538 data_channel = ast_data_add_node(data_root, "channel");
18539 if (!data_channel) {
18540 continue;
18541 }
18542
18543 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18544
18545
18546 if (!ast_data_search_match(search, data_channel)) {
18547 ast_data_remove_node(data_root, data_channel);
18548 }
18549 }
18550 ast_mutex_unlock(&iflock);
18551
18552 return 0;
18553 }
18554
18555
18556
18557
18558
18559
18560
18561
18562 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18563 struct ast_data *data_root)
18564 {
18565 int pseudo_fd = -1;
18566 struct dahdi_versioninfo vi = {
18567 .version = "Unknown",
18568 .echo_canceller = "Unknown"
18569 };
18570
18571 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18572 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18573 return -1;
18574 }
18575
18576 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18577 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18578 }
18579
18580 close(pseudo_fd);
18581
18582 ast_data_add_str(data_root, "value", vi.version);
18583 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18584
18585 return 0;
18586 }
18587
18588 static const struct ast_data_handler dahdi_status_data_provider = {
18589 .version = AST_DATA_HANDLER_VERSION,
18590 .get = dahdi_status_data_provider_get
18591 };
18592
18593 static const struct ast_data_handler dahdi_channels_data_provider = {
18594 .version = AST_DATA_HANDLER_VERSION,
18595 .get = dahdi_channels_data_provider_get
18596 };
18597
18598 static const struct ast_data_handler dahdi_version_data_provider = {
18599 .version = AST_DATA_HANDLER_VERSION,
18600 .get = dahdi_version_data_provider_get
18601 };
18602
18603 static const struct ast_data_entry dahdi_data_providers[] = {
18604 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18605 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18606 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18607 };
18608
18609 static int load_module(void)
18610 {
18611 int res;
18612 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18613 int y;
18614 #endif
18615
18616 #ifdef HAVE_PRI
18617 memset(pris, 0, sizeof(pris));
18618 for (y = 0; y < NUM_SPANS; y++) {
18619 sig_pri_init_pri(&pris[y].pri);
18620 }
18621 pri_set_error(dahdi_pri_error);
18622 pri_set_message(dahdi_pri_message);
18623 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18624 #ifdef HAVE_PRI_PROG_W_CAUSE
18625 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18626 #endif
18627 #if defined(HAVE_PRI_CCSS)
18628 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18629 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18630 __unload_module();
18631 return AST_MODULE_LOAD_FAILURE;
18632 }
18633 #endif
18634 if (sig_pri_load(
18635 #if defined(HAVE_PRI_CCSS)
18636 dahdi_pri_cc_type
18637 #else
18638 NULL
18639 #endif
18640 )) {
18641 __unload_module();
18642 return AST_MODULE_LOAD_FAILURE;
18643 }
18644 #endif
18645 #if defined(HAVE_SS7)
18646 memset(linksets, 0, sizeof(linksets));
18647 for (y = 0; y < NUM_SPANS; y++) {
18648 sig_ss7_init_linkset(&linksets[y].ss7);
18649 }
18650 ss7_set_error(dahdi_ss7_error);
18651 ss7_set_message(dahdi_ss7_message);
18652 #endif
18653 res = setup_dahdi(0);
18654
18655 if (res)
18656 return AST_MODULE_LOAD_DECLINE;
18657 if (ast_channel_register(&dahdi_tech)) {
18658 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18659 __unload_module();
18660 return AST_MODULE_LOAD_FAILURE;
18661 }
18662 #ifdef HAVE_PRI
18663 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18664 #endif
18665 #if defined(HAVE_SS7)
18666 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18667 #endif
18668 #ifdef HAVE_OPENR2
18669 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18670 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18671 #endif
18672
18673 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18674
18675 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18676 memset(round_robin, 0, sizeof(round_robin));
18677 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18678 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18679 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18680 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18681 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18682 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18683 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18684
18685 ast_cond_init(&ss_thread_complete, NULL);
18686
18687 return res;
18688 }
18689
18690 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18691 {
18692 #define END_SILENCE_LEN 400
18693 #define HEADER_MS 50
18694 #define TRAILER_MS 5
18695 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18696 #define ASCII_BYTES_PER_CHAR 80
18697
18698 unsigned char *buf,*mybuf;
18699 struct dahdi_pvt *p = c->tech_pvt;
18700 struct pollfd fds[1];
18701 int size,res,fd,len,x;
18702 int bytes=0;
18703
18704 float cr = 1.0;
18705 float ci = 0.0;
18706 float scont = 0.0;
18707 int idx;
18708
18709 idx = dahdi_get_index(c, p, 0);
18710 if (idx < 0) {
18711 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18712 return -1;
18713 }
18714 if (!text[0]) return(0);
18715 if ((!p->tdd) && (!p->mate)) return(0);
18716 if (p->mate)
18717 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18718 else
18719 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18720 if (!buf)
18721 return -1;
18722 mybuf = buf;
18723 if (p->mate) {
18724 int codec = AST_LAW(p);
18725 for (x = 0; x < HEADER_MS; x++) {
18726 PUT_CLID_MARKMS;
18727 }
18728
18729 for (x = 0; text[x]; x++) {
18730 PUT_CLID(text[x]);
18731 }
18732 for (x = 0; x < TRAILER_MS; x++) {
18733 PUT_CLID_MARKMS;
18734 }
18735 len = bytes;
18736 buf = mybuf;
18737 } else {
18738 len = tdd_generate(p->tdd, buf, text);
18739 if (len < 1) {
18740 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18741 ast_free(mybuf);
18742 return -1;
18743 }
18744 }
18745 memset(buf + len, 0x7f, END_SILENCE_LEN);
18746 len += END_SILENCE_LEN;
18747 fd = p->subs[idx].dfd;
18748 while (len) {
18749 if (ast_check_hangup(c)) {
18750 ast_free(mybuf);
18751 return -1;
18752 }
18753 size = len;
18754 if (size > READ_SIZE)
18755 size = READ_SIZE;
18756 fds[0].fd = fd;
18757 fds[0].events = POLLOUT | POLLPRI;
18758 fds[0].revents = 0;
18759 res = poll(fds, 1, -1);
18760 if (!res) {
18761 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18762 continue;
18763 }
18764
18765 if (fds[0].revents & POLLPRI) {
18766 ast_free(mybuf);
18767 return -1;
18768 }
18769 if (!(fds[0].revents & POLLOUT)) {
18770 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18771 continue;
18772 }
18773 res = write(fd, buf, size);
18774 if (res != size) {
18775 if (res == -1) {
18776 ast_free(mybuf);
18777 return -1;
18778 }
18779 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18780 break;
18781 }
18782 len -= size;
18783 buf += size;
18784 }
18785 ast_free(mybuf);
18786 return(0);
18787 }
18788
18789
18790 static int reload(void)
18791 {
18792 int res = 0;
18793
18794 res = setup_dahdi(1);
18795 if (res) {
18796 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18797 return -1;
18798 }
18799 return 0;
18800 }
18801
18802
18803
18804
18805
18806 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18807 .load = load_module,
18808 .unload = unload_module,
18809 .reload = reload,
18810 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18811 .nonoptreq = "res_smdi",
18812 );