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: 347006 $")
00053
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068
00069
00070
00071
00072
00073
00074 #ifdef HAVE_PRI
00075 #include "sig_pri.h"
00076 #endif
00077
00078 #if defined(HAVE_SS7)
00079 #include "sig_ss7.h"
00080 #endif
00081
00082 #ifdef HAVE_OPENR2
00083
00084 #define SIG_MFCR2_MAX_CHANNELS 672
00085 #include <openr2.h>
00086 #endif
00087
00088 #include "asterisk/lock.h"
00089 #include "asterisk/channel.h"
00090 #include "asterisk/config.h"
00091 #include "asterisk/module.h"
00092 #include "asterisk/pbx.h"
00093 #include "asterisk/file.h"
00094 #include "asterisk/ulaw.h"
00095 #include "asterisk/alaw.h"
00096 #include "asterisk/callerid.h"
00097 #include "asterisk/adsi.h"
00098 #include "asterisk/cli.h"
00099 #include "asterisk/cdr.h"
00100 #include "asterisk/cel.h"
00101 #include "asterisk/features.h"
00102 #include "asterisk/musiconhold.h"
00103 #include "asterisk/say.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/app.h"
00106 #include "asterisk/dsp.h"
00107 #include "asterisk/astdb.h"
00108 #include "asterisk/manager.h"
00109 #include "asterisk/causes.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/utils.h"
00112 #include "asterisk/transcap.h"
00113 #include "asterisk/stringfields.h"
00114 #include "asterisk/abstract_jb.h"
00115 #include "asterisk/smdi.h"
00116 #include "asterisk/astobj.h"
00117 #include "asterisk/event.h"
00118 #include "asterisk/devicestate.h"
00119 #include "asterisk/paths.h"
00120 #include "asterisk/ccss.h"
00121 #include "asterisk/data.h"
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 #define SMDI_MD_WAIT_TIMEOUT 1500
00276
00277 static const char * const lbostr[] = {
00278 "0 db (CSU)/0-133 feet (DSX-1)",
00279 "133-266 feet (DSX-1)",
00280 "266-399 feet (DSX-1)",
00281 "399-533 feet (DSX-1)",
00282 "533-655 feet (DSX-1)",
00283 "-7.5db (CSU)",
00284 "-15db (CSU)",
00285 "-22.5db (CSU)"
00286 };
00287
00288
00289
00290 static struct ast_jb_conf default_jbconf =
00291 {
00292 .flags = 0,
00293 .max_size = 200,
00294 .resync_threshold = 1000,
00295 .impl = "fixed",
00296 .target_extra = 40,
00297 };
00298 static struct ast_jb_conf global_jbconf;
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 #define DEFAULT_CIDRINGS 1
00313
00314 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00315
00316
00317
00318 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00319
00320 static const char tdesc[] = "DAHDI Telephony Driver"
00321 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00322 " w/"
00323 #if defined(HAVE_PRI)
00324 "PRI"
00325 #endif
00326 #if defined(HAVE_SS7)
00327 #if defined(HAVE_PRI)
00328 " & "
00329 #endif
00330 "SS7"
00331 #endif
00332 #if defined(HAVE_OPENR2)
00333 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00334 " & "
00335 #endif
00336 "MFC/R2"
00337 #endif
00338 #endif
00339 ;
00340
00341 static const char config[] = "chan_dahdi.conf";
00342
00343 #define SIG_EM DAHDI_SIG_EM
00344 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00345 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00346 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00347 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00348 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00349 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00350 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00351 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00352 #define SIG_FXSLS DAHDI_SIG_FXSLS
00353 #define SIG_FXSGS DAHDI_SIG_FXSGS
00354 #define SIG_FXSKS DAHDI_SIG_FXSKS
00355 #define SIG_FXOLS DAHDI_SIG_FXOLS
00356 #define SIG_FXOGS DAHDI_SIG_FXOGS
00357 #define SIG_FXOKS DAHDI_SIG_FXOKS
00358 #define SIG_PRI DAHDI_SIG_CLEAR
00359 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00360 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00361 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00362 #define SIG_MFCR2 DAHDI_SIG_CAS
00363 #define SIG_SF DAHDI_SIG_SF
00364 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00365 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00366 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00367 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00368 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00369
00370 #ifdef LOTS_OF_SPANS
00371 #define NUM_SPANS DAHDI_MAX_SPANS
00372 #else
00373 #define NUM_SPANS 32
00374 #endif
00375
00376 #define CHAN_PSEUDO -2
00377
00378 #define CALLPROGRESS_PROGRESS 1
00379 #define CALLPROGRESS_FAX_OUTGOING 2
00380 #define CALLPROGRESS_FAX_INCOMING 4
00381 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00382
00383 #define NUM_CADENCE_MAX 25
00384 static int num_cadence = 4;
00385 static int user_has_defined_cadences = 0;
00386
00387 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00388 { { 125, 125, 2000, 4000 } },
00389 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00390 { { 125, 125, 125, 125, 125, 4000 } },
00391 { { 1000, 500, 2500, 5000 } },
00392 };
00393
00394
00395
00396
00397
00398 static int cidrings[NUM_CADENCE_MAX] = {
00399 2,
00400 4,
00401 3,
00402 2,
00403 };
00404
00405
00406 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00407
00408 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00409 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00410
00411 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00412 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00413
00414 static char defaultcic[64] = "";
00415 static char defaultozz[64] = "";
00416
00417
00418 static char mwimonitornotify[PATH_MAX] = "";
00419 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00420 static int mwisend_rpas = 0;
00421 #endif
00422
00423 static char progzone[10] = "";
00424
00425 static int usedistinctiveringdetection = 0;
00426 static int distinctiveringaftercid = 0;
00427
00428 static int numbufs = 4;
00429
00430 static int mwilevel = 512;
00431 static int dtmfcid_level = 256;
00432
00433 #define REPORT_CHANNEL_ALARMS 1
00434 #define REPORT_SPAN_ALARMS 2
00435 static int report_alarms = REPORT_CHANNEL_ALARMS;
00436
00437 #ifdef HAVE_PRI
00438 static int pridebugfd = -1;
00439 static char pridebugfilename[1024] = "";
00440 #endif
00441
00442
00443 static int firstdigittimeout = 16000;
00444
00445
00446 static int gendigittimeout = 8000;
00447
00448
00449 static int matchdigittimeout = 3000;
00450
00451
00452 AST_MUTEX_DEFINE_STATIC(iflock);
00453
00454
00455 static int ifcount = 0;
00456
00457 #ifdef HAVE_PRI
00458 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00459 #endif
00460
00461
00462
00463 AST_MUTEX_DEFINE_STATIC(monlock);
00464
00465
00466
00467 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00468 static ast_cond_t ss_thread_complete;
00469 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00470 AST_MUTEX_DEFINE_STATIC(restart_lock);
00471 static int ss_thread_count = 0;
00472 static int num_restart_pending = 0;
00473
00474 static int restart_monitor(void);
00475
00476 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00477
00478 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00479
00480 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00481 {
00482
00483
00484
00485
00486 }
00487
00488
00489 static inline int dahdi_get_event(int fd)
00490 {
00491 int j;
00492 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00493 return -1;
00494 return j;
00495 }
00496
00497
00498 static inline int dahdi_wait_event(int fd)
00499 {
00500 int i, j = 0;
00501 i = DAHDI_IOMUX_SIGEVENT;
00502 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00503 return -1;
00504 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00505 return -1;
00506 return j;
00507 }
00508
00509
00510 #define READ_SIZE 160
00511
00512 #define MASK_AVAIL (1 << 0)
00513 #define MASK_INUSE (1 << 1)
00514
00515 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00516 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00517 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00518 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00519 #define MIN_MS_SINCE_FLASH ((2000) )
00520 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00521
00522 struct dahdi_pvt;
00523
00524
00525
00526
00527
00528 static int ringt_base = DEFAULT_RINGT;
00529
00530 #if defined(HAVE_SS7)
00531
00532 struct dahdi_ss7 {
00533 struct sig_ss7_linkset ss7;
00534 };
00535
00536 static struct dahdi_ss7 linksets[NUM_SPANS];
00537
00538 static int cur_ss7type = -1;
00539 static int cur_linkset = -1;
00540 static int cur_pointcode = -1;
00541 static int cur_cicbeginswith = -1;
00542 static int cur_adjpointcode = -1;
00543 static int cur_networkindicator = -1;
00544 static int cur_defaultdpc = -1;
00545 #endif
00546
00547 #ifdef HAVE_OPENR2
00548 struct dahdi_mfcr2 {
00549 pthread_t r2master;
00550 openr2_context_t *protocol_context;
00551 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00552 int numchans;
00553 int monitored_count;
00554 };
00555
00556 struct dahdi_mfcr2_conf {
00557 openr2_variant_t variant;
00558 int mfback_timeout;
00559 int metering_pulse_timeout;
00560 int max_ani;
00561 int max_dnis;
00562 signed int get_ani_first:2;
00563 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00564 signed int skip_category_request:2;
00565 #endif
00566 unsigned int call_files:1;
00567 unsigned int allow_collect_calls:1;
00568 unsigned int charge_calls:1;
00569 unsigned int accept_on_offer:1;
00570 unsigned int forced_release:1;
00571 unsigned int double_answer:1;
00572 signed int immediate_accept:2;
00573 char logdir[OR2_MAX_PATH];
00574 char r2proto_file[OR2_MAX_PATH];
00575 openr2_log_level_t loglevel;
00576 openr2_calling_party_category_t category;
00577 };
00578
00579
00580 static struct dahdi_mfcr2 **r2links;
00581
00582 static int r2links_count = 0;
00583
00584 #endif
00585
00586 #ifdef HAVE_PRI
00587
00588 struct dahdi_pri {
00589 int dchannels[SIG_PRI_NUM_DCHANS];
00590 int mastertrunkgroup;
00591 int prilogicalspan;
00592 struct sig_pri_span pri;
00593 };
00594
00595 static struct dahdi_pri pris[NUM_SPANS];
00596
00597 #if defined(HAVE_PRI_CCSS)
00598
00599 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00600 #endif
00601
00602 #else
00603
00604 struct dahdi_pri;
00605 #endif
00606
00607 #define SUB_REAL 0
00608 #define SUB_CALLWAIT 1
00609 #define SUB_THREEWAY 2
00610
00611
00612 #define POLARITY_IDLE 0
00613 #define POLARITY_REV 1
00614
00615
00616 struct distRingData {
00617 int ring[3];
00618 int range;
00619 };
00620 struct ringContextData {
00621 char contextData[AST_MAX_CONTEXT];
00622 };
00623 struct dahdi_distRings {
00624 struct distRingData ringnum[3];
00625 struct ringContextData ringContext[3];
00626 };
00627
00628 static const char * const subnames[] = {
00629 "Real",
00630 "Callwait",
00631 "Threeway"
00632 };
00633
00634 struct dahdi_subchannel {
00635 int dfd;
00636 struct ast_channel *owner;
00637 int chan;
00638 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00639 struct ast_frame f;
00640 unsigned int needringing:1;
00641 unsigned int needbusy:1;
00642 unsigned int needcongestion:1;
00643 unsigned int needanswer:1;
00644 unsigned int needflash:1;
00645 unsigned int needhold:1;
00646 unsigned int needunhold:1;
00647 unsigned int linear:1;
00648 unsigned int inthreeway:1;
00649 struct dahdi_confinfo curconf;
00650 };
00651
00652 #define CONF_USER_REAL (1 << 0)
00653 #define CONF_USER_THIRDCALL (1 << 1)
00654
00655 #define MAX_SLAVES 4
00656
00657
00658
00659
00660 typedef enum {
00661 MWI_SEND_NULL = 0,
00662 MWI_SEND_SA,
00663 MWI_SEND_SA_WAIT,
00664 MWI_SEND_PAUSE,
00665 MWI_SEND_SPILL,
00666 MWI_SEND_CLEANUP,
00667 MWI_SEND_DONE,
00668 } mwisend_states;
00669
00670 struct mwisend_info {
00671 struct timeval pause;
00672 mwisend_states mwisend_current;
00673 };
00674
00675
00676 enum DAHDI_IFLIST {
00677 DAHDI_IFLIST_NONE,
00678 DAHDI_IFLIST_MAIN,
00679 #if defined(HAVE_PRI)
00680 DAHDI_IFLIST_NO_B_CHAN,
00681 #endif
00682 };
00683
00684 struct dahdi_pvt {
00685 ast_mutex_t lock;
00686 struct callerid_state *cs;
00687 struct ast_channel *owner;
00688
00689
00690 struct dahdi_subchannel sub_unused;
00691 struct dahdi_subchannel subs[3];
00692 struct dahdi_confinfo saveconf;
00693
00694 struct dahdi_pvt *slaves[MAX_SLAVES];
00695 struct dahdi_pvt *master;
00696 int inconference;
00697
00698 int bufsize;
00699 int buf_no;
00700 int buf_policy;
00701 int faxbuf_no;
00702 int faxbuf_policy;
00703 int sig;
00704
00705
00706
00707
00708 int radio;
00709 int outsigmod;
00710 int oprmode;
00711 struct dahdi_pvt *oprpeer;
00712
00713 float cid_rxgain;
00714
00715 float rxgain;
00716
00717 float txgain;
00718
00719 float txdrc;
00720 float rxdrc;
00721
00722 int tonezone;
00723 enum DAHDI_IFLIST which_iflist;
00724 struct dahdi_pvt *next;
00725 struct dahdi_pvt *prev;
00726
00727
00728
00729
00730
00731
00732
00733 unsigned int adsi:1;
00734
00735
00736
00737
00738
00739 unsigned int answeronpolarityswitch:1;
00740
00741
00742
00743
00744
00745 unsigned int busydetect:1;
00746
00747
00748
00749
00750
00751 unsigned int callreturn:1;
00752
00753
00754
00755
00756
00757
00758 unsigned int callwaiting:1;
00759
00760
00761
00762
00763 unsigned int callwaitingcallerid:1;
00764
00765
00766
00767
00768
00769
00770 unsigned int cancallforward:1;
00771
00772
00773
00774
00775 unsigned int canpark:1;
00776
00777 unsigned int confirmanswer:1;
00778
00779
00780
00781
00782 unsigned int destroy:1;
00783 unsigned int didtdd:1;
00784
00785 unsigned int dialednone:1;
00786
00787
00788
00789
00790 unsigned int dialing:1;
00791
00792 unsigned int digital:1;
00793
00794 unsigned int dnd:1;
00795
00796 unsigned int echobreak:1;
00797
00798
00799
00800
00801
00802 unsigned int echocanbridged:1;
00803
00804 unsigned int echocanon:1;
00805
00806 unsigned int faxhandled:1;
00807
00808 unsigned int usefaxbuffers:1;
00809
00810 unsigned int bufferoverrideinuse:1;
00811
00812 unsigned int firstradio:1;
00813
00814
00815
00816
00817 unsigned int hanguponpolarityswitch:1;
00818
00819 unsigned int hardwaredtmf:1;
00820
00821
00822
00823
00824
00825
00826 unsigned int hidecallerid:1;
00827
00828
00829
00830
00831
00832 unsigned int hidecalleridname:1;
00833
00834 unsigned int ignoredtmf:1;
00835
00836
00837
00838
00839
00840 unsigned int immediate:1;
00841
00842 unsigned int inalarm:1;
00843
00844 unsigned int mate:1;
00845
00846 unsigned int outgoing:1;
00847
00848
00849
00850
00851
00852
00853 unsigned int permcallwaiting:1;
00854
00855
00856
00857
00858 unsigned int permhidecallerid:1;
00859
00860
00861
00862
00863 unsigned int priindication_oob:1;
00864
00865
00866
00867
00868 unsigned int priexclusive:1;
00869
00870
00871
00872
00873 unsigned int pulse:1;
00874
00875 unsigned int pulsedial:1;
00876 unsigned int restartpending:1;
00877
00878
00879
00880
00881
00882 unsigned int restrictcid:1;
00883
00884
00885
00886
00887 unsigned int threewaycalling:1;
00888
00889
00890
00891
00892
00893
00894
00895
00896 unsigned int transfer:1;
00897
00898
00899
00900
00901
00902
00903
00904 unsigned int use_callerid:1;
00905
00906
00907
00908
00909
00910
00911 unsigned int use_callingpres:1;
00912
00913
00914
00915
00916
00917 unsigned int usedistinctiveringdetection:1;
00918
00919
00920
00921
00922 unsigned int dahditrcallerid:1;
00923
00924
00925
00926
00927 unsigned int transfertobusy:1;
00928
00929
00930
00931
00932 unsigned int mwimonitor_neon:1;
00933
00934
00935
00936
00937 unsigned int mwimonitor_fsk:1;
00938
00939
00940
00941
00942
00943 unsigned int mwimonitor_rpas:1;
00944
00945 unsigned int mwimonitoractive:1;
00946
00947 unsigned int mwisendactive:1;
00948
00949
00950
00951
00952 unsigned int inservice:1;
00953
00954
00955
00956
00957 unsigned int locallyblocked:1;
00958
00959
00960
00961
00962 unsigned int remotelyblocked:1;
00963
00964
00965
00966
00967 unsigned int manages_span_alarms:1;
00968
00969 #if defined(HAVE_PRI)
00970 struct sig_pri_span *pri;
00971 int logicalspan;
00972 #endif
00973
00974
00975
00976
00977 unsigned int use_smdi:1;
00978 struct mwisend_info mwisend_data;
00979
00980 struct ast_smdi_interface *smdi_iface;
00981
00982
00983 struct dahdi_distRings drings;
00984
00985
00986
00987
00988
00989 char context[AST_MAX_CONTEXT];
00990
00991
00992
00993 char defcontext[AST_MAX_CONTEXT];
00994
00995 char exten[AST_MAX_EXTENSION];
00996
00997
00998
00999
01000 char language[MAX_LANGUAGE];
01001
01002
01003
01004
01005 char mohinterpret[MAX_MUSICCLASS];
01006
01007
01008
01009
01010 char mohsuggest[MAX_MUSICCLASS];
01011 char parkinglot[AST_MAX_EXTENSION];
01012 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01013
01014 char cid_ani[AST_MAX_EXTENSION];
01015 #endif
01016
01017 int cid_ani2;
01018
01019 char cid_num[AST_MAX_EXTENSION];
01020
01021
01022
01023
01024 char cid_tag[AST_MAX_EXTENSION];
01025
01026 int cid_ton;
01027
01028 char cid_name[AST_MAX_EXTENSION];
01029
01030 char cid_subaddr[AST_MAX_EXTENSION];
01031 char *origcid_num;
01032 char *origcid_name;
01033
01034 char callwait_num[AST_MAX_EXTENSION];
01035
01036 char callwait_name[AST_MAX_EXTENSION];
01037
01038 char rdnis[AST_MAX_EXTENSION];
01039
01040 char dnid[AST_MAX_EXTENSION];
01041
01042
01043
01044
01045 ast_group_t group;
01046
01047 int law_default;
01048
01049 int law;
01050 int confno;
01051 int confusers;
01052 int propconfno;
01053
01054
01055
01056
01057 ast_group_t callgroup;
01058
01059
01060
01061
01062 ast_group_t pickupgroup;
01063
01064
01065
01066
01067 struct ast_variable *vars;
01068 int channel;
01069 int span;
01070 time_t guardtime;
01071 int cid_signalling;
01072 int cid_start;
01073 int dtmfcid_holdoff_state;
01074 struct timeval dtmfcid_delay;
01075 int callingpres;
01076 int callwaitingrepeat;
01077 int cidcwexpire;
01078 int cid_suppress_expire;
01079
01080 unsigned char *cidspill;
01081
01082 int cidpos;
01083
01084 int cidlen;
01085
01086 int ringt;
01087
01088
01089
01090
01091 int ringt_base;
01092
01093
01094
01095
01096
01097
01098 int stripmsd;
01099
01100
01101
01102
01103
01104
01105 int callwaitcas;
01106
01107 int callwaitrings;
01108
01109 struct {
01110 struct dahdi_echocanparams head;
01111 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01112 } echocancel;
01113
01114
01115
01116
01117 int echotraining;
01118
01119 char echorest[20];
01120
01121
01122
01123
01124 int busycount;
01125
01126
01127
01128
01129 int busy_tonelength;
01130
01131
01132
01133
01134 int busy_quietlength;
01135
01136
01137
01138
01139 int callprogress;
01140
01141
01142
01143
01144 int waitfordialtone;
01145 struct timeval waitingfordt;
01146 struct timeval flashtime;
01147
01148 struct ast_dsp *dsp;
01149
01150 struct dahdi_dialoperation dop;
01151 int whichwink;
01152
01153 char finaldial[64];
01154 char accountcode[AST_MAX_ACCOUNT_CODE];
01155 int amaflags;
01156 struct tdd_state *tdd;
01157
01158 char call_forward[AST_MAX_EXTENSION];
01159
01160
01161
01162
01163 char mailbox[AST_MAX_EXTENSION];
01164
01165 struct ast_event_sub *mwi_event_sub;
01166
01167 char dialdest[256];
01168 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01169 struct dahdi_vmwi_info mwisend_setting;
01170 unsigned int mwisend_fsk: 1;
01171 unsigned int mwisend_rpas:1;
01172 #endif
01173 int distinctivering;
01174 int dtmfrelax;
01175
01176 int fake_event;
01177
01178
01179
01180
01181 int polarityonanswerdelay;
01182
01183 struct timeval polaritydelaytv;
01184
01185
01186
01187
01188 int sendcalleridafter;
01189
01190 int polarity;
01191
01192 int dsp_features;
01193 #if defined(HAVE_SS7)
01194
01195 struct sig_ss7_linkset *ss7;
01196 #endif
01197 #ifdef HAVE_OPENR2
01198 struct dahdi_mfcr2 *mfcr2;
01199 openr2_chan_t *r2chan;
01200 openr2_calling_party_category_t mfcr2_recvd_category;
01201 openr2_calling_party_category_t mfcr2_category;
01202 int mfcr2_dnis_index;
01203 int mfcr2_ani_index;
01204 int mfcr2call:1;
01205 int mfcr2_answer_pending:1;
01206 int mfcr2_charge_calls:1;
01207 int mfcr2_allow_collect_calls:1;
01208 int mfcr2_forced_release:1;
01209 int mfcr2_dnis_matched:1;
01210 int mfcr2_call_accepted:1;
01211 int mfcr2_progress:1;
01212 int mfcr2_accept_on_offer:1;
01213 #endif
01214
01215 char begindigit;
01216
01217 int muting;
01218 void *sig_pvt;
01219 struct ast_cc_config_params *cc_params;
01220
01221
01222
01223
01224
01225
01226 char dialstring[AST_CHANNEL_NAME];
01227 };
01228
01229 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01230 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01231 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01232 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01233 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01234 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01235 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01236 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01237 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01238 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01239 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01240 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01241 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01242 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01291 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01292 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01293 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01294 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01295 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01296 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01297
01298 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01299
01300 static struct dahdi_pvt *iflist = NULL;
01301 static struct dahdi_pvt *ifend = NULL;
01302
01303 #if defined(HAVE_PRI)
01304 static struct dahdi_parms_pseudo {
01305 int buf_no;
01306 int buf_policy;
01307 int faxbuf_no;
01308 int faxbuf_policy;
01309 } dahdi_pseudo_parms;
01310 #endif
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322 struct dahdi_chan_conf {
01323 struct dahdi_pvt chan;
01324 #ifdef HAVE_PRI
01325 struct dahdi_pri pri;
01326 #endif
01327
01328 #if defined(HAVE_SS7)
01329 struct dahdi_ss7 ss7;
01330 #endif
01331
01332 #ifdef HAVE_OPENR2
01333 struct dahdi_mfcr2_conf mfcr2;
01334 #endif
01335 struct dahdi_params timing;
01336 int is_sig_auto;
01337
01338 int ignore_failed_channels;
01339
01340
01341
01342
01343
01344 char smdi_port[SMDI_MAX_FILENAME_LEN];
01345 };
01346
01347
01348 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01349 {
01350
01351
01352
01353 struct dahdi_chan_conf conf = {
01354 #ifdef HAVE_PRI
01355 .pri.pri = {
01356 .nsf = PRI_NSF_NONE,
01357 .switchtype = PRI_SWITCH_NI2,
01358 .dialplan = PRI_UNKNOWN + 1,
01359 .localdialplan = PRI_NATIONAL_ISDN + 1,
01360 .nodetype = PRI_CPE,
01361 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01362
01363 #if defined(HAVE_PRI_CCSS)
01364 .cc_ptmp_recall_mode = 1,
01365 .cc_qsig_signaling_link_req = 1,
01366 .cc_qsig_signaling_link_rsp = 1,
01367 #endif
01368
01369 .minunused = 2,
01370 .idleext = "",
01371 .idledial = "",
01372 .internationalprefix = "",
01373 .nationalprefix = "",
01374 .localprefix = "",
01375 .privateprefix = "",
01376 .unknownprefix = "",
01377 .resetinterval = -1,
01378 },
01379 #endif
01380 #if defined(HAVE_SS7)
01381 .ss7.ss7 = {
01382 .called_nai = SS7_NAI_NATIONAL,
01383 .calling_nai = SS7_NAI_NATIONAL,
01384 .internationalprefix = "",
01385 .nationalprefix = "",
01386 .subscriberprefix = "",
01387 .unknownprefix = ""
01388 },
01389 #endif
01390 #ifdef HAVE_OPENR2
01391 .mfcr2 = {
01392 .variant = OR2_VAR_ITU,
01393 .mfback_timeout = -1,
01394 .metering_pulse_timeout = -1,
01395 .max_ani = 10,
01396 .max_dnis = 4,
01397 .get_ani_first = -1,
01398 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01399 .skip_category_request = -1,
01400 #endif
01401 .call_files = 0,
01402 .allow_collect_calls = 0,
01403 .charge_calls = 1,
01404 .accept_on_offer = 1,
01405 .forced_release = 0,
01406 .double_answer = 0,
01407 .immediate_accept = -1,
01408 .logdir = "",
01409 .r2proto_file = "",
01410 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01411 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01412 },
01413 #endif
01414 .chan = {
01415 .context = "default",
01416 .cid_num = "",
01417 .cid_name = "",
01418 .cid_tag = "",
01419 .mohinterpret = "default",
01420 .mohsuggest = "",
01421 .parkinglot = "",
01422 .transfertobusy = 1,
01423
01424 .cid_signalling = CID_SIG_BELL,
01425 .cid_start = CID_START_RING,
01426 .dahditrcallerid = 0,
01427 .use_callerid = 1,
01428 .sig = -1,
01429 .outsigmod = -1,
01430
01431 .cid_rxgain = +5.0,
01432
01433 .tonezone = -1,
01434
01435 .echocancel.head.tap_length = 1,
01436
01437 .busycount = 3,
01438
01439 .accountcode = "",
01440
01441 .mailbox = "",
01442
01443 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01444 .mwisend_fsk = 1,
01445 #endif
01446 .polarityonanswerdelay = 600,
01447
01448 .sendcalleridafter = DEFAULT_CIDRINGS,
01449
01450 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01451 .buf_no = numbufs,
01452 .usefaxbuffers = 0,
01453 .cc_params = ast_cc_config_params_init(),
01454 },
01455 .timing = {
01456 .prewinktime = -1,
01457 .preflashtime = -1,
01458 .winktime = -1,
01459 .flashtime = -1,
01460 .starttime = -1,
01461 .rxwinktime = -1,
01462 .rxflashtime = -1,
01463 .debouncetime = -1
01464 },
01465 .is_sig_auto = 1,
01466 .smdi_port = "/dev/ttyS0",
01467 };
01468
01469 return conf;
01470 }
01471
01472
01473 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01474 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01475 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01476 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01477 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01478 static int dahdi_hangup(struct ast_channel *ast);
01479 static int dahdi_answer(struct ast_channel *ast);
01480 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01481 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01482 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01483 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01484 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01485 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01486 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01487 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01488 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01489 static int dahdi_devicestate(void *data);
01490 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01491
01492 static const struct ast_channel_tech dahdi_tech = {
01493 .type = "DAHDI",
01494 .description = tdesc,
01495 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01496 .requester = dahdi_request,
01497 .send_digit_begin = dahdi_digit_begin,
01498 .send_digit_end = dahdi_digit_end,
01499 .send_text = dahdi_sendtext,
01500 .call = dahdi_call,
01501 .hangup = dahdi_hangup,
01502 .answer = dahdi_answer,
01503 .read = dahdi_read,
01504 .write = dahdi_write,
01505 .bridge = dahdi_bridge,
01506 .exception = dahdi_exception,
01507 .indicate = dahdi_indicate,
01508 .fixup = dahdi_fixup,
01509 .setoption = dahdi_setoption,
01510 .queryoption = dahdi_queryoption,
01511 .func_channel_read = dahdi_func_read,
01512 .func_channel_write = dahdi_func_write,
01513 .devicestate = dahdi_devicestate,
01514 .cc_callback = dahdi_cc_callback,
01515 };
01516
01517 #define GET_CHANNEL(p) ((p)->channel)
01518
01519 #define SIG_PRI_LIB_HANDLE_CASES \
01520 SIG_PRI: \
01521 case SIG_BRI: \
01522 case SIG_BRI_PTMP
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533 static inline int dahdi_sig_pri_lib_handles(int signaling)
01534 {
01535 int handles;
01536
01537 switch (signaling) {
01538 case SIG_PRI_LIB_HANDLE_CASES:
01539 handles = 1;
01540 break;
01541 default:
01542 handles = 0;
01543 break;
01544 }
01545
01546 return handles;
01547 }
01548
01549 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01550 {
01551 switch (sig) {
01552 case SIG_FXOLS:
01553 return ANALOG_SIG_FXOLS;
01554 case SIG_FXOGS:
01555 return ANALOG_SIG_FXOGS;
01556 case SIG_FXOKS:
01557 return ANALOG_SIG_FXOKS;
01558 case SIG_FXSLS:
01559 return ANALOG_SIG_FXSLS;
01560 case SIG_FXSGS:
01561 return ANALOG_SIG_FXSGS;
01562 case SIG_FXSKS:
01563 return ANALOG_SIG_FXSKS;
01564 case SIG_EMWINK:
01565 return ANALOG_SIG_EMWINK;
01566 case SIG_EM:
01567 return ANALOG_SIG_EM;
01568 case SIG_EM_E1:
01569 return ANALOG_SIG_EM_E1;
01570 case SIG_FEATD:
01571 return ANALOG_SIG_FEATD;
01572 case SIG_FEATDMF:
01573 return ANALOG_SIG_FEATDMF;
01574 case SIG_E911:
01575 return SIG_E911;
01576 case SIG_FGC_CAMA:
01577 return ANALOG_SIG_FGC_CAMA;
01578 case SIG_FGC_CAMAMF:
01579 return ANALOG_SIG_FGC_CAMAMF;
01580 case SIG_FEATB:
01581 return ANALOG_SIG_FEATB;
01582 case SIG_SFWINK:
01583 return ANALOG_SIG_SFWINK;
01584 case SIG_SF:
01585 return ANALOG_SIG_SF;
01586 case SIG_SF_FEATD:
01587 return ANALOG_SIG_SF_FEATD;
01588 case SIG_SF_FEATDMF:
01589 return ANALOG_SIG_SF_FEATDMF;
01590 case SIG_FEATDMF_TA:
01591 return ANALOG_SIG_FEATDMF_TA;
01592 case SIG_SF_FEATB:
01593 return ANALOG_SIG_FEATB;
01594 default:
01595 return -1;
01596 }
01597 }
01598
01599
01600 static int analog_tone_to_dahditone(enum analog_tone tone)
01601 {
01602 switch (tone) {
01603 case ANALOG_TONE_RINGTONE:
01604 return DAHDI_TONE_RINGTONE;
01605 case ANALOG_TONE_STUTTER:
01606 return DAHDI_TONE_STUTTER;
01607 case ANALOG_TONE_CONGESTION:
01608 return DAHDI_TONE_CONGESTION;
01609 case ANALOG_TONE_DIALTONE:
01610 return DAHDI_TONE_DIALTONE;
01611 case ANALOG_TONE_DIALRECALL:
01612 return DAHDI_TONE_DIALRECALL;
01613 case ANALOG_TONE_INFO:
01614 return DAHDI_TONE_INFO;
01615 default:
01616 return -1;
01617 }
01618 }
01619
01620 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01621 {
01622 int index;
01623
01624 switch (analogsub) {
01625 case ANALOG_SUB_REAL:
01626 index = SUB_REAL;
01627 break;
01628 case ANALOG_SUB_CALLWAIT:
01629 index = SUB_CALLWAIT;
01630 break;
01631 case ANALOG_SUB_THREEWAY:
01632 index = SUB_THREEWAY;
01633 break;
01634 default:
01635 ast_log(LOG_ERROR, "Unidentified sub!\n");
01636 index = SUB_REAL;
01637 }
01638
01639 return index;
01640 }
01641
01642 static enum analog_event dahdievent_to_analogevent(int event);
01643 static int bump_gains(struct dahdi_pvt *p);
01644 static int dahdi_setlinear(int dfd, int linear);
01645
01646 static int my_start_cid_detect(void *pvt, int cid_signalling)
01647 {
01648 struct dahdi_pvt *p = pvt;
01649 int index = SUB_REAL;
01650 p->cs = callerid_new(cid_signalling);
01651 if (!p->cs) {
01652 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01653 return -1;
01654 }
01655 bump_gains(p);
01656 dahdi_setlinear(p->subs[index].dfd, 0);
01657
01658 return 0;
01659 }
01660
01661 static int my_stop_cid_detect(void *pvt)
01662 {
01663 struct dahdi_pvt *p = pvt;
01664 int index = SUB_REAL;
01665 if (p->cs)
01666 callerid_free(p->cs);
01667 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01668 return 0;
01669 }
01670
01671 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01672 {
01673 struct dahdi_pvt *p = pvt;
01674 struct analog_pvt *analog_p = p->sig_pvt;
01675 struct pollfd poller;
01676 char *name, *num;
01677 int index = SUB_REAL;
01678 int res;
01679 unsigned char buf[256];
01680 int flags;
01681
01682 poller.fd = p->subs[SUB_REAL].dfd;
01683 poller.events = POLLPRI | POLLIN;
01684 poller.revents = 0;
01685
01686 res = poll(&poller, 1, timeout);
01687
01688 if (poller.revents & POLLPRI) {
01689 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01690 return 1;
01691 }
01692
01693 if (poller.revents & POLLIN) {
01694
01695
01696
01697
01698
01699 res = read(p->subs[index].dfd, buf, sizeof(buf));
01700 if (res < 0) {
01701 if (errno != ELAST) {
01702 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01703 callerid_free(p->cs);
01704 return -1;
01705 }
01706 }
01707
01708 if (analog_p->ringt > 0) {
01709 if (!(--analog_p->ringt)) {
01710
01711 return -1;
01712 }
01713 }
01714
01715 if (p->cid_signalling == CID_SIG_V23_JP) {
01716 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01717 } else {
01718 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01719 }
01720 if (res < 0) {
01721
01722
01723
01724
01725 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01726 return -1;
01727 }
01728
01729 if (res == 1) {
01730 callerid_get(p->cs, &name, &num, &flags);
01731 if (name)
01732 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01733 if (num)
01734 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01735
01736 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01737 return 0;
01738 }
01739 }
01740
01741 *ev = ANALOG_EVENT_NONE;
01742 return 2;
01743 }
01744
01745 static const char *event2str(int event);
01746 static int restore_gains(struct dahdi_pvt *p);
01747
01748 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01749 {
01750 unsigned char buf[256];
01751 int distMatches;
01752 int curRingData[RING_PATTERNS];
01753 int receivedRingT;
01754 int counter1;
01755 int counter;
01756 int i;
01757 int res;
01758 int checkaftercid = 0;
01759
01760 struct dahdi_pvt *p = pvt;
01761 struct analog_pvt *analog_p = p->sig_pvt;
01762
01763 if (ringdata == NULL) {
01764 ringdata = curRingData;
01765 } else {
01766 checkaftercid = 1;
01767 }
01768
01769
01770
01771 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01772
01773 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01774 ringdata[receivedRingT] = 0;
01775 receivedRingT = 0;
01776 if (checkaftercid && distinctiveringaftercid)
01777 ast_verb(3, "Detecting post-CID distinctive ring\n");
01778
01779 else if (strcmp(p->context,p->defcontext) != 0) {
01780 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01781 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01782 }
01783
01784 for (;;) {
01785 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01786 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01787 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01788 ast_hangup(chan);
01789 return 1;
01790 }
01791 if (i & DAHDI_IOMUX_SIGEVENT) {
01792 res = dahdi_get_event(p->subs[idx].dfd);
01793 if (res == DAHDI_EVENT_NOALARM) {
01794 p->inalarm = 0;
01795 analog_p->inalarm = 0;
01796 }
01797 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01798 res = 0;
01799
01800
01801 ringdata[receivedRingT] = analog_p->ringt;
01802
01803 if (analog_p->ringt < analog_p->ringt_base/2)
01804 break;
01805
01806
01807 if (++receivedRingT == RING_PATTERNS)
01808 break;
01809 } else if (i & DAHDI_IOMUX_READ) {
01810 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01811 if (res < 0) {
01812 if (errno != ELAST) {
01813 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01814 ast_hangup(chan);
01815 return 1;
01816 }
01817 break;
01818 }
01819 if (analog_p->ringt > 0) {
01820 if (!(--analog_p->ringt)) {
01821 res = -1;
01822 break;
01823 }
01824 }
01825 }
01826 }
01827 }
01828 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01829
01830 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01831 for (counter = 0; counter < 3; counter++) {
01832
01833 distMatches = 0;
01834
01835 ast_verb(3, "Checking %d,%d,%d\n",
01836 p->drings.ringnum[counter].ring[0],
01837 p->drings.ringnum[counter].ring[1],
01838 p->drings.ringnum[counter].ring[2]);
01839 for (counter1 = 0; counter1 < 3; counter1++) {
01840 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01841 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01842 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01843 ringdata[counter1]);
01844 distMatches++;
01845 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01846 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01847 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01848 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01849 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01850 distMatches++;
01851 }
01852 }
01853
01854 if (distMatches == 3) {
01855
01856 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01857 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01858 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01859 break;
01860 }
01861 }
01862 }
01863
01864 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01865 restore_gains(p);
01866
01867 return 0;
01868 }
01869
01870 static int my_stop_callwait(void *pvt)
01871 {
01872 struct dahdi_pvt *p = pvt;
01873 p->callwaitingrepeat = 0;
01874 p->cidcwexpire = 0;
01875 p->cid_suppress_expire = 0;
01876
01877 return 0;
01878 }
01879
01880 static int send_callerid(struct dahdi_pvt *p);
01881 static int save_conference(struct dahdi_pvt *p);
01882 static int restore_conference(struct dahdi_pvt *p);
01883
01884 static int my_callwait(void *pvt)
01885 {
01886 struct dahdi_pvt *p = pvt;
01887 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01888 if (p->cidspill) {
01889 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01890 ast_free(p->cidspill);
01891 }
01892
01893
01894
01895
01896
01897 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01898 return -1;
01899 save_conference(p);
01900
01901 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01902 if (!p->callwaitrings && p->callwaitingcallerid) {
01903 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01904 p->callwaitcas = 1;
01905 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01906 } else {
01907 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01908 p->callwaitcas = 0;
01909 p->cidlen = 2400 + READ_SIZE * 4;
01910 }
01911 p->cidpos = 0;
01912 send_callerid(p);
01913
01914 return 0;
01915 }
01916
01917 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01918 {
01919 struct dahdi_pvt *p = pvt;
01920
01921 ast_debug(2, "Starting cid spill\n");
01922
01923 if (p->cidspill) {
01924 ast_log(LOG_WARNING, "cidspill already exists??\n");
01925 ast_free(p->cidspill);
01926 }
01927
01928 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01929 if (cwcid == 0) {
01930 p->cidlen = ast_callerid_generate(p->cidspill,
01931 caller->id.name.str,
01932 caller->id.number.str,
01933 AST_LAW(p));
01934 } else {
01935 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01936 caller->id.name.str, caller->id.number.str);
01937 p->callwaitcas = 0;
01938 p->cidcwexpire = 0;
01939 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01940 caller->id.name.str,
01941 caller->id.number.str,
01942 AST_LAW(p));
01943 p->cidlen += READ_SIZE * 4;
01944 }
01945 p->cidpos = 0;
01946 p->cid_suppress_expire = 0;
01947 send_callerid(p);
01948 }
01949 return 0;
01950 }
01951
01952 static int my_dsp_reset_and_flush_digits(void *pvt)
01953 {
01954 struct dahdi_pvt *p = pvt;
01955 if (p->dsp)
01956 ast_dsp_digitreset(p->dsp);
01957
01958 return 0;
01959 }
01960
01961 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01962 {
01963 struct dahdi_pvt *p = pvt;
01964
01965 if (p->channel == CHAN_PSEUDO)
01966 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01967
01968 if (mode == ANALOG_DIGITMODE_DTMF) {
01969
01970 if (p->hardwaredtmf) {
01971 if (p->dsp) {
01972 ast_dsp_free(p->dsp);
01973 p->dsp = NULL;
01974 }
01975 return 0;
01976 }
01977
01978 if (!p->dsp) {
01979 p->dsp = ast_dsp_new();
01980 if (!p->dsp) {
01981 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01982 return -1;
01983 }
01984 }
01985
01986 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01987 } else if (mode == ANALOG_DIGITMODE_MF) {
01988 if (!p->dsp) {
01989 p->dsp = ast_dsp_new();
01990 if (!p->dsp) {
01991 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01992 return -1;
01993 }
01994 }
01995 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01996 }
01997 return 0;
01998 }
01999
02000 static int dahdi_wink(struct dahdi_pvt *p, int index);
02001
02002 static int my_wink(void *pvt, enum analog_sub sub)
02003 {
02004 struct dahdi_pvt *p = pvt;
02005 int index = analogsub_to_dahdisub(sub);
02006 if (index != SUB_REAL) {
02007 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02008 }
02009 return dahdi_wink(p, index);
02010 }
02011
02012 static void wakeup_sub(struct dahdi_pvt *p, int a);
02013
02014 static int reset_conf(struct dahdi_pvt *p);
02015
02016 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02017
02018 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02019 {
02020 struct ast_frame *f = *dest;
02021 struct dahdi_pvt *p = pvt;
02022 int idx = analogsub_to_dahdisub(analog_index);
02023
02024 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02025 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02026 f->subclass.integer, f->subclass.integer, ast->name);
02027
02028 if (f->subclass.integer == 'f') {
02029 if (f->frametype == AST_FRAME_DTMF_END) {
02030
02031 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02032
02033 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02034 struct dahdi_bufferinfo bi = {
02035 .txbufpolicy = p->faxbuf_policy,
02036 .bufsize = p->bufsize,
02037 .numbufs = p->faxbuf_no
02038 };
02039 int res;
02040
02041 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02042 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02043 } else {
02044 p->bufferoverrideinuse = 1;
02045 }
02046 }
02047 p->faxhandled = 1;
02048 if (p->dsp) {
02049 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02050 ast_dsp_set_features(p->dsp, p->dsp_features);
02051 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02052 }
02053 if (strcmp(ast->exten, "fax")) {
02054 const char *target_context = S_OR(ast->macrocontext, ast->context);
02055
02056
02057
02058
02059
02060 ast_mutex_unlock(&p->lock);
02061 ast_channel_unlock(ast);
02062 if (ast_exists_extension(ast, target_context, "fax", 1,
02063 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02064 ast_channel_lock(ast);
02065 ast_mutex_lock(&p->lock);
02066 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02067
02068 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02069 if (ast_async_goto(ast, target_context, "fax", 1))
02070 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02071 } else {
02072 ast_channel_lock(ast);
02073 ast_mutex_lock(&p->lock);
02074 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02075 }
02076 } else {
02077 ast_debug(1, "Already in a fax extension, not redirecting\n");
02078 }
02079 } else {
02080 ast_debug(1, "Fax already handled\n");
02081 }
02082 dahdi_confmute(p, 0);
02083 }
02084 p->subs[idx].f.frametype = AST_FRAME_NULL;
02085 p->subs[idx].f.subclass.integer = 0;
02086 *dest = &p->subs[idx].f;
02087 }
02088 }
02089
02090 static void my_lock_private(void *pvt)
02091 {
02092 struct dahdi_pvt *p = pvt;
02093 ast_mutex_lock(&p->lock);
02094 }
02095
02096 static void my_unlock_private(void *pvt)
02097 {
02098 struct dahdi_pvt *p = pvt;
02099 ast_mutex_unlock(&p->lock);
02100 }
02101
02102 static void my_deadlock_avoidance_private(void *pvt)
02103 {
02104 struct dahdi_pvt *p = pvt;
02105
02106 DEADLOCK_AVOIDANCE(&p->lock);
02107 }
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02120 {
02121 char ch_name[20];
02122
02123 if (p->channel < CHAN_PSEUDO) {
02124
02125 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02126 } else if (p->channel == CHAN_PSEUDO) {
02127
02128 strcpy(ch_name, "pseudo");
02129 } else {
02130
02131 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02132 }
02133 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02134 "Channel: %s\r\n"
02135 "Uniqueid: %s\r\n"
02136 "DAHDISpan: %d\r\n"
02137 "DAHDIChannel: %s\r\n",
02138 chan->name,
02139 chan->uniqueid,
02140 p->span,
02141 ch_name);
02142 }
02143
02144 #ifdef HAVE_PRI
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02156 {
02157 struct dahdi_pvt *p = pvt;
02158
02159 dahdi_ami_channel_event(p, chan);
02160 }
02161 #endif
02162
02163
02164
02165
02166 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02167 {
02168 struct dahdi_pvt *p = pvt;
02169 int oldval;
02170 int idx = analogsub_to_dahdisub(sub);
02171
02172 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02173 oldval = p->subs[idx].linear;
02174 p->subs[idx].linear = linear_mode ? 1 : 0;
02175 return oldval;
02176 }
02177
02178 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02179 {
02180 struct dahdi_pvt *p = pvt;
02181 int idx = analogsub_to_dahdisub(sub);
02182
02183 p->subs[idx].inthreeway = inthreeway;
02184 }
02185
02186 static int get_alarms(struct dahdi_pvt *p);
02187 static void handle_alarms(struct dahdi_pvt *p, int alms);
02188 static void my_get_and_handle_alarms(void *pvt)
02189 {
02190 int res;
02191 struct dahdi_pvt *p = pvt;
02192
02193 res = get_alarms(p);
02194 handle_alarms(p, res);
02195 }
02196
02197 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02198 {
02199 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02200 if (p)
02201 return p->sig_pvt;
02202 else
02203 return NULL;
02204 }
02205
02206 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02207 {
02208 struct dahdi_pvt *p = pvt;
02209 int dahdi_sub = analogsub_to_dahdisub(sub);
02210 return p->subs[dahdi_sub].dfd;
02211 }
02212
02213 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02214 {
02215 struct dahdi_pvt *p = pvt;
02216
02217
02218 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02219 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02220 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02221 *cidrings = cidrings[p->distinctivering - 1];
02222 } else {
02223 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02224 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02225 *cidrings = p->sendcalleridafter;
02226 }
02227 }
02228
02229 static void my_set_alarm(void *pvt, int in_alarm)
02230 {
02231 struct dahdi_pvt *p = pvt;
02232
02233 p->inalarm = in_alarm;
02234 }
02235
02236 static void my_set_dialing(void *pvt, int is_dialing)
02237 {
02238 struct dahdi_pvt *p = pvt;
02239
02240 p->dialing = is_dialing;
02241 }
02242
02243 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02244 static void my_set_digital(void *pvt, int is_digital)
02245 {
02246 struct dahdi_pvt *p = pvt;
02247
02248 p->digital = is_digital;
02249 }
02250 #endif
02251
02252 #if defined(HAVE_SS7)
02253 static void my_set_inservice(void *pvt, int is_inservice)
02254 {
02255 struct dahdi_pvt *p = pvt;
02256
02257 p->inservice = is_inservice;
02258 }
02259 #endif
02260
02261 #if defined(HAVE_SS7)
02262 static void my_set_locallyblocked(void *pvt, int is_blocked)
02263 {
02264 struct dahdi_pvt *p = pvt;
02265
02266 p->locallyblocked = is_blocked;
02267 }
02268 #endif
02269
02270 #if defined(HAVE_SS7)
02271 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02272 {
02273 struct dahdi_pvt *p = pvt;
02274
02275 p->remotelyblocked = is_blocked;
02276 }
02277 #endif
02278
02279 static void my_set_ringtimeout(void *pvt, int ringt)
02280 {
02281 struct dahdi_pvt *p = pvt;
02282 p->ringt = ringt;
02283 }
02284
02285 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02286 {
02287 struct dahdi_pvt *p = pvt;
02288
02289 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02290 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02291 gettimeofday(&p->waitingfordt, NULL);
02292 ast_setstate(ast, AST_STATE_OFFHOOK);
02293 }
02294 }
02295
02296 static int my_check_waitingfordt(void *pvt)
02297 {
02298 struct dahdi_pvt *p = pvt;
02299
02300 if (p->waitingfordt.tv_usec) {
02301 return 1;
02302 }
02303
02304 return 0;
02305 }
02306
02307 static void my_set_confirmanswer(void *pvt, int flag)
02308 {
02309 struct dahdi_pvt *p = pvt;
02310 p->confirmanswer = flag;
02311 }
02312
02313 static int my_check_confirmanswer(void *pvt)
02314 {
02315 struct dahdi_pvt *p = pvt;
02316 if (p->confirmanswer) {
02317 return 1;
02318 }
02319
02320 return 0;
02321 }
02322
02323 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02324 {
02325 struct dahdi_pvt *p = pvt;
02326
02327 p->callwaiting = callwaiting_enable;
02328 }
02329
02330 static void my_cancel_cidspill(void *pvt)
02331 {
02332 struct dahdi_pvt *p = pvt;
02333
02334 ast_free(p->cidspill);
02335 p->cidspill = NULL;
02336 restore_conference(p);
02337 }
02338
02339 static int my_confmute(void *pvt, int mute)
02340 {
02341 struct dahdi_pvt *p = pvt;
02342 return dahdi_confmute(p, mute);
02343 }
02344
02345 static void my_set_pulsedial(void *pvt, int flag)
02346 {
02347 struct dahdi_pvt *p = pvt;
02348 p->pulsedial = flag;
02349 }
02350
02351 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02352 {
02353 struct dahdi_pvt *p = pvt;
02354
02355 p->owner = new_owner;
02356 }
02357
02358 static const char *my_get_orig_dialstring(void *pvt)
02359 {
02360 struct dahdi_pvt *p = pvt;
02361
02362 return p->dialstring;
02363 }
02364
02365 static void my_increase_ss_count(void)
02366 {
02367 ast_mutex_lock(&ss_thread_lock);
02368 ss_thread_count++;
02369 ast_mutex_unlock(&ss_thread_lock);
02370 }
02371
02372 static void my_decrease_ss_count(void)
02373 {
02374 ast_mutex_lock(&ss_thread_lock);
02375 ss_thread_count--;
02376 ast_cond_signal(&ss_thread_complete);
02377 ast_mutex_unlock(&ss_thread_lock);
02378 }
02379
02380 static void my_all_subchannels_hungup(void *pvt)
02381 {
02382 struct dahdi_pvt *p = pvt;
02383 int res, law;
02384
02385 p->faxhandled = 0;
02386 p->didtdd = 0;
02387
02388 if (p->dsp) {
02389 ast_dsp_free(p->dsp);
02390 p->dsp = NULL;
02391 }
02392
02393 p->law = p->law_default;
02394 law = p->law_default;
02395 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02396 if (res < 0)
02397 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02398
02399 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02400
02401 #if 1
02402 {
02403 int i;
02404 p->owner = NULL;
02405
02406 for (i = 0; i < 3; i++) {
02407 p->subs[i].owner = NULL;
02408 }
02409 }
02410 #endif
02411
02412 reset_conf(p);
02413 if (num_restart_pending == 0) {
02414 restart_monitor();
02415 }
02416 }
02417
02418 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02419
02420 static int my_conf_del(void *pvt, enum analog_sub sub)
02421 {
02422 struct dahdi_pvt *p = pvt;
02423 int x = analogsub_to_dahdisub(sub);
02424
02425 return conf_del(p, &p->subs[x], x);
02426 }
02427
02428 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02429
02430 static int my_conf_add(void *pvt, enum analog_sub sub)
02431 {
02432 struct dahdi_pvt *p = pvt;
02433 int x = analogsub_to_dahdisub(sub);
02434
02435 return conf_add(p, &p->subs[x], x, 0);
02436 }
02437
02438 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02439
02440 static int my_complete_conference_update(void *pvt, int needconference)
02441 {
02442 struct dahdi_pvt *p = pvt;
02443 int needconf = needconference;
02444 int x;
02445 int useslavenative;
02446 struct dahdi_pvt *slave = NULL;
02447
02448 useslavenative = isslavenative(p, &slave);
02449
02450
02451
02452 for (x = 0; x < MAX_SLAVES; x++) {
02453 if (p->slaves[x]) {
02454 if (useslavenative)
02455 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02456 else {
02457 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02458 needconf++;
02459 }
02460 }
02461 }
02462
02463 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02464 if (useslavenative)
02465 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02466 else {
02467 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02468 needconf++;
02469 }
02470 }
02471
02472 if (p->master) {
02473 if (isslavenative(p->master, NULL)) {
02474 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02475 } else {
02476 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02477 }
02478 }
02479 if (!needconf) {
02480
02481
02482 p->confno = -1;
02483 }
02484
02485 return 0;
02486 }
02487
02488 static int check_for_conference(struct dahdi_pvt *p);
02489
02490 static int my_check_for_conference(void *pvt)
02491 {
02492 struct dahdi_pvt *p = pvt;
02493 return check_for_conference(p);
02494 }
02495
02496 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)
02497 {
02498 struct dahdi_pvt *p = pvt;
02499 int da, db;
02500 int tchan;
02501 int tinthreeway;
02502
02503 da = analogsub_to_dahdisub(a);
02504 db = analogsub_to_dahdisub(b);
02505
02506 tchan = p->subs[da].chan;
02507 p->subs[da].chan = p->subs[db].chan;
02508 p->subs[db].chan = tchan;
02509
02510 tinthreeway = p->subs[da].inthreeway;
02511 p->subs[da].inthreeway = p->subs[db].inthreeway;
02512 p->subs[db].inthreeway = tinthreeway;
02513
02514 p->subs[da].owner = ast_a;
02515 p->subs[db].owner = ast_b;
02516
02517 if (ast_a)
02518 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02519 if (ast_b)
02520 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02521
02522 wakeup_sub(p, a);
02523 wakeup_sub(p, b);
02524
02525 return;
02526 }
02527
02528 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02529
02530 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02531 {
02532 struct dahdi_pvt *p = pvt;
02533 int dsub = analogsub_to_dahdisub(sub);
02534
02535 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02536 }
02537
02538 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02539 static int dahdi_setlaw(int dfd, int law)
02540 {
02541 int res;
02542 res = ioctl(dfd, DAHDI_SETLAW, &law);
02543 if (res)
02544 return res;
02545 return 0;
02546 }
02547 #endif
02548
02549 #if defined(HAVE_PRI)
02550 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)
02551 {
02552 struct dahdi_pvt *p = pvt;
02553 int audio;
02554 int newlaw = -1;
02555
02556 switch (p->sig) {
02557 case SIG_PRI_LIB_HANDLE_CASES:
02558 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02559
02560 break;
02561 }
02562
02563 default:
02564
02565 audio = 1;
02566 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02567 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02568 p->channel, audio, strerror(errno));
02569 }
02570 break;
02571 }
02572
02573 if (law != SIG_PRI_DEFLAW) {
02574 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02575 }
02576
02577 ast_copy_string(p->exten, exten, sizeof(p->exten));
02578
02579 switch (law) {
02580 case SIG_PRI_DEFLAW:
02581 newlaw = 0;
02582 break;
02583 case SIG_PRI_ALAW:
02584 newlaw = DAHDI_LAW_ALAW;
02585 break;
02586 case SIG_PRI_ULAW:
02587 newlaw = DAHDI_LAW_MULAW;
02588 break;
02589 }
02590 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02591 }
02592 #endif
02593
02594 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02595
02596 #if defined(HAVE_PRI)
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606 static void my_pri_open_media(void *p)
02607 {
02608 struct dahdi_pvt *pvt = p;
02609 int res;
02610 int dfd;
02611 int set_val;
02612
02613 dfd = pvt->subs[SUB_REAL].dfd;
02614
02615
02616 set_val = 1;
02617 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02618 if (res < 0) {
02619 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02620 pvt->channel, strerror(errno));
02621 }
02622
02623
02624 res = dahdi_setlaw(dfd, pvt->law);
02625 if (res < 0) {
02626 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02627 }
02628
02629
02630 if (pvt->digital) {
02631 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02632 } else {
02633 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02634 pvt->law);
02635 }
02636 if (res < 0) {
02637 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02638 }
02639
02640 if (pvt->dsp_features && pvt->dsp) {
02641 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02642 pvt->dsp_features = 0;
02643 }
02644 }
02645 #endif
02646
02647 static int unalloc_sub(struct dahdi_pvt *p, int x);
02648
02649 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02650 {
02651 struct dahdi_pvt *p = pvt;
02652
02653 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02654 }
02655
02656 static int alloc_sub(struct dahdi_pvt *p, int x);
02657
02658 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02659 {
02660 struct dahdi_pvt *p = pvt;
02661
02662 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02663 }
02664
02665 static int has_voicemail(struct dahdi_pvt *p);
02666
02667 static int my_has_voicemail(void *pvt)
02668 {
02669 struct dahdi_pvt *p = pvt;
02670
02671 return has_voicemail(p);
02672 }
02673
02674 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02675 {
02676 struct dahdi_pvt *p = pvt;
02677 int index;
02678
02679 index = analogsub_to_dahdisub(sub);
02680
02681 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02682 }
02683
02684 static enum analog_event dahdievent_to_analogevent(int event)
02685 {
02686 enum analog_event res;
02687
02688 switch (event) {
02689 case DAHDI_EVENT_ONHOOK:
02690 res = ANALOG_EVENT_ONHOOK;
02691 break;
02692 case DAHDI_EVENT_RINGOFFHOOK:
02693 res = ANALOG_EVENT_RINGOFFHOOK;
02694 break;
02695 case DAHDI_EVENT_WINKFLASH:
02696 res = ANALOG_EVENT_WINKFLASH;
02697 break;
02698 case DAHDI_EVENT_ALARM:
02699 res = ANALOG_EVENT_ALARM;
02700 break;
02701 case DAHDI_EVENT_NOALARM:
02702 res = ANALOG_EVENT_NOALARM;
02703 break;
02704 case DAHDI_EVENT_DIALCOMPLETE:
02705 res = ANALOG_EVENT_DIALCOMPLETE;
02706 break;
02707 case DAHDI_EVENT_RINGERON:
02708 res = ANALOG_EVENT_RINGERON;
02709 break;
02710 case DAHDI_EVENT_RINGEROFF:
02711 res = ANALOG_EVENT_RINGEROFF;
02712 break;
02713 case DAHDI_EVENT_HOOKCOMPLETE:
02714 res = ANALOG_EVENT_HOOKCOMPLETE;
02715 break;
02716 case DAHDI_EVENT_PULSE_START:
02717 res = ANALOG_EVENT_PULSE_START;
02718 break;
02719 case DAHDI_EVENT_POLARITY:
02720 res = ANALOG_EVENT_POLARITY;
02721 break;
02722 case DAHDI_EVENT_RINGBEGIN:
02723 res = ANALOG_EVENT_RINGBEGIN;
02724 break;
02725 case DAHDI_EVENT_EC_DISABLED:
02726 res = ANALOG_EVENT_EC_DISABLED;
02727 break;
02728 case DAHDI_EVENT_REMOVED:
02729 res = ANALOG_EVENT_REMOVED;
02730 break;
02731 case DAHDI_EVENT_NEONMWI_ACTIVE:
02732 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02733 break;
02734 case DAHDI_EVENT_NEONMWI_INACTIVE:
02735 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02736 break;
02737 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02738 case DAHDI_EVENT_TX_CED_DETECTED:
02739 res = ANALOG_EVENT_TX_CED_DETECTED;
02740 break;
02741 case DAHDI_EVENT_RX_CED_DETECTED:
02742 res = ANALOG_EVENT_RX_CED_DETECTED;
02743 break;
02744 case DAHDI_EVENT_EC_NLP_DISABLED:
02745 res = ANALOG_EVENT_EC_NLP_DISABLED;
02746 break;
02747 case DAHDI_EVENT_EC_NLP_ENABLED:
02748 res = ANALOG_EVENT_EC_NLP_ENABLED;
02749 break;
02750 #endif
02751 case DAHDI_EVENT_PULSEDIGIT:
02752 res = ANALOG_EVENT_PULSEDIGIT;
02753 break;
02754 case DAHDI_EVENT_DTMFDOWN:
02755 res = ANALOG_EVENT_DTMFDOWN;
02756 break;
02757 case DAHDI_EVENT_DTMFUP:
02758 res = ANALOG_EVENT_DTMFUP;
02759 break;
02760 default:
02761 switch(event & 0xFFFF0000) {
02762 case DAHDI_EVENT_PULSEDIGIT:
02763 case DAHDI_EVENT_DTMFDOWN:
02764 case DAHDI_EVENT_DTMFUP:
02765
02766
02767
02768
02769 return event;
02770 }
02771
02772 res = ANALOG_EVENT_ERROR;
02773 break;
02774 }
02775
02776 return res;
02777 }
02778
02779 static inline int dahdi_wait_event(int fd);
02780
02781 static int my_wait_event(void *pvt)
02782 {
02783 struct dahdi_pvt *p = pvt;
02784
02785 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02786 }
02787
02788 static int my_get_event(void *pvt)
02789 {
02790 struct dahdi_pvt *p = pvt;
02791 int res;
02792
02793 if (p->fake_event) {
02794 res = p->fake_event;
02795 p->fake_event = 0;
02796 } else
02797 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02798
02799 return dahdievent_to_analogevent(res);
02800 }
02801
02802 static int my_is_off_hook(void *pvt)
02803 {
02804 struct dahdi_pvt *p = pvt;
02805 int res;
02806 struct dahdi_params par;
02807
02808 memset(&par, 0, sizeof(par));
02809
02810 if (p->subs[SUB_REAL].dfd > -1)
02811 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02812 else {
02813
02814 res = 0;
02815 par.rxisoffhook = 0;
02816 }
02817 if (res) {
02818 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02819 }
02820
02821 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02822
02823
02824
02825 return (par.rxbits > -1) || par.rxisoffhook;
02826 }
02827
02828 return par.rxisoffhook;
02829 }
02830
02831 static void dahdi_enable_ec(struct dahdi_pvt *p);
02832 static void dahdi_disable_ec(struct dahdi_pvt *p);
02833
02834 static int my_set_echocanceller(void *pvt, int enable)
02835 {
02836 struct dahdi_pvt *p = pvt;
02837
02838 if (enable)
02839 dahdi_enable_ec(p);
02840 else
02841 dahdi_disable_ec(p);
02842
02843 return 0;
02844 }
02845
02846 static int dahdi_ring_phone(struct dahdi_pvt *p);
02847
02848 static int my_ring(void *pvt)
02849 {
02850 struct dahdi_pvt *p = pvt;
02851
02852 return dahdi_ring_phone(p);
02853 }
02854
02855 static int my_flash(void *pvt)
02856 {
02857 struct dahdi_pvt *p = pvt;
02858 int func = DAHDI_FLASH;
02859 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02860 }
02861
02862 static inline int dahdi_set_hook(int fd, int hs);
02863
02864 static int my_off_hook(void *pvt)
02865 {
02866 struct dahdi_pvt *p = pvt;
02867 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02868 }
02869
02870 static void my_set_needringing(void *pvt, int value)
02871 {
02872 struct dahdi_pvt *p = pvt;
02873 p->subs[SUB_REAL].needringing = value;
02874 }
02875
02876 static void my_set_polarity(void *pvt, int value)
02877 {
02878 struct dahdi_pvt *p = pvt;
02879
02880 if (p->channel == CHAN_PSEUDO) {
02881 return;
02882 }
02883 p->polarity = value;
02884 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02885 }
02886
02887 static void my_start_polarityswitch(void *pvt)
02888 {
02889 struct dahdi_pvt *p = pvt;
02890
02891 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02892 my_set_polarity(pvt, 0);
02893 }
02894 }
02895
02896 static void my_answer_polarityswitch(void *pvt)
02897 {
02898 struct dahdi_pvt *p = pvt;
02899
02900 if (!p->answeronpolarityswitch) {
02901 return;
02902 }
02903
02904 my_set_polarity(pvt, 1);
02905 }
02906
02907 static void my_hangup_polarityswitch(void *pvt)
02908 {
02909 struct dahdi_pvt *p = pvt;
02910
02911 if (!p->hanguponpolarityswitch) {
02912 return;
02913 }
02914
02915 if (p->answeronpolarityswitch) {
02916 my_set_polarity(pvt, 0);
02917 } else {
02918 my_set_polarity(pvt, 1);
02919 }
02920 }
02921
02922 static int my_start(void *pvt)
02923 {
02924 struct dahdi_pvt *p = pvt;
02925 int x = DAHDI_START;
02926
02927 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02928 }
02929
02930 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02931 {
02932 int index = analogsub_to_dahdisub(sub);
02933 int res;
02934 struct dahdi_pvt *p = pvt;
02935 struct dahdi_dialoperation ddop;
02936
02937 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02938 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02939 return -1;
02940 }
02941
02942 if (sub != ANALOG_SUB_REAL) {
02943 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
02944 dop->dialstr, p->channel, sub);
02945 return -1;
02946 }
02947
02948 ddop.op = DAHDI_DIAL_OP_REPLACE;
02949 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02950
02951 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
02952
02953 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02954 if (res == -1) {
02955 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02956 }
02957
02958 return res;
02959 }
02960
02961 static void dahdi_train_ec(struct dahdi_pvt *p);
02962
02963 static int my_train_echocanceller(void *pvt)
02964 {
02965 struct dahdi_pvt *p = pvt;
02966
02967 dahdi_train_ec(p);
02968
02969 return 0;
02970 }
02971
02972 static int my_is_dialing(void *pvt, enum analog_sub sub)
02973 {
02974 struct dahdi_pvt *p = pvt;
02975 int index;
02976 int x;
02977
02978 index = analogsub_to_dahdisub(sub);
02979
02980 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02981 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02982 return -1;
02983 }
02984
02985 return x;
02986 }
02987
02988 static int my_on_hook(void *pvt)
02989 {
02990 struct dahdi_pvt *p = pvt;
02991 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02992 }
02993
02994 #if defined(HAVE_PRI)
02995 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02996 {
02997 struct dahdi_pvt *old_chan = chan_old;
02998 struct dahdi_pvt *new_chan = chan_new;
02999
03000 new_chan->owner = old_chan->owner;
03001 old_chan->owner = NULL;
03002 if (new_chan->owner) {
03003 new_chan->owner->tech_pvt = new_chan;
03004 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03005 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03006 old_chan->subs[SUB_REAL].owner = NULL;
03007 }
03008
03009 new_chan->dsp = old_chan->dsp;
03010 new_chan->dsp_features = old_chan->dsp_features;
03011 old_chan->dsp = NULL;
03012 old_chan->dsp_features = 0;
03013
03014
03015 new_chan->dialing = old_chan->dialing;
03016 new_chan->digital = old_chan->digital;
03017 new_chan->outgoing = old_chan->outgoing;
03018 old_chan->dialing = 0;
03019 old_chan->digital = 0;
03020 old_chan->outgoing = 0;
03021
03022
03023 new_chan->law = old_chan->law;
03024 strcpy(new_chan->dialstring, old_chan->dialstring);
03025 }
03026 #endif
03027
03028 #if defined(HAVE_PRI)
03029 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03030 {
03031 switch (tone) {
03032 case SIG_PRI_TONE_RINGTONE:
03033 return DAHDI_TONE_RINGTONE;
03034 case SIG_PRI_TONE_STUTTER:
03035 return DAHDI_TONE_STUTTER;
03036 case SIG_PRI_TONE_CONGESTION:
03037 return DAHDI_TONE_CONGESTION;
03038 case SIG_PRI_TONE_DIALTONE:
03039 return DAHDI_TONE_DIALTONE;
03040 case SIG_PRI_TONE_DIALRECALL:
03041 return DAHDI_TONE_DIALRECALL;
03042 case SIG_PRI_TONE_INFO:
03043 return DAHDI_TONE_INFO;
03044 case SIG_PRI_TONE_BUSY:
03045 return DAHDI_TONE_BUSY;
03046 default:
03047 return -1;
03048 }
03049 }
03050 #endif
03051
03052 #if defined(HAVE_PRI)
03053 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03054 {
03055 int x;
03056
03057 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03058 if (x) {
03059 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03060 }
03061
03062 switch (x) {
03063 case DAHDI_EVENT_ALARM:
03064 pri_event_alarm(pri, index, 0);
03065 break;
03066 case DAHDI_EVENT_NOALARM:
03067 pri_event_noalarm(pri, index, 0);
03068 break;
03069 default:
03070 break;
03071 }
03072 }
03073 #endif
03074
03075 #if defined(HAVE_PRI)
03076 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03077 {
03078 struct dahdi_pvt *p = pvt;
03079
03080 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03081 }
03082 #endif
03083
03084 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03096 {
03097 struct dahdi_pvt *p = pvt;
03098
03099 ast_copy_string(p->cid_num,
03100 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03101 sizeof(p->cid_num));
03102 ast_copy_string(p->cid_name,
03103 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03104 sizeof(p->cid_name));
03105 ast_copy_string(p->cid_subaddr,
03106 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03107 sizeof(p->cid_subaddr));
03108 p->cid_ton = caller->id.number.plan;
03109 p->callingpres = ast_party_id_presentation(&caller->id);
03110 if (caller->id.tag) {
03111 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03112 }
03113 ast_copy_string(p->cid_ani,
03114 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03115 sizeof(p->cid_ani));
03116 p->cid_ani2 = caller->ani2;
03117 }
03118 #endif
03119
03120 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131 static void my_set_dnid(void *pvt, const char *dnid)
03132 {
03133 struct dahdi_pvt *p = pvt;
03134
03135 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03136 }
03137 #endif
03138
03139 #if defined(HAVE_PRI)
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150 static void my_set_rdnis(void *pvt, const char *rdnis)
03151 {
03152 struct dahdi_pvt *p = pvt;
03153
03154 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03155 }
03156 #endif
03157
03158 #if defined(HAVE_PRI)
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03184 {
03185 char *dial;
03186 struct dahdi_pvt *pvt;
03187 AST_DECLARE_APP_ARGS(args,
03188 AST_APP_ARG(tech);
03189 AST_APP_ARG(group);
03190
03191
03192
03193 );
03194
03195 pvt = priv;
03196 dial = ast_strdupa(pvt->dialstring);
03197 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03198 if (!args.tech) {
03199 ast_copy_string(buf, pvt->dialstring, buf_size);
03200 return;
03201 }
03202 if (!args.group) {
03203
03204 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03205 return;
03206 }
03207 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03208
03209
03210 ast_copy_string(buf, pvt->dialstring, buf_size);
03211 return;
03212 }
03213
03214 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03215 }
03216 #endif
03217
03218 #if defined(HAVE_PRI)
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03231 {
03232 unsigned idx;
03233 unsigned num_b_chans;
03234 unsigned in_use;
03235 unsigned in_alarm;
03236 enum ast_device_state new_state;
03237
03238
03239 num_b_chans = 0;
03240 in_use = 0;
03241 in_alarm = 1;
03242 for (idx = pri->numchans; idx--;) {
03243 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03244
03245 ++num_b_chans;
03246 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03247 ++in_use;
03248 }
03249 if (!pri->pvts[idx]->inalarm) {
03250
03251 in_alarm = 0;
03252 }
03253 }
03254 }
03255
03256
03257 if (in_alarm) {
03258 new_state = AST_DEVICE_UNAVAILABLE;
03259 } else {
03260 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03261 }
03262 if (pri->congestion_devstate != new_state) {
03263 pri->congestion_devstate = new_state;
03264 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03265 }
03266 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03267
03268 if (in_alarm) {
03269 new_state = AST_DEVICE_UNAVAILABLE;
03270 } else if (!in_use) {
03271 new_state = AST_DEVICE_NOT_INUSE;
03272 } else if (!pri->user_busy_threshold) {
03273 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03274 } else {
03275 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03276 : AST_DEVICE_BUSY;
03277 }
03278 if (pri->threshold_devstate != new_state) {
03279 pri->threshold_devstate = new_state;
03280 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03281 }
03282 #endif
03283 }
03284 #endif
03285
03286 #if defined(HAVE_PRI)
03287
03288
03289
03290
03291
03292
03293
03294 static void my_module_ref(void)
03295 {
03296 ast_module_ref(ast_module_info->self);
03297 }
03298 #endif
03299
03300 #if defined(HAVE_PRI)
03301
03302
03303
03304
03305
03306
03307
03308 static void my_module_unref(void)
03309 {
03310 ast_module_unref(ast_module_info->self);
03311 }
03312 #endif
03313
03314 #if defined(HAVE_PRI)
03315 #if defined(HAVE_PRI_CALL_WAITING)
03316 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03317 #endif
03318 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03319
03320 static struct sig_pri_callback dahdi_pri_callbacks =
03321 {
03322 .handle_dchan_exception = my_handle_dchan_exception,
03323 .play_tone = my_pri_play_tone,
03324 .set_echocanceller = my_set_echocanceller,
03325 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03326 .lock_private = my_lock_private,
03327 .unlock_private = my_unlock_private,
03328 .new_ast_channel = my_new_pri_ast_channel,
03329 .fixup_chans = my_pri_fixup_chans,
03330 .set_alarm = my_set_alarm,
03331 .set_dialing = my_set_dialing,
03332 .set_digital = my_set_digital,
03333 .set_callerid = my_set_callerid,
03334 .set_dnid = my_set_dnid,
03335 .set_rdnis = my_set_rdnis,
03336 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03337 #if defined(HAVE_PRI_CALL_WAITING)
03338 .init_config = my_pri_init_config,
03339 #endif
03340 .get_orig_dialstring = my_get_orig_dialstring,
03341 .make_cc_dialstring = my_pri_make_cc_dialstring,
03342 .update_span_devstate = dahdi_pri_update_span_devstate,
03343 .module_ref = my_module_ref,
03344 .module_unref = my_module_unref,
03345 .open_media = my_pri_open_media,
03346 .ami_channel_event = my_ami_channel_event,
03347 };
03348 #endif
03349
03350 #if defined(HAVE_SS7)
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03362 {
03363 int event;
03364
03365 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03366 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03367 linkset->span, which);
03368 return;
03369 }
03370 switch (event) {
03371 case DAHDI_EVENT_NONE:
03372 break;
03373 case DAHDI_EVENT_ALARM:
03374 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03375 event2str(event), event, linkset->span, which);
03376 sig_ss7_link_alarm(linkset, which);
03377 break;
03378 case DAHDI_EVENT_NOALARM:
03379 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03380 event2str(event), event, linkset->span, which);
03381 sig_ss7_link_noalarm(linkset, which);
03382 break;
03383 default:
03384 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03385 event2str(event), event, linkset->span, which);
03386 break;
03387 }
03388 }
03389 #endif
03390
03391 #if defined(HAVE_SS7)
03392 static void my_ss7_set_loopback(void *pvt, int enable)
03393 {
03394 struct dahdi_pvt *p = pvt;
03395
03396 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03397 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03398 strerror(errno));
03399 }
03400 }
03401 #endif
03402
03403 #if defined(HAVE_SS7)
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418 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)
03419 {
03420 struct dahdi_pvt *p = pvt;
03421 int audio;
03422 int newlaw;
03423
03424
03425 audio = 1;
03426 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03427 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03428 p->channel, audio, strerror(errno));
03429
03430 if (law != SIG_SS7_DEFLAW) {
03431 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03432 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03433 }
03434
03435 ast_copy_string(p->exten, exten, sizeof(p->exten));
03436
03437 newlaw = -1;
03438 switch (law) {
03439 case SIG_SS7_DEFLAW:
03440 newlaw = 0;
03441 break;
03442 case SIG_SS7_ALAW:
03443 newlaw = DAHDI_LAW_ALAW;
03444 break;
03445 case SIG_SS7_ULAW:
03446 newlaw = DAHDI_LAW_MULAW;
03447 break;
03448 }
03449 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03450 }
03451 #endif
03452
03453 #if defined(HAVE_SS7)
03454 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03455 {
03456 switch (tone) {
03457 case SIG_SS7_TONE_RINGTONE:
03458 return DAHDI_TONE_RINGTONE;
03459 case SIG_SS7_TONE_STUTTER:
03460 return DAHDI_TONE_STUTTER;
03461 case SIG_SS7_TONE_CONGESTION:
03462 return DAHDI_TONE_CONGESTION;
03463 case SIG_SS7_TONE_DIALTONE:
03464 return DAHDI_TONE_DIALTONE;
03465 case SIG_SS7_TONE_DIALRECALL:
03466 return DAHDI_TONE_DIALRECALL;
03467 case SIG_SS7_TONE_INFO:
03468 return DAHDI_TONE_INFO;
03469 case SIG_SS7_TONE_BUSY:
03470 return DAHDI_TONE_BUSY;
03471 default:
03472 return -1;
03473 }
03474 }
03475 #endif
03476
03477 #if defined(HAVE_SS7)
03478 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03479 {
03480 struct dahdi_pvt *p = pvt;
03481
03482 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03483 }
03484 #endif
03485
03486 #if defined(HAVE_SS7)
03487 static struct sig_ss7_callback dahdi_ss7_callbacks =
03488 {
03489 .lock_private = my_lock_private,
03490 .unlock_private = my_unlock_private,
03491
03492 .set_echocanceller = my_set_echocanceller,
03493 .set_loopback = my_ss7_set_loopback,
03494
03495 .new_ast_channel = my_new_ss7_ast_channel,
03496 .play_tone = my_ss7_play_tone,
03497
03498 .handle_link_exception = my_handle_link_exception,
03499 .set_alarm = my_set_alarm,
03500 .set_dialing = my_set_dialing,
03501 .set_digital = my_set_digital,
03502 .set_inservice = my_set_inservice,
03503 .set_locallyblocked = my_set_locallyblocked,
03504 .set_remotelyblocked = my_set_remotelyblocked,
03505 .set_callerid = my_set_callerid,
03506 .set_dnid = my_set_dnid,
03507 };
03508 #endif
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528 static void notify_message(char *mailbox_full, int thereornot)
03529 {
03530 char s[sizeof(mwimonitornotify) + 80];
03531 struct ast_event *event;
03532 char *mailbox, *context;
03533
03534
03535 context = mailbox = ast_strdupa(mailbox_full);
03536 strsep(&context, "@");
03537 if (ast_strlen_zero(context))
03538 context = "default";
03539
03540 if (!(event = ast_event_new(AST_EVENT_MWI,
03541 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03542 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03543 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03544 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03545 AST_EVENT_IE_END))) {
03546 return;
03547 }
03548
03549 ast_event_queue_and_cache(event);
03550
03551 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03552 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03553 ast_safe_system(s);
03554 }
03555 }
03556
03557 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03558 {
03559 struct dahdi_pvt *p = pvt;
03560
03561 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03562 return;
03563
03564 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03565 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03566 notify_message(p->mailbox, 1);
03567 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03568 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03569 notify_message(p->mailbox, 0);
03570 }
03571
03572
03573 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03574 ast_hangup(chan);
03575 return;
03576 }
03577 }
03578
03579 static int my_have_progressdetect(void *pvt)
03580 {
03581 struct dahdi_pvt *p = pvt;
03582
03583 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03584 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03585 return 1;
03586 } else {
03587
03588 return 0;
03589 }
03590 }
03591
03592 static struct analog_callback dahdi_analog_callbacks =
03593 {
03594 .play_tone = my_play_tone,
03595 .get_event = my_get_event,
03596 .wait_event = my_wait_event,
03597 .is_off_hook = my_is_off_hook,
03598 .set_echocanceller = my_set_echocanceller,
03599 .ring = my_ring,
03600 .flash = my_flash,
03601 .off_hook = my_off_hook,
03602 .dial_digits = my_dial_digits,
03603 .train_echocanceller = my_train_echocanceller,
03604 .on_hook = my_on_hook,
03605 .is_dialing = my_is_dialing,
03606 .allocate_sub = my_allocate_sub,
03607 .unallocate_sub = my_unallocate_sub,
03608 .swap_subs = my_swap_subchannels,
03609 .has_voicemail = my_has_voicemail,
03610 .check_for_conference = my_check_for_conference,
03611 .conf_add = my_conf_add,
03612 .conf_del = my_conf_del,
03613 .complete_conference_update = my_complete_conference_update,
03614 .start = my_start,
03615 .all_subchannels_hungup = my_all_subchannels_hungup,
03616 .lock_private = my_lock_private,
03617 .unlock_private = my_unlock_private,
03618 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03619 .handle_dtmf = my_handle_dtmf,
03620 .wink = my_wink,
03621 .new_ast_channel = my_new_analog_ast_channel,
03622 .dsp_set_digitmode = my_dsp_set_digitmode,
03623 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03624 .send_callerid = my_send_callerid,
03625 .callwait = my_callwait,
03626 .stop_callwait = my_stop_callwait,
03627 .get_callerid = my_get_callerid,
03628 .start_cid_detect = my_start_cid_detect,
03629 .stop_cid_detect = my_stop_cid_detect,
03630 .handle_notify_message = my_handle_notify_message,
03631 .increase_ss_count = my_increase_ss_count,
03632 .decrease_ss_count = my_decrease_ss_count,
03633 .distinctive_ring = my_distinctive_ring,
03634 .set_linear_mode = my_set_linear_mode,
03635 .set_inthreeway = my_set_inthreeway,
03636 .get_and_handle_alarms = my_get_and_handle_alarms,
03637 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03638 .get_sub_fd = my_get_sub_fd,
03639 .set_cadence = my_set_cadence,
03640 .set_alarm = my_set_alarm,
03641 .set_dialing = my_set_dialing,
03642 .set_ringtimeout = my_set_ringtimeout,
03643 .set_waitingfordt = my_set_waitingfordt,
03644 .check_waitingfordt = my_check_waitingfordt,
03645 .set_confirmanswer = my_set_confirmanswer,
03646 .check_confirmanswer = my_check_confirmanswer,
03647 .set_callwaiting = my_set_callwaiting,
03648 .cancel_cidspill = my_cancel_cidspill,
03649 .confmute = my_confmute,
03650 .set_pulsedial = my_set_pulsedial,
03651 .set_new_owner = my_set_new_owner,
03652 .get_orig_dialstring = my_get_orig_dialstring,
03653 .set_needringing = my_set_needringing,
03654 .set_polarity = my_set_polarity,
03655 .start_polarityswitch = my_start_polarityswitch,
03656 .answer_polarityswitch = my_answer_polarityswitch,
03657 .hangup_polarityswitch = my_hangup_polarityswitch,
03658 .have_progressdetect = my_have_progressdetect,
03659 };
03660
03661
03662 static struct dahdi_pvt *round_robin[32];
03663
03664 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03665 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03666 {
03667 int res;
03668 if (p->subs[SUB_REAL].owner == ast)
03669 res = 0;
03670 else if (p->subs[SUB_CALLWAIT].owner == ast)
03671 res = 1;
03672 else if (p->subs[SUB_THREEWAY].owner == ast)
03673 res = 2;
03674 else {
03675 res = -1;
03676 if (!nullok)
03677 ast_log(LOG_WARNING,
03678 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03679 ast ? ast->name : "", p->channel, fname, line);
03680 }
03681 return res;
03682 }
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03700 {
03701 for (;;) {
03702 if (!pvt->subs[sub_idx].owner) {
03703
03704 break;
03705 }
03706 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03707
03708 break;
03709 }
03710
03711 DEADLOCK_AVOIDANCE(&pvt->lock);
03712 }
03713 }
03714
03715 static void wakeup_sub(struct dahdi_pvt *p, int a)
03716 {
03717 dahdi_lock_sub_owner(p, a);
03718 if (p->subs[a].owner) {
03719 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03720 ast_channel_unlock(p->subs[a].owner);
03721 }
03722 }
03723
03724 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03725 {
03726 for (;;) {
03727 if (p->owner) {
03728 if (ast_channel_trylock(p->owner)) {
03729 DEADLOCK_AVOIDANCE(&p->lock);
03730 } else {
03731 ast_queue_frame(p->owner, f);
03732 ast_channel_unlock(p->owner);
03733 break;
03734 }
03735 } else
03736 break;
03737 }
03738 }
03739
03740 static void handle_clear_alarms(struct dahdi_pvt *p)
03741 {
03742 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03743 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03744 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03745 }
03746 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03747 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03748 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03749 }
03750 }
03751
03752 #ifdef HAVE_OPENR2
03753
03754 static int dahdi_r2_answer(struct dahdi_pvt *p)
03755 {
03756 int res = 0;
03757
03758
03759
03760 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03761 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03762 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03763 if (!double_answer) {
03764
03765
03766 res = openr2_chan_answer_call(p->r2chan);
03767 } else if (wants_double_answer) {
03768 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03769 } else {
03770 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03771 }
03772 #else
03773 res = openr2_chan_answer_call(p->r2chan);
03774 #endif
03775 return res;
03776 }
03777
03778
03779
03780
03781 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03782 {
03783 openr2_calling_party_category_t cat;
03784 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03785 struct dahdi_pvt *p = c->tech_pvt;
03786 if (ast_strlen_zero(catstr)) {
03787 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03788 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03789 return p->mfcr2_category;
03790 }
03791 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03792 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03793 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03794 return p->mfcr2_category;
03795 }
03796 ast_debug(1, "Using category %s\n", catstr);
03797 return cat;
03798 }
03799
03800 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03801 {
03802 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03803 ast_mutex_lock(&p->lock);
03804 if (p->mfcr2call) {
03805 ast_mutex_unlock(&p->lock);
03806
03807
03808
03809
03810
03811 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03812 return;
03813 }
03814 p->mfcr2call = 1;
03815
03816 p->cid_name[0] = '\0';
03817 p->cid_num[0] = '\0';
03818 p->cid_subaddr[0] = '\0';
03819 p->rdnis[0] = '\0';
03820 p->exten[0] = '\0';
03821 p->mfcr2_ani_index = '\0';
03822 p->mfcr2_dnis_index = '\0';
03823 p->mfcr2_dnis_matched = 0;
03824 p->mfcr2_answer_pending = 0;
03825 p->mfcr2_call_accepted = 0;
03826 ast_mutex_unlock(&p->lock);
03827 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03828 }
03829
03830 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03831 {
03832 int res;
03833 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03834 ast_mutex_lock(&p->lock);
03835 p->inalarm = alarm ? 1 : 0;
03836 if (p->inalarm) {
03837 res = get_alarms(p);
03838 handle_alarms(p, res);
03839 } else {
03840 handle_clear_alarms(p);
03841 }
03842 ast_mutex_unlock(&p->lock);
03843 }
03844
03845 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03846 {
03847 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03848 }
03849
03850 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03851 {
03852 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03853 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03854 if (p->owner) {
03855 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03856 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03857 }
03858 ast_mutex_lock(&p->lock);
03859 p->mfcr2call = 0;
03860 ast_mutex_unlock(&p->lock);
03861 }
03862
03863 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03864 {
03865 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03866 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03867 p->channel, openr2_proto_get_disconnect_string(cause));
03868
03869 openr2_chan_set_idle(p->r2chan);
03870 ast_mutex_lock(&p->lock);
03871 p->mfcr2call = 0;
03872 ast_mutex_unlock(&p->lock);
03873 }
03874 }
03875
03876 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03877 {
03878 struct dahdi_pvt *p;
03879 struct ast_channel *c;
03880 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03881 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03882 openr2_proto_get_category_string(category));
03883 p = openr2_chan_get_client_data(r2chan);
03884
03885 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03886 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03887 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03888 return;
03889 }
03890 ast_mutex_lock(&p->lock);
03891 p->mfcr2_recvd_category = category;
03892
03893 if (!p->use_callerid) {
03894 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03895 p->cid_num[0] = 0;
03896 p->cid_name[0] = 0;
03897 }
03898
03899 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03900 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03901 p->exten[0] = 's';
03902 p->exten[1] = 0;
03903 }
03904 ast_mutex_unlock(&p->lock);
03905 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03906 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03907 p->channel, p->exten, p->context);
03908 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03909 return;
03910 }
03911 if (!p->mfcr2_accept_on_offer) {
03912
03913 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03914 if (c) {
03915
03916
03917
03918 return;
03919 }
03920 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03921 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03922 } else if (p->mfcr2_charge_calls) {
03923 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03924 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03925 } else {
03926 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03927 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03928 }
03929 }
03930
03931 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03932 {
03933 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03934 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03935 ast_mutex_lock(&p->lock);
03936 p->mfcr2call = 0;
03937 ast_mutex_unlock(&p->lock);
03938 }
03939
03940 static void dahdi_enable_ec(struct dahdi_pvt *p);
03941 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03942 {
03943 struct dahdi_pvt *p = NULL;
03944 struct ast_channel *c = NULL;
03945 p = openr2_chan_get_client_data(r2chan);
03946 dahdi_enable_ec(p);
03947 p->mfcr2_call_accepted = 1;
03948
03949 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03950 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03951
03952
03953
03954
03955 if (!p->mfcr2_accept_on_offer) {
03956 openr2_chan_disable_read(r2chan);
03957 if (p->mfcr2_answer_pending) {
03958 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03959 dahdi_r2_answer(p);
03960 }
03961 return;
03962 }
03963 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03964 if (c) {
03965
03966
03967 openr2_chan_disable_read(r2chan);
03968 return;
03969 }
03970 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03971
03972 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03973 return;
03974 }
03975
03976 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03977 p->subs[SUB_REAL].needringing = 1;
03978 p->dialing = 0;
03979
03980 openr2_chan_disable_read(r2chan);
03981 }
03982
03983 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03984 {
03985 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03986 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03987 p->subs[SUB_REAL].needanswer = 1;
03988 }
03989
03990 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03991 {
03992
03993 }
03994
03995 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03996 {
03997 switch (cause) {
03998 case OR2_CAUSE_BUSY_NUMBER:
03999 return AST_CAUSE_BUSY;
04000 case OR2_CAUSE_NETWORK_CONGESTION:
04001 return AST_CAUSE_CONGESTION;
04002 case OR2_CAUSE_OUT_OF_ORDER:
04003 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04004 case OR2_CAUSE_UNALLOCATED_NUMBER:
04005 return AST_CAUSE_UNREGISTERED;
04006 case OR2_CAUSE_NO_ANSWER:
04007 return AST_CAUSE_NO_ANSWER;
04008 case OR2_CAUSE_NORMAL_CLEARING:
04009 return AST_CAUSE_NORMAL_CLEARING;
04010 case OR2_CAUSE_UNSPECIFIED:
04011 default:
04012 return AST_CAUSE_NOTDEFINED;
04013 }
04014 }
04015
04016 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04017 {
04018 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04019 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04020 ast_mutex_lock(&p->lock);
04021 if (!p->owner) {
04022 ast_mutex_unlock(&p->lock);
04023
04024 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04025 return;
04026 }
04027
04028
04029 if (p->owner->_state == AST_STATE_UP) {
04030 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04031 ast_mutex_unlock(&p->lock);
04032 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04033
04034 switch (cause) {
04035 case OR2_CAUSE_BUSY_NUMBER:
04036 p->subs[SUB_REAL].needbusy = 1;
04037 break;
04038 case OR2_CAUSE_NETWORK_CONGESTION:
04039 case OR2_CAUSE_OUT_OF_ORDER:
04040 case OR2_CAUSE_UNALLOCATED_NUMBER:
04041 case OR2_CAUSE_NO_ANSWER:
04042 case OR2_CAUSE_UNSPECIFIED:
04043 case OR2_CAUSE_NORMAL_CLEARING:
04044 p->subs[SUB_REAL].needcongestion = 1;
04045 break;
04046 default:
04047 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04048 }
04049 ast_mutex_unlock(&p->lock);
04050 } else {
04051 ast_mutex_unlock(&p->lock);
04052
04053
04054 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04055 }
04056 }
04057
04058 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04059 {
04060 switch (level) {
04061 case OR2_LOG_NOTICE:
04062 ast_verbose("%s", logmessage);
04063 break;
04064 case OR2_LOG_WARNING:
04065 ast_log(LOG_WARNING, "%s", logmessage);
04066 break;
04067 case OR2_LOG_ERROR:
04068 ast_log(LOG_ERROR, "%s", logmessage);
04069 break;
04070 case OR2_LOG_STACK_TRACE:
04071 case OR2_LOG_MF_TRACE:
04072 case OR2_LOG_CAS_TRACE:
04073 case OR2_LOG_DEBUG:
04074 case OR2_LOG_EX_DEBUG:
04075 ast_log(LOG_DEBUG, "%s", logmessage);
04076 break;
04077 default:
04078 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04079 ast_log(LOG_DEBUG, "%s", logmessage);
04080 break;
04081 }
04082 }
04083
04084 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04085 {
04086 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04087 ast_mutex_lock(&p->lock);
04088 p->remotelyblocked = 1;
04089 ast_mutex_unlock(&p->lock);
04090 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04091 }
04092
04093 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04094 {
04095 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04096 ast_mutex_lock(&p->lock);
04097 p->remotelyblocked = 0;
04098 ast_mutex_unlock(&p->lock);
04099 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04100 }
04101
04102 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04103 __attribute__((format (printf, 3, 0)));
04104 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04105 {
04106 #define CONTEXT_TAG "Context - "
04107 char logmsg[256];
04108 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04109 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04110 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04111 dahdi_r2_write_log(level, completemsg);
04112 #undef CONTEXT_TAG
04113 }
04114
04115 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04116 __attribute__((format (printf, 3, 0)));
04117 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04118 {
04119 #define CHAN_TAG "Chan "
04120 char logmsg[256];
04121 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04122 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04123 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04124 dahdi_r2_write_log(level, completemsg);
04125 }
04126
04127 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04128 {
04129 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04130
04131 if (p->immediate) {
04132 return 0;
04133 }
04134 p->exten[p->mfcr2_dnis_index] = digit;
04135 p->rdnis[p->mfcr2_dnis_index] = digit;
04136 p->mfcr2_dnis_index++;
04137 p->exten[p->mfcr2_dnis_index] = 0;
04138 p->rdnis[p->mfcr2_dnis_index] = 0;
04139
04140 if ((p->mfcr2_dnis_matched ||
04141 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04142 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04143 return 0;
04144 }
04145
04146 return 1;
04147 }
04148
04149 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04150 {
04151 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04152 p->cid_num[p->mfcr2_ani_index] = digit;
04153 p->cid_name[p->mfcr2_ani_index] = digit;
04154 p->mfcr2_ani_index++;
04155 p->cid_num[p->mfcr2_ani_index] = 0;
04156 p->cid_name[p->mfcr2_ani_index] = 0;
04157 }
04158
04159 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04160 {
04161 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04162 }
04163
04164 static openr2_event_interface_t dahdi_r2_event_iface = {
04165 .on_call_init = dahdi_r2_on_call_init,
04166 .on_call_offered = dahdi_r2_on_call_offered,
04167 .on_call_accepted = dahdi_r2_on_call_accepted,
04168 .on_call_answered = dahdi_r2_on_call_answered,
04169 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04170 .on_call_end = dahdi_r2_on_call_end,
04171 .on_call_read = dahdi_r2_on_call_read,
04172 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04173 .on_os_error = dahdi_r2_on_os_error,
04174 .on_protocol_error = dahdi_r2_on_protocol_error,
04175 .on_line_blocked = dahdi_r2_on_line_blocked,
04176 .on_line_idle = dahdi_r2_on_line_idle,
04177
04178 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04179 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04180 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04181
04182 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04183 };
04184
04185 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04186 {
04187 return AST_ALAW(sample);
04188 }
04189
04190 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04191 {
04192 return AST_LIN2A(sample);
04193 }
04194
04195 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04196 dahdi_r2_alaw_to_linear,
04197 dahdi_r2_linear_to_alaw
04198 };
04199
04200 #endif
04201
04202 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04203 {
04204 int tchan;
04205 int tinthreeway;
04206 struct ast_channel *towner;
04207
04208 ast_debug(1, "Swapping %d and %d\n", a, b);
04209
04210 tchan = p->subs[a].chan;
04211 towner = p->subs[a].owner;
04212 tinthreeway = p->subs[a].inthreeway;
04213
04214 p->subs[a].chan = p->subs[b].chan;
04215 p->subs[a].owner = p->subs[b].owner;
04216 p->subs[a].inthreeway = p->subs[b].inthreeway;
04217
04218 p->subs[b].chan = tchan;
04219 p->subs[b].owner = towner;
04220 p->subs[b].inthreeway = tinthreeway;
04221
04222 if (p->subs[a].owner)
04223 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04224 if (p->subs[b].owner)
04225 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04226 wakeup_sub(p, a);
04227 wakeup_sub(p, b);
04228 }
04229
04230 static int dahdi_open(char *fn)
04231 {
04232 int fd;
04233 int isnum;
04234 int chan = 0;
04235 int bs;
04236 int x;
04237 isnum = 1;
04238 for (x = 0; x < strlen(fn); x++) {
04239 if (!isdigit(fn[x])) {
04240 isnum = 0;
04241 break;
04242 }
04243 }
04244 if (isnum) {
04245 chan = atoi(fn);
04246 if (chan < 1) {
04247 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04248 return -1;
04249 }
04250 fn = "/dev/dahdi/channel";
04251 }
04252 fd = open(fn, O_RDWR | O_NONBLOCK);
04253 if (fd < 0) {
04254 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04255 return -1;
04256 }
04257 if (chan) {
04258 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04259 x = errno;
04260 close(fd);
04261 errno = x;
04262 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04263 return -1;
04264 }
04265 }
04266 bs = READ_SIZE;
04267 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04268 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04269 x = errno;
04270 close(fd);
04271 errno = x;
04272 return -1;
04273 }
04274 return fd;
04275 }
04276
04277 static void dahdi_close(int fd)
04278 {
04279 if (fd > 0)
04280 close(fd);
04281 }
04282
04283 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04284 {
04285 dahdi_close(chan_pvt->subs[sub_num].dfd);
04286 chan_pvt->subs[sub_num].dfd = -1;
04287 }
04288
04289 #if defined(HAVE_PRI)
04290 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04291 {
04292 dahdi_close(pri->pri.fds[fd_num]);
04293 pri->pri.fds[fd_num] = -1;
04294 }
04295 #endif
04296
04297 #if defined(HAVE_SS7)
04298 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04299 {
04300 dahdi_close(ss7->ss7.fds[fd_num]);
04301 ss7->ss7.fds[fd_num] = -1;
04302 }
04303 #endif
04304
04305 static int dahdi_setlinear(int dfd, int linear)
04306 {
04307 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04308 }
04309
04310
04311 static int alloc_sub(struct dahdi_pvt *p, int x)
04312 {
04313 struct dahdi_bufferinfo bi;
04314 int res;
04315 if (p->subs[x].dfd >= 0) {
04316 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04317 return -1;
04318 }
04319
04320 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04321 if (p->subs[x].dfd <= -1) {
04322 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04323 return -1;
04324 }
04325
04326 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04327 if (!res) {
04328 bi.txbufpolicy = p->buf_policy;
04329 bi.rxbufpolicy = p->buf_policy;
04330 bi.numbufs = p->buf_no;
04331 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04332 if (res < 0) {
04333 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04334 }
04335 } else
04336 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04337
04338 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04339 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04340 dahdi_close_sub(p, x);
04341 p->subs[x].dfd = -1;
04342 return -1;
04343 }
04344 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04345 return 0;
04346 }
04347
04348 static int unalloc_sub(struct dahdi_pvt *p, int x)
04349 {
04350 if (!x) {
04351 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04352 return -1;
04353 }
04354 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04355 dahdi_close_sub(p, x);
04356 p->subs[x].linear = 0;
04357 p->subs[x].chan = 0;
04358 p->subs[x].owner = NULL;
04359 p->subs[x].inthreeway = 0;
04360 p->polarity = POLARITY_IDLE;
04361 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04362 return 0;
04363 }
04364
04365 static int digit_to_dtmfindex(char digit)
04366 {
04367 if (isdigit(digit))
04368 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04369 else if (digit >= 'A' && digit <= 'D')
04370 return DAHDI_TONE_DTMF_A + (digit - 'A');
04371 else if (digit >= 'a' && digit <= 'd')
04372 return DAHDI_TONE_DTMF_A + (digit - 'a');
04373 else if (digit == '*')
04374 return DAHDI_TONE_DTMF_s;
04375 else if (digit == '#')
04376 return DAHDI_TONE_DTMF_p;
04377 else
04378 return -1;
04379 }
04380
04381 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04382 {
04383 struct dahdi_pvt *pvt;
04384 int idx;
04385 int dtmf = -1;
04386 int res;
04387
04388 pvt = chan->tech_pvt;
04389
04390 ast_mutex_lock(&pvt->lock);
04391
04392 idx = dahdi_get_index(chan, pvt, 0);
04393
04394 if ((idx != SUB_REAL) || !pvt->owner)
04395 goto out;
04396
04397 #ifdef HAVE_PRI
04398 switch (pvt->sig) {
04399 case SIG_PRI_LIB_HANDLE_CASES:
04400 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04401 if (!res)
04402 goto out;
04403 break;
04404 default:
04405 break;
04406 }
04407 #endif
04408 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04409 goto out;
04410
04411 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04412 struct dahdi_dialoperation zo = {
04413 .op = DAHDI_DIAL_OP_APPEND,
04414 };
04415
04416 zo.dialstr[0] = 'T';
04417 zo.dialstr[1] = digit;
04418 zo.dialstr[2] = '\0';
04419 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04420 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04421 else
04422 pvt->dialing = 1;
04423 } else {
04424 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04425 pvt->dialing = 1;
04426 pvt->begindigit = digit;
04427 }
04428
04429 out:
04430 ast_mutex_unlock(&pvt->lock);
04431
04432 return 0;
04433 }
04434
04435 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04436 {
04437 struct dahdi_pvt *pvt;
04438 int res = 0;
04439 int idx;
04440 int x;
04441
04442 pvt = chan->tech_pvt;
04443
04444 ast_mutex_lock(&pvt->lock);
04445
04446 idx = dahdi_get_index(chan, pvt, 0);
04447
04448 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04449 goto out;
04450
04451 #ifdef HAVE_PRI
04452
04453 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04454 goto out;
04455 }
04456 #endif
04457
04458 if (pvt->begindigit) {
04459 x = -1;
04460 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04461 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04462 pvt->dialing = 0;
04463 pvt->begindigit = 0;
04464 }
04465
04466 out:
04467 ast_mutex_unlock(&pvt->lock);
04468
04469 return res;
04470 }
04471
04472 static const char * const events[] = {
04473 "No event",
04474 "On hook",
04475 "Ring/Answered",
04476 "Wink/Flash",
04477 "Alarm",
04478 "No more alarm",
04479 "HDLC Abort",
04480 "HDLC Overrun",
04481 "HDLC Bad FCS",
04482 "Dial Complete",
04483 "Ringer On",
04484 "Ringer Off",
04485 "Hook Transition Complete",
04486 "Bits Changed",
04487 "Pulse Start",
04488 "Timer Expired",
04489 "Timer Ping",
04490 "Polarity Reversal",
04491 "Ring Begin",
04492 };
04493
04494 static struct {
04495 int alarm;
04496 char *name;
04497 } alarms[] = {
04498 { DAHDI_ALARM_RED, "Red Alarm" },
04499 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04500 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04501 { DAHDI_ALARM_RECOVER, "Recovering" },
04502 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04503 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04504 { DAHDI_ALARM_NONE, "None" },
04505 };
04506
04507 static char *alarm2str(int alm)
04508 {
04509 int x;
04510 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04511 if (alarms[x].alarm & alm)
04512 return alarms[x].name;
04513 }
04514 return alm ? "Unknown Alarm" : "No Alarm";
04515 }
04516
04517 static const char *event2str(int event)
04518 {
04519 static char buf[256];
04520 if ((event < (ARRAY_LEN(events))) && (event > -1))
04521 return events[event];
04522 sprintf(buf, "Event %d", event);
04523 return buf;
04524 }
04525
04526 static char *dahdi_sig2str(int sig)
04527 {
04528 static char buf[256];
04529 switch (sig) {
04530 case SIG_EM:
04531 return "E & M Immediate";
04532 case SIG_EMWINK:
04533 return "E & M Wink";
04534 case SIG_EM_E1:
04535 return "E & M E1";
04536 case SIG_FEATD:
04537 return "Feature Group D (DTMF)";
04538 case SIG_FEATDMF:
04539 return "Feature Group D (MF)";
04540 case SIG_FEATDMF_TA:
04541 return "Feature Groud D (MF) Tandem Access";
04542 case SIG_FEATB:
04543 return "Feature Group B (MF)";
04544 case SIG_E911:
04545 return "E911 (MF)";
04546 case SIG_FGC_CAMA:
04547 return "FGC/CAMA (Dialpulse)";
04548 case SIG_FGC_CAMAMF:
04549 return "FGC/CAMA (MF)";
04550 case SIG_FXSLS:
04551 return "FXS Loopstart";
04552 case SIG_FXSGS:
04553 return "FXS Groundstart";
04554 case SIG_FXSKS:
04555 return "FXS Kewlstart";
04556 case SIG_FXOLS:
04557 return "FXO Loopstart";
04558 case SIG_FXOGS:
04559 return "FXO Groundstart";
04560 case SIG_FXOKS:
04561 return "FXO Kewlstart";
04562 case SIG_PRI:
04563 return "ISDN PRI";
04564 case SIG_BRI:
04565 return "ISDN BRI Point to Point";
04566 case SIG_BRI_PTMP:
04567 return "ISDN BRI Point to MultiPoint";
04568 case SIG_SS7:
04569 return "SS7";
04570 case SIG_MFCR2:
04571 return "MFC/R2";
04572 case SIG_SF:
04573 return "SF (Tone) Immediate";
04574 case SIG_SFWINK:
04575 return "SF (Tone) Wink";
04576 case SIG_SF_FEATD:
04577 return "SF (Tone) with Feature Group D (DTMF)";
04578 case SIG_SF_FEATDMF:
04579 return "SF (Tone) with Feature Group D (MF)";
04580 case SIG_SF_FEATB:
04581 return "SF (Tone) with Feature Group B (MF)";
04582 case 0:
04583 return "Pseudo";
04584 default:
04585 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04586 return buf;
04587 }
04588 }
04589
04590 #define sig2str dahdi_sig2str
04591
04592 static int analog_lib_handles(int signalling, int radio, int oprmode)
04593 {
04594 switch (signalling) {
04595 case SIG_FXOLS:
04596 case SIG_FXOGS:
04597 case SIG_FXOKS:
04598 case SIG_FXSLS:
04599 case SIG_FXSGS:
04600 case SIG_FXSKS:
04601 case SIG_EMWINK:
04602 case SIG_EM:
04603 case SIG_EM_E1:
04604 case SIG_FEATD:
04605 case SIG_FEATDMF:
04606 case SIG_E911:
04607 case SIG_FGC_CAMA:
04608 case SIG_FGC_CAMAMF:
04609 case SIG_FEATB:
04610 case SIG_SFWINK:
04611 case SIG_SF:
04612 case SIG_SF_FEATD:
04613 case SIG_SF_FEATDMF:
04614 case SIG_FEATDMF_TA:
04615 case SIG_SF_FEATB:
04616 break;
04617 default:
04618
04619 return 0;
04620 }
04621
04622 if (radio)
04623 return 0;
04624
04625 if (oprmode)
04626 return 0;
04627
04628 return 1;
04629 }
04630
04631 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04632 {
04633
04634
04635 struct dahdi_confinfo zi;
04636
04637 memset(&zi, 0, sizeof(zi));
04638 zi.chan = 0;
04639
04640 if (slavechannel > 0) {
04641
04642 zi.confmode = DAHDI_CONF_DIGITALMON;
04643 zi.confno = slavechannel;
04644 } else {
04645 if (!idx) {
04646
04647 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04648 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04649 } else
04650 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04651 zi.confno = p->confno;
04652 }
04653 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04654 return 0;
04655 if (c->dfd < 0)
04656 return 0;
04657 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04658 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04659 return -1;
04660 }
04661 if (slavechannel < 1) {
04662 p->confno = zi.confno;
04663 }
04664 c->curconf = zi;
04665 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04666 return 0;
04667 }
04668
04669 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04670 {
04671
04672 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04673 return 1;
04674
04675 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04676 return 1;
04677 return 0;
04678 }
04679
04680 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04681 {
04682 struct dahdi_confinfo zi;
04683 if (
04684 (c->dfd < 0) ||
04685
04686 !isourconf(p, c)
04687
04688 ) return 0;
04689 memset(&zi, 0, sizeof(zi));
04690 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04691 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04692 return -1;
04693 }
04694 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04695 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04696 return 0;
04697 }
04698
04699 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04700 {
04701 int x;
04702 int useslavenative;
04703 struct dahdi_pvt *slave = NULL;
04704
04705 useslavenative = 1;
04706
04707 for (x = 0; x < 3; x++) {
04708
04709
04710 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04711 useslavenative = 0;
04712 }
04713
04714
04715 if (useslavenative) {
04716 for (x = 0; x < MAX_SLAVES; x++) {
04717 if (p->slaves[x]) {
04718 if (slave) {
04719
04720
04721 slave = NULL;
04722 useslavenative = 0;
04723 break;
04724 } else {
04725
04726 slave = p->slaves[x];
04727 }
04728 }
04729 }
04730 }
04731
04732 if (!slave)
04733 useslavenative = 0;
04734 else if (slave->law != p->law) {
04735 useslavenative = 0;
04736 slave = NULL;
04737 }
04738 if (out)
04739 *out = slave;
04740 return useslavenative;
04741 }
04742
04743 static int reset_conf(struct dahdi_pvt *p)
04744 {
04745 p->confno = -1;
04746 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04747 if (p->subs[SUB_REAL].dfd > -1) {
04748 struct dahdi_confinfo zi;
04749
04750 memset(&zi, 0, sizeof(zi));
04751 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04752 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04753 }
04754 return 0;
04755 }
04756
04757 static int update_conf(struct dahdi_pvt *p)
04758 {
04759 int needconf = 0;
04760 int x;
04761 int useslavenative;
04762 struct dahdi_pvt *slave = NULL;
04763
04764 useslavenative = isslavenative(p, &slave);
04765
04766 for (x = 0; x < 3; x++) {
04767
04768 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04769 conf_add(p, &p->subs[x], x, 0);
04770 needconf++;
04771 } else {
04772 conf_del(p, &p->subs[x], x);
04773 }
04774 }
04775
04776
04777 for (x = 0; x < MAX_SLAVES; x++) {
04778 if (p->slaves[x]) {
04779 if (useslavenative)
04780 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04781 else {
04782 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04783 needconf++;
04784 }
04785 }
04786 }
04787
04788 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04789 if (useslavenative)
04790 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04791 else {
04792 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04793 needconf++;
04794 }
04795 }
04796
04797 if (p->master) {
04798 if (isslavenative(p->master, NULL)) {
04799 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04800 } else {
04801 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04802 }
04803 }
04804 if (!needconf) {
04805
04806
04807 p->confno = -1;
04808 }
04809 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04810 return 0;
04811 }
04812
04813 static void dahdi_enable_ec(struct dahdi_pvt *p)
04814 {
04815 int res;
04816 if (!p)
04817 return;
04818 if (p->echocanon) {
04819 ast_debug(1, "Echo cancellation already on\n");
04820 return;
04821 }
04822 if (p->digital) {
04823 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04824 return;
04825 }
04826 if (p->echocancel.head.tap_length) {
04827 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04828 switch (p->sig) {
04829 #if defined(HAVE_PRI)
04830 case SIG_PRI_LIB_HANDLE_CASES:
04831 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04832
04833
04834
04835
04836 return;
04837 }
04838
04839 #endif
04840 #if defined(HAVE_SS7)
04841 case SIG_SS7:
04842 #endif
04843 {
04844 int x = 1;
04845
04846 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04847 if (res)
04848 ast_log(LOG_WARNING,
04849 "Unable to enable audio mode on channel %d (%s)\n",
04850 p->channel, strerror(errno));
04851 }
04852 break;
04853 default:
04854 break;
04855 }
04856 #endif
04857 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04858 if (res) {
04859 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04860 } else {
04861 p->echocanon = 1;
04862 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04863 }
04864 } else
04865 ast_debug(1, "No echo cancellation requested\n");
04866 }
04867
04868 static void dahdi_train_ec(struct dahdi_pvt *p)
04869 {
04870 int x;
04871 int res;
04872
04873 if (p && p->echocanon && p->echotraining) {
04874 x = p->echotraining;
04875 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04876 if (res)
04877 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04878 else
04879 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04880 } else {
04881 ast_debug(1, "No echo training requested\n");
04882 }
04883 }
04884
04885 static void dahdi_disable_ec(struct dahdi_pvt *p)
04886 {
04887 int res;
04888
04889 if (p->echocanon) {
04890 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04891
04892 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04893
04894 if (res)
04895 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04896 else
04897 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04898 }
04899
04900 p->echocanon = 0;
04901 }
04902
04903
04904 static int drc_sample(int sample, float drc)
04905 {
04906 float neg;
04907 float shallow, steep;
04908 float max = SHRT_MAX;
04909
04910 neg = (sample < 0 ? -1 : 1);
04911 steep = drc*sample;
04912 shallow = neg*(max-max/drc)+(float)sample/drc;
04913 if (abs(steep) < abs(shallow)) {
04914 sample = steep;
04915 }
04916 else {
04917 sample = shallow;
04918 }
04919
04920 return sample;
04921 }
04922
04923
04924 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04925 {
04926 int j;
04927 int k;
04928
04929 float linear_gain = pow(10.0, gain / 20.0);
04930
04931 switch (law) {
04932 case DAHDI_LAW_ALAW:
04933 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04934 if (gain || drc) {
04935 k = AST_ALAW(j);
04936 if (drc) {
04937 k = drc_sample(k, drc);
04938 }
04939 k = (float)k*linear_gain;
04940 if (k > 32767) k = 32767;
04941 if (k < -32767) k = -32767;
04942 g->txgain[j] = AST_LIN2A(k);
04943 } else {
04944 g->txgain[j] = j;
04945 }
04946 }
04947 break;
04948 case DAHDI_LAW_MULAW:
04949 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04950 if (gain || drc) {
04951 k = AST_MULAW(j);
04952 if (drc) {
04953 k = drc_sample(k, drc);
04954 }
04955 k = (float)k*linear_gain;
04956 if (k > 32767) k = 32767;
04957 if (k < -32767) k = -32767;
04958 g->txgain[j] = AST_LIN2MU(k);
04959
04960 } else {
04961 g->txgain[j] = j;
04962 }
04963 }
04964 break;
04965 }
04966 }
04967
04968 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04969 {
04970 int j;
04971 int k;
04972 float linear_gain = pow(10.0, gain / 20.0);
04973
04974 switch (law) {
04975 case DAHDI_LAW_ALAW:
04976 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04977 if (gain || drc) {
04978 k = AST_ALAW(j);
04979 if (drc) {
04980 k = drc_sample(k, drc);
04981 }
04982 k = (float)k*linear_gain;
04983 if (k > 32767) k = 32767;
04984 if (k < -32767) k = -32767;
04985 g->rxgain[j] = AST_LIN2A(k);
04986 } else {
04987 g->rxgain[j] = j;
04988 }
04989 }
04990 break;
04991 case DAHDI_LAW_MULAW:
04992 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04993 if (gain || drc) {
04994 k = AST_MULAW(j);
04995 if (drc) {
04996 k = drc_sample(k, drc);
04997 }
04998 k = (float)k*linear_gain;
04999 if (k > 32767) k = 32767;
05000 if (k < -32767) k = -32767;
05001 g->rxgain[j] = AST_LIN2MU(k);
05002 } else {
05003 g->rxgain[j] = j;
05004 }
05005 }
05006 break;
05007 }
05008 }
05009
05010 static int set_actual_txgain(int fd, float gain, float drc, int law)
05011 {
05012 struct dahdi_gains g;
05013 int res;
05014
05015 memset(&g, 0, sizeof(g));
05016 res = ioctl(fd, DAHDI_GETGAINS, &g);
05017 if (res) {
05018 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05019 return res;
05020 }
05021
05022 fill_txgain(&g, gain, drc, law);
05023
05024 return ioctl(fd, DAHDI_SETGAINS, &g);
05025 }
05026
05027 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05028 {
05029 struct dahdi_gains g;
05030 int res;
05031
05032 memset(&g, 0, sizeof(g));
05033 res = ioctl(fd, DAHDI_GETGAINS, &g);
05034 if (res) {
05035 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05036 return res;
05037 }
05038
05039 fill_rxgain(&g, gain, drc, law);
05040
05041 return ioctl(fd, DAHDI_SETGAINS, &g);
05042 }
05043
05044 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05045 {
05046 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05047 }
05048
05049 static int bump_gains(struct dahdi_pvt *p)
05050 {
05051 int res;
05052
05053
05054 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05055 if (res) {
05056 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05057 return -1;
05058 }
05059
05060 return 0;
05061 }
05062
05063 static int restore_gains(struct dahdi_pvt *p)
05064 {
05065 int res;
05066
05067 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05068 if (res) {
05069 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05070 return -1;
05071 }
05072
05073 return 0;
05074 }
05075
05076 static inline int dahdi_set_hook(int fd, int hs)
05077 {
05078 int x, res;
05079
05080 x = hs;
05081 res = ioctl(fd, DAHDI_HOOK, &x);
05082
05083 if (res < 0) {
05084 if (errno == EINPROGRESS)
05085 return 0;
05086 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05087
05088 }
05089
05090 return res;
05091 }
05092
05093 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05094 {
05095 int x, res;
05096
05097 x = muted;
05098 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05099 switch (p->sig) {
05100 #if defined(HAVE_PRI)
05101 case SIG_PRI_LIB_HANDLE_CASES:
05102 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05103
05104 break;
05105 }
05106
05107 #endif
05108 #if defined(HAVE_SS7)
05109 case SIG_SS7:
05110 #endif
05111 {
05112 int y = 1;
05113
05114 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05115 if (res)
05116 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05117 p->channel, strerror(errno));
05118 }
05119 break;
05120 default:
05121 break;
05122 }
05123 #endif
05124 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05125 if (res < 0)
05126 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05127 return res;
05128 }
05129
05130 static int save_conference(struct dahdi_pvt *p)
05131 {
05132 struct dahdi_confinfo c;
05133 int res;
05134 if (p->saveconf.confmode) {
05135 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05136 return -1;
05137 }
05138 p->saveconf.chan = 0;
05139 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05140 if (res) {
05141 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05142 p->saveconf.confmode = 0;
05143 return -1;
05144 }
05145 memset(&c, 0, sizeof(c));
05146 c.confmode = DAHDI_CONF_NORMAL;
05147 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05148 if (res) {
05149 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05150 return -1;
05151 }
05152 ast_debug(1, "Disabled conferencing\n");
05153 return 0;
05154 }
05155
05156 static int restore_conference(struct dahdi_pvt *p)
05157 {
05158 int res;
05159 if (p->saveconf.confmode) {
05160 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05161 p->saveconf.confmode = 0;
05162 if (res) {
05163 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05164 return -1;
05165 }
05166 ast_debug(1, "Restored conferencing\n");
05167 }
05168 return 0;
05169 }
05170
05171 static int send_cwcidspill(struct dahdi_pvt *p)
05172 {
05173 p->callwaitcas = 0;
05174 p->cidcwexpire = 0;
05175 p->cid_suppress_expire = 0;
05176 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05177 return -1;
05178 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05179
05180 p->cidlen += READ_SIZE * 4;
05181 p->cidpos = 0;
05182 send_callerid(p);
05183 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05184 return 0;
05185 }
05186
05187 static int has_voicemail(struct dahdi_pvt *p)
05188 {
05189 int new_msgs;
05190 struct ast_event *event;
05191 char *mailbox, *context;
05192
05193 mailbox = context = ast_strdupa(p->mailbox);
05194 strsep(&context, "@");
05195 if (ast_strlen_zero(context))
05196 context = "default";
05197
05198 event = ast_event_get_cached(AST_EVENT_MWI,
05199 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05200 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05201 AST_EVENT_IE_END);
05202
05203 if (event) {
05204 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05205 ast_event_destroy(event);
05206 } else
05207 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05208
05209 return new_msgs;
05210 }
05211
05212
05213
05214 static int send_callerid(struct dahdi_pvt *p)
05215 {
05216
05217 int res;
05218
05219 if (p->subs[SUB_REAL].linear) {
05220 p->subs[SUB_REAL].linear = 0;
05221 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05222 }
05223 while (p->cidpos < p->cidlen) {
05224 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05225 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05226 if (res < 0) {
05227 if (errno == EAGAIN)
05228 return 0;
05229 else {
05230 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05231 return -1;
05232 }
05233 }
05234 if (!res)
05235 return 0;
05236 p->cidpos += res;
05237 }
05238 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05239 ast_free(p->cidspill);
05240 p->cidspill = NULL;
05241 if (p->callwaitcas) {
05242
05243 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05244 p->cid_suppress_expire = p->cidcwexpire;
05245 } else
05246 restore_conference(p);
05247 return 0;
05248 }
05249
05250 static int dahdi_callwait(struct ast_channel *ast)
05251 {
05252 struct dahdi_pvt *p = ast->tech_pvt;
05253 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05254 if (p->cidspill) {
05255 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05256 ast_free(p->cidspill);
05257 }
05258
05259
05260
05261
05262
05263 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05264 return -1;
05265 save_conference(p);
05266
05267 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05268 if (!p->callwaitrings && p->callwaitingcallerid) {
05269 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05270 p->callwaitcas = 1;
05271 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05272 } else {
05273 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05274 p->callwaitcas = 0;
05275 p->cidlen = 2400 + READ_SIZE * 4;
05276 }
05277 p->cidpos = 0;
05278 send_callerid(p);
05279
05280 return 0;
05281 }
05282
05283 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05284 {
05285 struct dahdi_pvt *p = ast->tech_pvt;
05286 int x, res, mysig;
05287 char dest[256];
05288
05289 ast_mutex_lock(&p->lock);
05290 ast_copy_string(dest, rdest, sizeof(dest));
05291 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05292 if ((ast->_state == AST_STATE_BUSY)) {
05293 p->subs[SUB_REAL].needbusy = 1;
05294 ast_mutex_unlock(&p->lock);
05295 return 0;
05296 }
05297 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05298 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05299 ast_mutex_unlock(&p->lock);
05300 return -1;
05301 }
05302 p->waitingfordt.tv_sec = 0;
05303 p->dialednone = 0;
05304 if ((p->radio || (p->oprmode < 0)))
05305 {
05306
05307 ast_setstate(ast, AST_STATE_UP);
05308 ast_mutex_unlock(&p->lock);
05309 return 0;
05310 }
05311 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05312 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05313 if (res)
05314 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05315 p->outgoing = 1;
05316
05317 if (IS_DIGITAL(ast->transfercapability)){
05318 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05319 } else {
05320 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05321 }
05322
05323 #ifdef HAVE_PRI
05324 if (dahdi_sig_pri_lib_handles(p->sig)) {
05325 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05326 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05327 ast_mutex_unlock(&p->lock);
05328 return res;
05329 }
05330 #endif
05331
05332 #if defined(HAVE_SS7)
05333 if (p->sig == SIG_SS7) {
05334 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05335 ast_mutex_unlock(&p->lock);
05336 return res;
05337 }
05338 #endif
05339
05340
05341 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05342 p->callwaitrings = 0;
05343 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05344 ast_mutex_unlock(&p->lock);
05345 return res;
05346 }
05347
05348 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05349 switch (mysig) {
05350 case 0:
05351
05352 ast_setstate(ast, AST_STATE_UP);
05353 break;
05354 case SIG_MFCR2:
05355 break;
05356 default:
05357 ast_debug(1, "not yet implemented\n");
05358 ast_mutex_unlock(&p->lock);
05359 return -1;
05360 }
05361
05362 #ifdef HAVE_OPENR2
05363 if (p->mfcr2) {
05364 openr2_calling_party_category_t chancat;
05365 int callres = 0;
05366 char *c, *l;
05367
05368
05369 p->dialdest[0] = '\0';
05370
05371 c = strchr(dest, '/');
05372 if (c) {
05373 c++;
05374 } else {
05375 c = "";
05376 }
05377 if (!p->hidecallerid) {
05378 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05379 } else {
05380 l = NULL;
05381 }
05382 if (strlen(c) < p->stripmsd) {
05383 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05384 ast_mutex_unlock(&p->lock);
05385 return -1;
05386 }
05387 p->dialing = 1;
05388 chancat = dahdi_r2_get_channel_category(ast);
05389 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05390 if (-1 == callres) {
05391 ast_mutex_unlock(&p->lock);
05392 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05393 return -1;
05394 }
05395 p->mfcr2_call_accepted = 0;
05396 p->mfcr2_progress = 0;
05397 ast_setstate(ast, AST_STATE_DIALING);
05398 }
05399 #endif
05400 ast_mutex_unlock(&p->lock);
05401 return 0;
05402 }
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05420 {
05421 struct dahdi_pvt *cur;
05422
05423 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05424
05425
05426 for (cur = iflist; cur; cur = cur->next) {
05427 if (pvt->channel < cur->channel) {
05428
05429 pvt->prev = cur->prev;
05430 pvt->next = cur;
05431 if (cur->prev) {
05432
05433 cur->prev->next = pvt;
05434 } else {
05435
05436 iflist = pvt;
05437 }
05438 cur->prev = pvt;
05439 return;
05440 }
05441 }
05442
05443
05444 pvt->prev = ifend;
05445 pvt->next = NULL;
05446 if (ifend) {
05447 ifend->next = pvt;
05448 }
05449 ifend = pvt;
05450 if (!iflist) {
05451
05452 iflist = pvt;
05453 }
05454 }
05455
05456
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05470 {
05471
05472 if (pvt->prev) {
05473 pvt->prev->next = pvt->next;
05474 } else if (iflist == pvt) {
05475
05476 iflist = pvt->next;
05477 }
05478
05479
05480 if (pvt->next) {
05481 pvt->next->prev = pvt->prev;
05482 } else if (ifend == pvt) {
05483
05484 ifend = pvt->prev;
05485 }
05486
05487
05488 pvt->which_iflist = DAHDI_IFLIST_NONE;
05489 pvt->prev = NULL;
05490 pvt->next = NULL;
05491 }
05492
05493 #if defined(HAVE_PRI)
05494
05495
05496
05497
05498
05499
05500
05501
05502
05503
05504
05505
05506
05507
05508
05509
05510 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05511 {
05512 struct dahdi_pvt *cur;
05513
05514 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05515
05516
05517 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05518 if (pvt->channel < cur->channel) {
05519
05520 pvt->prev = cur->prev;
05521 pvt->next = cur;
05522 if (cur->prev) {
05523
05524 cur->prev->next = pvt;
05525 } else {
05526
05527 pri->no_b_chan_iflist = pvt;
05528 }
05529 cur->prev = pvt;
05530 return;
05531 }
05532 }
05533
05534
05535 pvt->prev = pri->no_b_chan_end;
05536 pvt->next = NULL;
05537 if (pri->no_b_chan_end) {
05538 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05539 }
05540 pri->no_b_chan_end = pvt;
05541 if (!pri->no_b_chan_iflist) {
05542
05543 pri->no_b_chan_iflist = pvt;
05544 }
05545 }
05546 #endif
05547
05548 #if defined(HAVE_PRI)
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05564 {
05565
05566 if (pvt->prev) {
05567 pvt->prev->next = pvt->next;
05568 } else if (pri->no_b_chan_iflist == pvt) {
05569
05570 pri->no_b_chan_iflist = pvt->next;
05571 }
05572
05573
05574 if (pvt->next) {
05575 pvt->next->prev = pvt->prev;
05576 } else if (pri->no_b_chan_end == pvt) {
05577
05578 pri->no_b_chan_end = pvt->prev;
05579 }
05580
05581
05582 pvt->which_iflist = DAHDI_IFLIST_NONE;
05583 pvt->prev = NULL;
05584 pvt->next = NULL;
05585 }
05586 #endif
05587
05588 #if defined(HAVE_PRI)
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05599 {
05600 unsigned idx;
05601 struct sig_pri_span *pri;
05602
05603 pri = pvt->pri;
05604 if (!pri) {
05605
05606 return;
05607 }
05608 ast_mutex_lock(&pri->lock);
05609 for (idx = 0; idx < pri->numchans; ++idx) {
05610 if (pri->pvts[idx] == pvt->sig_pvt) {
05611 pri->pvts[idx] = NULL;
05612 ast_mutex_unlock(&pri->lock);
05613 return;
05614 }
05615 }
05616 ast_mutex_unlock(&pri->lock);
05617 }
05618 #endif
05619
05620 #if defined(HAVE_SS7)
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05631 {
05632 unsigned idx;
05633 struct sig_ss7_linkset *ss7;
05634
05635 ss7 = pvt->ss7;
05636 if (!ss7) {
05637
05638 return;
05639 }
05640 ast_mutex_lock(&ss7->lock);
05641 for (idx = 0; idx < ss7->numchans; ++idx) {
05642 if (ss7->pvts[idx] == pvt->sig_pvt) {
05643 ss7->pvts[idx] = NULL;
05644 ast_mutex_unlock(&ss7->lock);
05645 return;
05646 }
05647 }
05648 ast_mutex_unlock(&ss7->lock);
05649 }
05650 #endif
05651
05652 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05653 {
05654 if (cur->next && cur->next->span == cur->span) {
05655 return cur->next;
05656 } else if (cur->prev && cur->prev->span == cur->span) {
05657 return cur->prev;
05658 }
05659
05660 return NULL;
05661 }
05662
05663 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05664 {
05665 struct dahdi_pvt *p = pvt;
05666
05667 if (p->manages_span_alarms) {
05668 struct dahdi_pvt *next = find_next_iface_in_span(p);
05669 if (next) {
05670 next->manages_span_alarms = 1;
05671 }
05672 }
05673
05674
05675 #if defined(HAVE_PRI)
05676 dahdi_unlink_pri_pvt(p);
05677 #endif
05678 #if defined(HAVE_SS7)
05679 dahdi_unlink_ss7_pvt(p);
05680 #endif
05681 switch (pvt->which_iflist) {
05682 case DAHDI_IFLIST_NONE:
05683 break;
05684 case DAHDI_IFLIST_MAIN:
05685 dahdi_iflist_extract(p);
05686 break;
05687 #if defined(HAVE_PRI)
05688 case DAHDI_IFLIST_NO_B_CHAN:
05689 if (p->pri) {
05690 dahdi_nobch_extract(p->pri, p);
05691 }
05692 break;
05693 #endif
05694 }
05695
05696 if (p->sig_pvt) {
05697 if (analog_lib_handles(p->sig, 0, 0)) {
05698 analog_delete(p->sig_pvt);
05699 }
05700 switch (p->sig) {
05701 #if defined(HAVE_PRI)
05702 case SIG_PRI_LIB_HANDLE_CASES:
05703 sig_pri_chan_delete(p->sig_pvt);
05704 break;
05705 #endif
05706 #if defined(HAVE_SS7)
05707 case SIG_SS7:
05708 sig_ss7_chan_delete(p->sig_pvt);
05709 break;
05710 #endif
05711 default:
05712 break;
05713 }
05714 }
05715 ast_free(p->cidspill);
05716 if (p->use_smdi)
05717 ast_smdi_interface_unref(p->smdi_iface);
05718 if (p->mwi_event_sub)
05719 ast_event_unsubscribe(p->mwi_event_sub);
05720 if (p->vars) {
05721 ast_variables_destroy(p->vars);
05722 }
05723 if (p->cc_params) {
05724 ast_cc_config_params_destroy(p->cc_params);
05725 }
05726 ast_mutex_destroy(&p->lock);
05727 dahdi_close_sub(p, SUB_REAL);
05728 if (p->owner)
05729 p->owner->tech_pvt = NULL;
05730 ast_free(p);
05731 }
05732
05733 static void destroy_channel(struct dahdi_pvt *cur, int now)
05734 {
05735 int i;
05736
05737 if (!now) {
05738
05739 if (cur->owner) {
05740 return;
05741 }
05742 for (i = 0; i < 3; i++) {
05743 if (cur->subs[i].owner) {
05744 return;
05745 }
05746 }
05747 }
05748 destroy_dahdi_pvt(cur);
05749 }
05750
05751 static void destroy_all_channels(void)
05752 {
05753 int chan;
05754 #if defined(HAVE_PRI)
05755 unsigned span;
05756 struct sig_pri_span *pri;
05757 #endif
05758 struct dahdi_pvt *p;
05759
05760 while (num_restart_pending) {
05761 usleep(1);
05762 }
05763
05764 ast_mutex_lock(&iflock);
05765
05766 while (iflist) {
05767 p = iflist;
05768
05769 chan = p->channel;
05770 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05771 {
05772 char db_chan_name[20];
05773 char db_answer[5];
05774 char state;
05775 int why = -1;
05776
05777 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05778 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05779 sscanf(db_answer, "%1c:%30d", &state, &why);
05780 }
05781 if (!why) {
05782
05783 ast_db_del(db_chan_name, SRVST_DBKEY);
05784 }
05785 }
05786 #endif
05787
05788 destroy_dahdi_pvt(p);
05789 ast_verb(3, "Unregistered channel %d\n", chan);
05790 }
05791 ifcount = 0;
05792 ast_mutex_unlock(&iflock);
05793
05794 #if defined(HAVE_PRI)
05795
05796 for (span = 0; span < NUM_SPANS; ++span) {
05797 if (!pris[span].dchannels[0]) {
05798 break;
05799 }
05800 pri = &pris[span].pri;
05801 ast_mutex_lock(&pri->lock);
05802 while (pri->no_b_chan_iflist) {
05803 p = pri->no_b_chan_iflist;
05804
05805
05806 destroy_dahdi_pvt(p);
05807 }
05808 ast_mutex_unlock(&pri->lock);
05809 }
05810 #endif
05811 }
05812
05813 #if defined(HAVE_PRI)
05814 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05815
05816 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05817 {
05818
05819 struct dahdi_pvt *p;
05820
05821 if (ast_strlen_zero(digits)) {
05822 ast_debug(1, "No digit string sent to application!\n");
05823 return -1;
05824 }
05825
05826 p = (struct dahdi_pvt *)chan->tech_pvt;
05827
05828 if (!p) {
05829 ast_debug(1, "Unable to find technology private\n");
05830 return -1;
05831 }
05832
05833 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05834
05835 return 0;
05836 }
05837 #endif
05838
05839 #if defined(HAVE_PRI)
05840 #if defined(HAVE_PRI_PROG_W_CAUSE)
05841 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05842
05843 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05844 {
05845
05846 struct dahdi_pvt *pvt;
05847 char *parse;
05848 int res = -1;
05849 AST_DECLARE_APP_ARGS(args,
05850 AST_APP_ARG(destination);
05851 AST_APP_ARG(original);
05852 AST_APP_ARG(reason);
05853 );
05854
05855 if (ast_strlen_zero(data)) {
05856 ast_log(LOG_DEBUG, "No data sent to application!\n");
05857 return -1;
05858 }
05859 if (chan->tech != &dahdi_tech) {
05860 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05861 return -1;
05862 }
05863 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05864 if (!pvt) {
05865 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05866 return -1;
05867 }
05868 switch (pvt->sig) {
05869 case SIG_PRI_LIB_HANDLE_CASES:
05870 break;
05871 default:
05872 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05873 chan->name);
05874 return -1;
05875 }
05876
05877 parse = ast_strdupa(data);
05878 AST_STANDARD_APP_ARGS(args, parse);
05879
05880 if (ast_strlen_zero(args.destination)) {
05881 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05882 return -1;
05883 }
05884
05885 if (ast_strlen_zero(args.original)) {
05886 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05887 args.original = NULL;
05888 }
05889
05890 if (ast_strlen_zero(args.reason)) {
05891 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05892 args.reason = NULL;
05893 }
05894
05895 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05896 args.original, args.reason);
05897
05898 return res;
05899 }
05900 #endif
05901 #endif
05902
05903 #if defined(HAVE_OPENR2)
05904 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05905
05906 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05907 {
05908
05909 openr2_call_mode_t accept_mode;
05910 int res, timeout, maxloops;
05911 struct ast_frame *f;
05912 struct dahdi_pvt *p;
05913 char *parse;
05914 AST_DECLARE_APP_ARGS(args,
05915 AST_APP_ARG(charge);
05916 );
05917
05918 if (ast_strlen_zero(data)) {
05919 ast_log(LOG_DEBUG, "No data sent to application!\n");
05920 return -1;
05921 }
05922
05923 if (chan->tech != &dahdi_tech) {
05924 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05925 return -1;
05926 }
05927
05928 p = (struct dahdi_pvt *)chan->tech_pvt;
05929 if (!p) {
05930 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05931 return -1;
05932 }
05933
05934 parse = ast_strdupa(data);
05935 AST_STANDARD_APP_ARGS(args, parse);
05936
05937 if (ast_strlen_zero(args.charge)) {
05938 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05939 return -1;
05940 }
05941
05942 ast_mutex_lock(&p->lock);
05943 if (!p->mfcr2 || !p->mfcr2call) {
05944 ast_mutex_unlock(&p->lock);
05945 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05946 return -1;
05947 }
05948
05949 if (p->mfcr2_call_accepted) {
05950 ast_mutex_unlock(&p->lock);
05951 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05952 return 0;
05953 }
05954 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05955 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05956 ast_mutex_unlock(&p->lock);
05957 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05958 return -1;
05959 }
05960 ast_mutex_unlock(&p->lock);
05961
05962 res = 0;
05963 timeout = 100;
05964 maxloops = 50;
05965
05966 while (maxloops > 0) {
05967 maxloops--;
05968 if (ast_check_hangup(chan)) {
05969 break;
05970 }
05971 res = ast_waitfor(chan, timeout);
05972 if (res < 0) {
05973 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05974 res = -1;
05975 break;
05976 }
05977 if (res == 0) {
05978 continue;
05979 }
05980 f = ast_read(chan);
05981 if (!f) {
05982 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05983 res = -1;
05984 break;
05985 }
05986 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05987 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05988 ast_frfree(f);
05989 res = -1;
05990 break;
05991 }
05992 ast_frfree(f);
05993 ast_mutex_lock(&p->lock);
05994 if (p->mfcr2_call_accepted) {
05995 ast_mutex_unlock(&p->lock);
05996 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05997 break;
05998 }
05999 ast_mutex_unlock(&p->lock);
06000 }
06001 if (res == -1) {
06002 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06003 }
06004 return res;
06005 }
06006
06007 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06008 {
06009 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06010 switch (cause) {
06011 case AST_CAUSE_USER_BUSY:
06012 case AST_CAUSE_CALL_REJECTED:
06013 case AST_CAUSE_INTERWORKING:
06014 r2cause = OR2_CAUSE_BUSY_NUMBER;
06015 break;
06016
06017 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06018 case AST_CAUSE_SWITCH_CONGESTION:
06019 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06020 break;
06021
06022 case AST_CAUSE_UNALLOCATED:
06023 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06024 break;
06025
06026 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06027 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06028 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06029 break;
06030
06031 case AST_CAUSE_NO_ANSWER:
06032 case AST_CAUSE_NO_USER_RESPONSE:
06033 r2cause = OR2_CAUSE_NO_ANSWER;
06034 break;
06035
06036 default:
06037 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06038 break;
06039 }
06040 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06041 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06042 return r2cause;
06043 }
06044 #endif
06045
06046 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06047 {
06048 if (p->bufferoverrideinuse) {
06049
06050 struct dahdi_bufferinfo bi = {
06051 .txbufpolicy = p->buf_policy,
06052 .rxbufpolicy = p->buf_policy,
06053 .bufsize = p->bufsize,
06054 .numbufs = p->buf_no
06055 };
06056 int bpres;
06057
06058 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06059 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06060 }
06061 p->bufferoverrideinuse = 0;
06062 return bpres;
06063 }
06064
06065 return -1;
06066 }
06067
06068 static int dahdi_hangup(struct ast_channel *ast)
06069 {
06070 int res = 0;
06071 int idx,x;
06072 int law;
06073
06074 struct dahdi_pvt *p = ast->tech_pvt;
06075 struct dahdi_params par;
06076
06077 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06078 if (!ast->tech_pvt) {
06079 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06080 return 0;
06081 }
06082
06083 ast_mutex_lock(&p->lock);
06084 p->exten[0] = '\0';
06085 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06086 dahdi_confmute(p, 0);
06087 restore_gains(p);
06088 p->ignoredtmf = 0;
06089 p->waitingfordt.tv_sec = 0;
06090
06091 res = analog_hangup(p->sig_pvt, ast);
06092 revert_fax_buffers(p, ast);
06093
06094 goto hangup_out;
06095 } else {
06096 p->cid_num[0] = '\0';
06097 p->cid_name[0] = '\0';
06098 p->cid_subaddr[0] = '\0';
06099 }
06100
06101 #if defined(HAVE_PRI)
06102 if (dahdi_sig_pri_lib_handles(p->sig)) {
06103 x = 1;
06104 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06105
06106 dahdi_confmute(p, 0);
06107 p->muting = 0;
06108 restore_gains(p);
06109 if (p->dsp) {
06110 ast_dsp_free(p->dsp);
06111 p->dsp = NULL;
06112 }
06113 p->ignoredtmf = 0;
06114
06115
06116 p->subs[SUB_REAL].owner = NULL;
06117 p->subs[SUB_REAL].needbusy = 0;
06118 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06119
06120 p->owner = NULL;
06121 p->cid_tag[0] = '\0';
06122 p->ringt = 0;
06123 p->distinctivering = 0;
06124 p->confirmanswer = 0;
06125 p->outgoing = 0;
06126 p->digital = 0;
06127 p->faxhandled = 0;
06128 p->pulsedial = 0;
06129
06130 revert_fax_buffers(p, ast);
06131
06132 p->law = p->law_default;
06133 law = p->law_default;
06134 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06135 if (res < 0) {
06136 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06137 p->channel, strerror(errno));
06138 }
06139
06140 sig_pri_hangup(p->sig_pvt, ast);
06141
06142 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06143 dahdi_disable_ec(p);
06144
06145 x = 0;
06146 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06147 p->didtdd = 0;
06148
06149 p->rdnis[0] = '\0';
06150 update_conf(p);
06151 reset_conf(p);
06152
06153
06154 x = 0;
06155 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06156
06157 if (num_restart_pending == 0) {
06158 restart_monitor();
06159 }
06160 goto hangup_out;
06161 }
06162 #endif
06163
06164 #if defined(HAVE_SS7)
06165 if (p->sig == SIG_SS7) {
06166 x = 1;
06167 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06168
06169 dahdi_confmute(p, 0);
06170 p->muting = 0;
06171 restore_gains(p);
06172 if (p->dsp) {
06173 ast_dsp_free(p->dsp);
06174 p->dsp = NULL;
06175 }
06176 p->ignoredtmf = 0;
06177
06178
06179 p->subs[SUB_REAL].owner = NULL;
06180 p->subs[SUB_REAL].needbusy = 0;
06181 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06182
06183 p->owner = NULL;
06184 p->ringt = 0;
06185 p->distinctivering = 0;
06186 p->confirmanswer = 0;
06187 p->outgoing = 0;
06188 p->digital = 0;
06189 p->faxhandled = 0;
06190 p->pulsedial = 0;
06191
06192 revert_fax_buffers(p, ast);
06193
06194 p->law = p->law_default;
06195 law = p->law_default;
06196 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06197 if (res < 0) {
06198 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06199 p->channel, strerror(errno));
06200 }
06201
06202 sig_ss7_hangup(p->sig_pvt, ast);
06203
06204 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06205 dahdi_disable_ec(p);
06206
06207 x = 0;
06208 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06209 p->didtdd = 0;
06210
06211 update_conf(p);
06212 reset_conf(p);
06213
06214
06215 x = 0;
06216 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06217
06218 if (num_restart_pending == 0) {
06219 restart_monitor();
06220 }
06221 goto hangup_out;
06222 }
06223 #endif
06224
06225 idx = dahdi_get_index(ast, p, 1);
06226
06227 dahdi_confmute(p, 0);
06228 p->muting = 0;
06229 restore_gains(p);
06230 if (p->origcid_num) {
06231 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06232 ast_free(p->origcid_num);
06233 p->origcid_num = NULL;
06234 }
06235 if (p->origcid_name) {
06236 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06237 ast_free(p->origcid_name);
06238 p->origcid_name = NULL;
06239 }
06240 if (p->dsp)
06241 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06242
06243 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06244 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06245 p->ignoredtmf = 0;
06246
06247 if (idx > -1) {
06248
06249 p->subs[idx].owner = NULL;
06250 p->subs[idx].needanswer = 0;
06251 p->subs[idx].needflash = 0;
06252 p->subs[idx].needringing = 0;
06253 p->subs[idx].needbusy = 0;
06254 p->subs[idx].needcongestion = 0;
06255 p->subs[idx].linear = 0;
06256 p->polarity = POLARITY_IDLE;
06257 dahdi_setlinear(p->subs[idx].dfd, 0);
06258 if (idx == SUB_REAL) {
06259 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06260 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06261 if (p->subs[SUB_CALLWAIT].inthreeway) {
06262
06263 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06264
06265 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06266 unalloc_sub(p, SUB_CALLWAIT);
06267 p->owner = NULL;
06268 } else {
06269
06270 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06271 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06272 unalloc_sub(p, SUB_THREEWAY);
06273 if (p->subs[SUB_REAL].inthreeway) {
06274
06275
06276 ast_debug(1, "Call was complete, setting owner to former third call\n");
06277 p->owner = p->subs[SUB_REAL].owner;
06278 } else {
06279
06280 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06281 p->owner = NULL;
06282 }
06283 p->subs[SUB_REAL].inthreeway = 0;
06284 }
06285 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06286
06287 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06288 unalloc_sub(p, SUB_CALLWAIT);
06289 p->owner = p->subs[SUB_REAL].owner;
06290 if (p->owner->_state != AST_STATE_UP)
06291 p->subs[SUB_REAL].needanswer = 1;
06292 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06293 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06294 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06295 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06296 unalloc_sub(p, SUB_THREEWAY);
06297 if (p->subs[SUB_REAL].inthreeway) {
06298
06299
06300 ast_debug(1, "Call was complete, setting owner to former third call\n");
06301 p->owner = p->subs[SUB_REAL].owner;
06302 } else {
06303
06304 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06305 p->owner = NULL;
06306 }
06307 p->subs[SUB_REAL].inthreeway = 0;
06308 }
06309 } else if (idx == SUB_CALLWAIT) {
06310
06311 if (p->subs[SUB_CALLWAIT].inthreeway) {
06312
06313
06314 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06315 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06316 S_OR(p->mohsuggest, NULL),
06317 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06318 }
06319 p->subs[SUB_THREEWAY].inthreeway = 0;
06320
06321 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06322 unalloc_sub(p, SUB_THREEWAY);
06323 } else
06324 unalloc_sub(p, SUB_CALLWAIT);
06325 } else if (idx == SUB_THREEWAY) {
06326 if (p->subs[SUB_CALLWAIT].inthreeway) {
06327
06328
06329 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06330 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06331 S_OR(p->mohsuggest, NULL),
06332 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06333 }
06334 p->subs[SUB_CALLWAIT].inthreeway = 0;
06335 }
06336 p->subs[SUB_REAL].inthreeway = 0;
06337
06338
06339 unalloc_sub(p, SUB_THREEWAY);
06340 } else {
06341
06342 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06343 }
06344 }
06345
06346 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06347 p->owner = NULL;
06348 p->ringt = 0;
06349 p->distinctivering = 0;
06350 p->confirmanswer = 0;
06351 p->outgoing = 0;
06352 p->digital = 0;
06353 p->faxhandled = 0;
06354 p->pulsedial = 0;
06355 if (p->dsp) {
06356 ast_dsp_free(p->dsp);
06357 p->dsp = NULL;
06358 }
06359
06360 revert_fax_buffers(p, ast);
06361
06362 p->law = p->law_default;
06363 law = p->law_default;
06364 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06365 if (res < 0)
06366 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06367
06368 #ifdef HAVE_OPENR2
06369 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06370 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06371
06372 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06373 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06374 } else {
06375 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06376 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06377 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06378 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06379 dahdi_r2_disconnect_call(p, r2cause);
06380 }
06381 } else if (p->mfcr2call) {
06382 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06383
06384
06385
06386
06387 p->mfcr2call = 0;
06388 }
06389 #endif
06390 switch (p->sig) {
06391 case SIG_SS7:
06392 case SIG_MFCR2:
06393 case SIG_PRI_LIB_HANDLE_CASES:
06394 case 0:
06395 break;
06396 default:
06397 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06398 break;
06399 }
06400 if (res < 0) {
06401 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06402 }
06403 switch (p->sig) {
06404 case SIG_FXOGS:
06405 case SIG_FXOLS:
06406 case SIG_FXOKS:
06407 memset(&par, 0, sizeof(par));
06408 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06409 if (!res) {
06410 struct analog_pvt *analog_p = p->sig_pvt;
06411 #if 0
06412 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06413 #endif
06414
06415 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06416 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06417 else
06418 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06419 analog_p->fxsoffhookstate = par.rxisoffhook;
06420 }
06421 break;
06422 case SIG_FXSGS:
06423 case SIG_FXSLS:
06424 case SIG_FXSKS:
06425
06426
06427 if (ast->_state != AST_STATE_RESERVED) {
06428 time(&p->guardtime);
06429 p->guardtime += 2;
06430 }
06431 break;
06432 default:
06433 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06434 break;
06435 }
06436 if (p->sig)
06437 dahdi_disable_ec(p);
06438 x = 0;
06439 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06440 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06441 p->didtdd = 0;
06442 p->callwaitcas = 0;
06443 p->callwaiting = p->permcallwaiting;
06444 p->hidecallerid = p->permhidecallerid;
06445 p->waitingfordt.tv_sec = 0;
06446 p->dialing = 0;
06447 p->rdnis[0] = '\0';
06448 update_conf(p);
06449 reset_conf(p);
06450
06451 switch (p->sig) {
06452 case SIG_PRI_LIB_HANDLE_CASES:
06453 case SIG_SS7:
06454 x = 0;
06455 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06456 break;
06457 default:
06458 break;
06459 }
06460 if (num_restart_pending == 0)
06461 restart_monitor();
06462 }
06463
06464 p->callwaitingrepeat = 0;
06465 p->cidcwexpire = 0;
06466 p->cid_suppress_expire = 0;
06467 p->oprmode = 0;
06468 hangup_out:
06469 ast->tech_pvt = NULL;
06470 ast_free(p->cidspill);
06471 p->cidspill = NULL;
06472
06473 ast_mutex_unlock(&p->lock);
06474 ast_verb(3, "Hungup '%s'\n", ast->name);
06475
06476 ast_mutex_lock(&iflock);
06477 if (p->restartpending) {
06478 num_restart_pending--;
06479 }
06480
06481 if (p->destroy) {
06482 destroy_channel(p, 0);
06483 }
06484 ast_mutex_unlock(&iflock);
06485
06486 ast_module_unref(ast_module_info->self);
06487 return 0;
06488 }
06489
06490 static int dahdi_answer(struct ast_channel *ast)
06491 {
06492 struct dahdi_pvt *p = ast->tech_pvt;
06493 int res = 0;
06494 int idx;
06495 ast_setstate(ast, AST_STATE_UP);
06496 ast_mutex_lock(&p->lock);
06497 idx = dahdi_get_index(ast, p, 0);
06498 if (idx < 0)
06499 idx = SUB_REAL;
06500
06501 if ((p->radio || (p->oprmode < 0))) {
06502 ast_mutex_unlock(&p->lock);
06503 return 0;
06504 }
06505
06506 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06507 res = analog_answer(p->sig_pvt, ast);
06508 ast_mutex_unlock(&p->lock);
06509 return res;
06510 }
06511
06512 switch (p->sig) {
06513 #if defined(HAVE_PRI)
06514 case SIG_PRI_LIB_HANDLE_CASES:
06515 res = sig_pri_answer(p->sig_pvt, ast);
06516 break;
06517 #endif
06518 #if defined(HAVE_SS7)
06519 case SIG_SS7:
06520 res = sig_ss7_answer(p->sig_pvt, ast);
06521 break;
06522 #endif
06523 #ifdef HAVE_OPENR2
06524 case SIG_MFCR2:
06525 if (!p->mfcr2_call_accepted) {
06526
06527
06528 p->mfcr2_answer_pending = 1;
06529 if (p->mfcr2_charge_calls) {
06530 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06531 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06532 } else {
06533 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06534 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06535 }
06536 } else {
06537 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06538 dahdi_r2_answer(p);
06539 }
06540 break;
06541 #endif
06542 case 0:
06543 ast_mutex_unlock(&p->lock);
06544 return 0;
06545 default:
06546 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06547 res = -1;
06548 break;
06549 }
06550 ast_mutex_unlock(&p->lock);
06551 return res;
06552 }
06553
06554 static void disable_dtmf_detect(struct dahdi_pvt *p)
06555 {
06556 int val = 0;
06557
06558 p->ignoredtmf = 1;
06559
06560 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06561
06562 if (!p->hardwaredtmf && p->dsp) {
06563 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06564 ast_dsp_set_features(p->dsp, p->dsp_features);
06565 }
06566 }
06567
06568 static void enable_dtmf_detect(struct dahdi_pvt *p)
06569 {
06570 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06571
06572 if (p->channel == CHAN_PSEUDO)
06573 return;
06574
06575 p->ignoredtmf = 0;
06576
06577 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06578
06579 if (!p->hardwaredtmf && p->dsp) {
06580 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06581 ast_dsp_set_features(p->dsp, p->dsp_features);
06582 }
06583 }
06584
06585 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06586 {
06587 char *cp;
06588 struct dahdi_pvt *p = chan->tech_pvt;
06589
06590
06591 if (!data || (*datalen < 1)) {
06592 errno = EINVAL;
06593 return -1;
06594 }
06595
06596 switch (option) {
06597 case AST_OPTION_DIGIT_DETECT:
06598 cp = (char *) data;
06599 *cp = p->ignoredtmf ? 0 : 1;
06600 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06601 break;
06602 case AST_OPTION_FAX_DETECT:
06603 cp = (char *) data;
06604 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06605 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06606 break;
06607 case AST_OPTION_CC_AGENT_TYPE:
06608 #if defined(HAVE_PRI)
06609 #if defined(HAVE_PRI_CCSS)
06610 if (dahdi_sig_pri_lib_handles(p->sig)) {
06611 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06612 break;
06613 }
06614 #endif
06615 #endif
06616 return -1;
06617 default:
06618 return -1;
06619 }
06620
06621 errno = 0;
06622
06623 return 0;
06624 }
06625
06626 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06627 {
06628 char *cp;
06629 signed char *scp;
06630 int x;
06631 int idx;
06632 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06633 struct oprmode *oprmode;
06634
06635
06636
06637 if (!data || (datalen < 1)) {
06638 errno = EINVAL;
06639 return -1;
06640 }
06641
06642 switch (option) {
06643 case AST_OPTION_TXGAIN:
06644 scp = (signed char *) data;
06645 idx = dahdi_get_index(chan, p, 0);
06646 if (idx < 0) {
06647 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06648 return -1;
06649 }
06650 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06651 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06652 case AST_OPTION_RXGAIN:
06653 scp = (signed char *) data;
06654 idx = dahdi_get_index(chan, p, 0);
06655 if (idx < 0) {
06656 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06657 return -1;
06658 }
06659 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06660 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06661 case AST_OPTION_TONE_VERIFY:
06662 if (!p->dsp)
06663 break;
06664 cp = (char *) data;
06665 switch (*cp) {
06666 case 1:
06667 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06668 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06669 break;
06670 case 2:
06671 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06672 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06673 break;
06674 default:
06675 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06676 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06677 break;
06678 }
06679 break;
06680 case AST_OPTION_TDD:
06681
06682 cp = (char *) data;
06683 p->mate = 0;
06684 if (!*cp) {
06685 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06686 if (p->tdd)
06687 tdd_free(p->tdd);
06688 p->tdd = 0;
06689 break;
06690 }
06691 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06692 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06693 dahdi_disable_ec(p);
06694
06695 if (!p->didtdd) {
06696 unsigned char mybuf[41000];
06697 unsigned char *buf;
06698 int size, res, fd, len;
06699 struct pollfd fds[1];
06700
06701 buf = mybuf;
06702 memset(buf, 0x7f, sizeof(mybuf));
06703 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06704 len = 40000;
06705 idx = dahdi_get_index(chan, p, 0);
06706 if (idx < 0) {
06707 ast_log(LOG_WARNING, "No index in TDD?\n");
06708 return -1;
06709 }
06710 fd = p->subs[idx].dfd;
06711 while (len) {
06712 if (ast_check_hangup(chan))
06713 return -1;
06714 size = len;
06715 if (size > READ_SIZE)
06716 size = READ_SIZE;
06717 fds[0].fd = fd;
06718 fds[0].events = POLLPRI | POLLOUT;
06719 fds[0].revents = 0;
06720 res = poll(fds, 1, -1);
06721 if (!res) {
06722 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06723 continue;
06724 }
06725
06726 if (fds[0].revents & POLLPRI)
06727 return -1;
06728 if (!(fds[0].revents & POLLOUT)) {
06729 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06730 continue;
06731 }
06732 res = write(fd, buf, size);
06733 if (res != size) {
06734 if (res == -1) return -1;
06735 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06736 break;
06737 }
06738 len -= size;
06739 buf += size;
06740 }
06741 p->didtdd = 1;
06742 }
06743 if (*cp == 2) {
06744 if (p->tdd)
06745 tdd_free(p->tdd);
06746 p->tdd = 0;
06747 p->mate = 1;
06748 break;
06749 }
06750 if (!p->tdd) {
06751 p->tdd = tdd_new();
06752 }
06753 break;
06754 case AST_OPTION_RELAXDTMF:
06755 if (!p->dsp)
06756 break;
06757 cp = (char *) data;
06758 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06759 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06760 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06761 break;
06762 case AST_OPTION_AUDIO_MODE:
06763 #if defined(HAVE_PRI)
06764 if (dahdi_sig_pri_lib_handles(p->sig)
06765 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06766
06767 break;
06768 }
06769 #endif
06770
06771 cp = (char *) data;
06772 if (!*cp) {
06773 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06774 x = 0;
06775 dahdi_disable_ec(p);
06776 } else {
06777 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06778 x = 1;
06779 }
06780 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06781 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06782 break;
06783 case AST_OPTION_OPRMODE:
06784 oprmode = (struct oprmode *) data;
06785
06786 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06787 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06788 chan->tech->type, oprmode->peer->tech->type);
06789 errno = EINVAL;
06790 return -1;
06791 }
06792 pp = oprmode->peer->tech_pvt;
06793 p->oprmode = pp->oprmode = 0;
06794
06795 p->oprpeer = pp;
06796 pp->oprpeer = p;
06797
06798 if (oprmode->mode)
06799 {
06800 pp->oprmode = oprmode->mode;
06801 p->oprmode = -oprmode->mode;
06802 }
06803 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06804 oprmode->mode, chan->name,oprmode->peer->name);
06805 break;
06806 case AST_OPTION_ECHOCAN:
06807 cp = (char *) data;
06808 if (*cp) {
06809 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06810 dahdi_enable_ec(p);
06811 } else {
06812 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06813 dahdi_disable_ec(p);
06814 }
06815 break;
06816 case AST_OPTION_DIGIT_DETECT:
06817 cp = (char *) data;
06818 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06819 if (*cp) {
06820 enable_dtmf_detect(p);
06821 } else {
06822 disable_dtmf_detect(p);
06823 }
06824 break;
06825 case AST_OPTION_FAX_DETECT:
06826 cp = (char *) data;
06827 if (p->dsp) {
06828 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06829 if (*cp) {
06830 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06831 } else {
06832 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06833 }
06834 ast_dsp_set_features(p->dsp, p->dsp_features);
06835 }
06836 break;
06837 default:
06838 return -1;
06839 }
06840 errno = 0;
06841
06842 return 0;
06843 }
06844
06845 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06846 {
06847 struct dahdi_pvt *p = chan->tech_pvt;
06848 int res = 0;
06849
06850 if (!strcasecmp(data, "rxgain")) {
06851 ast_mutex_lock(&p->lock);
06852 snprintf(buf, len, "%f", p->rxgain);
06853 ast_mutex_unlock(&p->lock);
06854 } else if (!strcasecmp(data, "txgain")) {
06855 ast_mutex_lock(&p->lock);
06856 snprintf(buf, len, "%f", p->txgain);
06857 ast_mutex_unlock(&p->lock);
06858 } else if (!strcasecmp(data, "dahdi_channel")) {
06859 ast_mutex_lock(&p->lock);
06860 snprintf(buf, len, "%d", p->channel);
06861 ast_mutex_unlock(&p->lock);
06862 } else if (!strcasecmp(data, "dahdi_span")) {
06863 ast_mutex_lock(&p->lock);
06864 snprintf(buf, len, "%d", p->span);
06865 ast_mutex_unlock(&p->lock);
06866 } else if (!strcasecmp(data, "dahdi_type")) {
06867 ast_mutex_lock(&p->lock);
06868 switch (p->sig) {
06869 #if defined(HAVE_OPENR2)
06870 case SIG_MFCR2:
06871 ast_copy_string(buf, "mfc/r2", len);
06872 break;
06873 #endif
06874 #if defined(HAVE_PRI)
06875 case SIG_PRI_LIB_HANDLE_CASES:
06876 ast_copy_string(buf, "pri", len);
06877 break;
06878 #endif
06879 case 0:
06880 ast_copy_string(buf, "pseudo", len);
06881 break;
06882 #if defined(HAVE_SS7)
06883 case SIG_SS7:
06884 ast_copy_string(buf, "ss7", len);
06885 break;
06886 #endif
06887 default:
06888
06889 ast_copy_string(buf, "analog", len);
06890 break;
06891 }
06892 ast_mutex_unlock(&p->lock);
06893 #if defined(HAVE_PRI)
06894 #if defined(HAVE_PRI_REVERSE_CHARGE)
06895 } else if (!strcasecmp(data, "reversecharge")) {
06896 ast_mutex_lock(&p->lock);
06897 switch (p->sig) {
06898 case SIG_PRI_LIB_HANDLE_CASES:
06899 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06900 break;
06901 default:
06902 *buf = '\0';
06903 res = -1;
06904 break;
06905 }
06906 ast_mutex_unlock(&p->lock);
06907 #endif
06908 #if defined(HAVE_PRI_SETUP_KEYPAD)
06909 } else if (!strcasecmp(data, "keypad_digits")) {
06910 ast_mutex_lock(&p->lock);
06911 switch (p->sig) {
06912 case SIG_PRI_LIB_HANDLE_CASES:
06913 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06914 len);
06915 break;
06916 default:
06917 *buf = '\0';
06918 res = -1;
06919 break;
06920 }
06921 ast_mutex_unlock(&p->lock);
06922 #endif
06923 } else if (!strcasecmp(data, "no_media_path")) {
06924 ast_mutex_lock(&p->lock);
06925 switch (p->sig) {
06926 case SIG_PRI_LIB_HANDLE_CASES:
06927
06928
06929
06930
06931 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06932 break;
06933 default:
06934 *buf = '\0';
06935 res = -1;
06936 break;
06937 }
06938 ast_mutex_unlock(&p->lock);
06939 #endif
06940 } else {
06941 *buf = '\0';
06942 res = -1;
06943 }
06944
06945 return res;
06946 }
06947
06948
06949 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06950 {
06951 int res;
06952 char policy_str[21] = "";
06953
06954 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06955 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06956 return 1;
06957 }
06958 if (*num_buffers < 0) {
06959 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06960 return -1;
06961 }
06962 if (!strcasecmp(policy_str, "full")) {
06963 *policy = DAHDI_POLICY_WHEN_FULL;
06964 } else if (!strcasecmp(policy_str, "immediate")) {
06965 *policy = DAHDI_POLICY_IMMEDIATE;
06966 #if defined(HAVE_DAHDI_HALF_FULL)
06967 } else if (!strcasecmp(policy_str, "half")) {
06968 *policy = DAHDI_POLICY_HALF_FULL;
06969 #endif
06970 } else {
06971 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06972 return -1;
06973 }
06974
06975 return 0;
06976 }
06977
06978 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06979 {
06980 struct dahdi_pvt *p = chan->tech_pvt;
06981 int res = 0;
06982
06983 if (!strcasecmp(data, "buffers")) {
06984 int num_bufs, policy;
06985
06986 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06987 struct dahdi_bufferinfo bi = {
06988 .txbufpolicy = policy,
06989 .rxbufpolicy = policy,
06990 .bufsize = p->bufsize,
06991 .numbufs = num_bufs,
06992 };
06993 int bpres;
06994
06995 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06996 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06997 } else {
06998 p->bufferoverrideinuse = 1;
06999 }
07000 } else {
07001 res = -1;
07002 }
07003 } else if (!strcasecmp(data, "echocan_mode")) {
07004 if (!strcasecmp(value, "on")) {
07005 ast_mutex_lock(&p->lock);
07006 dahdi_enable_ec(p);
07007 ast_mutex_unlock(&p->lock);
07008 } else if (!strcasecmp(value, "off")) {
07009 ast_mutex_lock(&p->lock);
07010 dahdi_disable_ec(p);
07011 ast_mutex_unlock(&p->lock);
07012 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07013 } else if (!strcasecmp(value, "fax")) {
07014 int blah = 1;
07015
07016 ast_mutex_lock(&p->lock);
07017 if (!p->echocanon) {
07018 dahdi_enable_ec(p);
07019 }
07020 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07021 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07022 }
07023 ast_mutex_unlock(&p->lock);
07024 } else if (!strcasecmp(value, "voice")) {
07025 int blah = 0;
07026
07027 ast_mutex_lock(&p->lock);
07028 if (!p->echocanon) {
07029 dahdi_enable_ec(p);
07030 }
07031 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07032 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07033 }
07034 ast_mutex_unlock(&p->lock);
07035 #endif
07036 } else {
07037 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07038 res = -1;
07039 }
07040 } else {
07041 res = -1;
07042 }
07043
07044 return res;
07045 }
07046
07047 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07048 {
07049
07050 int x;
07051 int hasslaves;
07052 if (!master)
07053 return;
07054 if (needlock) {
07055 ast_mutex_lock(&master->lock);
07056 if (slave) {
07057 while (ast_mutex_trylock(&slave->lock)) {
07058 DEADLOCK_AVOIDANCE(&master->lock);
07059 }
07060 }
07061 }
07062 hasslaves = 0;
07063 for (x = 0; x < MAX_SLAVES; x++) {
07064 if (master->slaves[x]) {
07065 if (!slave || (master->slaves[x] == slave)) {
07066
07067 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07068 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07069 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07070 master->slaves[x]->master = NULL;
07071 master->slaves[x] = NULL;
07072 } else
07073 hasslaves = 1;
07074 }
07075 if (!hasslaves)
07076 master->inconference = 0;
07077 }
07078 if (!slave) {
07079 if (master->master) {
07080
07081 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07082 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07083 hasslaves = 0;
07084 for (x = 0; x < MAX_SLAVES; x++) {
07085 if (master->master->slaves[x] == master)
07086 master->master->slaves[x] = NULL;
07087 else if (master->master->slaves[x])
07088 hasslaves = 1;
07089 }
07090 if (!hasslaves)
07091 master->master->inconference = 0;
07092 }
07093 master->master = NULL;
07094 }
07095 update_conf(master);
07096 if (needlock) {
07097 if (slave)
07098 ast_mutex_unlock(&slave->lock);
07099 ast_mutex_unlock(&master->lock);
07100 }
07101 }
07102
07103 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07104 int x;
07105 if (!slave || !master) {
07106 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07107 return;
07108 }
07109 for (x = 0; x < MAX_SLAVES; x++) {
07110 if (!master->slaves[x]) {
07111 master->slaves[x] = slave;
07112 break;
07113 }
07114 }
07115 if (x >= MAX_SLAVES) {
07116 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07117 master->slaves[MAX_SLAVES - 1] = slave;
07118 }
07119 if (slave->master)
07120 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07121 slave->master = master;
07122
07123 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07124 }
07125
07126 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)
07127 {
07128 struct ast_channel *who;
07129 struct dahdi_pvt *p0, *p1, *op0, *op1;
07130 struct dahdi_pvt *master = NULL, *slave = NULL;
07131 struct ast_frame *f;
07132 int inconf = 0;
07133 int nothingok = 1;
07134 int ofd0, ofd1;
07135 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07136 int os0 = -1, os1 = -1;
07137 int priority = 0;
07138 struct ast_channel *oc0, *oc1;
07139 enum ast_bridge_result res;
07140 #ifdef PRI_2BCT
07141 int triedtopribridge = 0;
07142 q931_call *q931c0;
07143 q931_call *q931c1;
07144 #endif
07145
07146
07147
07148
07149
07150
07151 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07152 return AST_BRIDGE_FAILED_NOWARN;
07153
07154 ast_channel_lock(c0);
07155 while (ast_channel_trylock(c1)) {
07156 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07157 }
07158
07159 p0 = c0->tech_pvt;
07160 p1 = c1->tech_pvt;
07161
07162 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07163 ast_channel_unlock(c0);
07164 ast_channel_unlock(c1);
07165 return AST_BRIDGE_FAILED_NOWARN;
07166 }
07167
07168 oi0 = dahdi_get_index(c0, p0, 0);
07169 oi1 = dahdi_get_index(c1, p1, 0);
07170 if ((oi0 < 0) || (oi1 < 0)) {
07171 ast_channel_unlock(c0);
07172 ast_channel_unlock(c1);
07173 return AST_BRIDGE_FAILED;
07174 }
07175
07176 op0 = p0 = c0->tech_pvt;
07177 op1 = p1 = c1->tech_pvt;
07178 ofd0 = c0->fds[0];
07179 ofd1 = c1->fds[0];
07180 oc0 = p0->owner;
07181 oc1 = p1->owner;
07182
07183 if (ast_mutex_trylock(&p0->lock)) {
07184
07185 ast_channel_unlock(c0);
07186 ast_channel_unlock(c1);
07187 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07188 return AST_BRIDGE_RETRY;
07189 }
07190 if (ast_mutex_trylock(&p1->lock)) {
07191
07192 ast_mutex_unlock(&p0->lock);
07193 ast_channel_unlock(c0);
07194 ast_channel_unlock(c1);
07195 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07196 return AST_BRIDGE_RETRY;
07197 }
07198
07199 if ((p0->callwaiting && p0->callwaitingcallerid)
07200 || (p1->callwaiting && p1->callwaitingcallerid)) {
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210 ast_mutex_unlock(&p0->lock);
07211 ast_mutex_unlock(&p1->lock);
07212 ast_channel_unlock(c0);
07213 ast_channel_unlock(c1);
07214 return AST_BRIDGE_FAILED_NOWARN;
07215 }
07216
07217 #if defined(HAVE_PRI)
07218 if ((dahdi_sig_pri_lib_handles(p0->sig)
07219 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07220 || (dahdi_sig_pri_lib_handles(p1->sig)
07221 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07222
07223
07224
07225
07226 ast_mutex_unlock(&p0->lock);
07227 ast_mutex_unlock(&p1->lock);
07228 ast_channel_unlock(c0);
07229 ast_channel_unlock(c1);
07230 return AST_BRIDGE_FAILED_NOWARN;
07231 }
07232 #endif
07233
07234 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07235 if (p0->owner && p1->owner) {
07236
07237 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07238 master = p0;
07239 slave = p1;
07240 inconf = 1;
07241 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07242 master = p1;
07243 slave = p0;
07244 inconf = 1;
07245 } else {
07246 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07247 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07248 p0->channel,
07249 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07250 p0->subs[SUB_REAL].inthreeway, p0->channel,
07251 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07252 p1->subs[SUB_REAL].inthreeway);
07253 }
07254 nothingok = 0;
07255 }
07256 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07257 if (p1->subs[SUB_THREEWAY].inthreeway) {
07258 master = p1;
07259 slave = p0;
07260 nothingok = 0;
07261 }
07262 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07263 if (p0->subs[SUB_THREEWAY].inthreeway) {
07264 master = p0;
07265 slave = p1;
07266 nothingok = 0;
07267 }
07268 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07269
07270
07271 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07272 master = p1;
07273 slave = p0;
07274 nothingok = 0;
07275 }
07276 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07277
07278 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07279 master = p0;
07280 slave = p1;
07281 nothingok = 0;
07282 }
07283 }
07284 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07285 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07286 if (master && slave) {
07287
07288
07289
07290 if ((oi1 == SUB_THREEWAY) &&
07291 p1->subs[SUB_THREEWAY].inthreeway &&
07292 p1->subs[SUB_REAL].owner &&
07293 p1->subs[SUB_REAL].inthreeway &&
07294 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07295 ast_debug(1,
07296 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07297 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07298 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07299 os1 = p1->subs[SUB_REAL].owner->_state;
07300 } else {
07301 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07302 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07303 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07304 }
07305 if ((oi0 == SUB_THREEWAY) &&
07306 p0->subs[SUB_THREEWAY].inthreeway &&
07307 p0->subs[SUB_REAL].owner &&
07308 p0->subs[SUB_REAL].inthreeway &&
07309 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07310 ast_debug(1,
07311 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07312 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07313 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07314 os0 = p0->subs[SUB_REAL].owner->_state;
07315 } else {
07316 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07317 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07318 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07319 }
07320 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07321 if (!p0->echocanbridged || !p1->echocanbridged) {
07322
07323 dahdi_disable_ec(p0);
07324 dahdi_disable_ec(p1);
07325 }
07326 }
07327 dahdi_link(slave, master);
07328 master->inconference = inconf;
07329 } else if (!nothingok)
07330 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07331
07332 update_conf(p0);
07333 update_conf(p1);
07334 t0 = p0->subs[SUB_REAL].inthreeway;
07335 t1 = p1->subs[SUB_REAL].inthreeway;
07336
07337 ast_mutex_unlock(&p0->lock);
07338 ast_mutex_unlock(&p1->lock);
07339
07340 ast_channel_unlock(c0);
07341 ast_channel_unlock(c1);
07342
07343
07344 if ((!master || !slave) && !nothingok) {
07345 dahdi_enable_ec(p0);
07346 dahdi_enable_ec(p1);
07347 return AST_BRIDGE_FAILED;
07348 }
07349
07350 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07351
07352 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07353 disable_dtmf_detect(op0);
07354
07355 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07356 disable_dtmf_detect(op1);
07357
07358 for (;;) {
07359 struct ast_channel *c0_priority[2] = {c0, c1};
07360 struct ast_channel *c1_priority[2] = {c1, c0};
07361
07362
07363
07364
07365 ast_channel_lock(c0);
07366 while (ast_channel_trylock(c1)) {
07367 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07368 }
07369
07370 p0 = c0->tech_pvt;
07371 p1 = c1->tech_pvt;
07372
07373 if (op0 == p0)
07374 i0 = dahdi_get_index(c0, p0, 1);
07375 if (op1 == p1)
07376 i1 = dahdi_get_index(c1, p1, 1);
07377
07378 ast_channel_unlock(c0);
07379 ast_channel_unlock(c1);
07380
07381 if (!timeoutms ||
07382 (op0 != p0) ||
07383 (op1 != p1) ||
07384 (ofd0 != c0->fds[0]) ||
07385 (ofd1 != c1->fds[0]) ||
07386 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07387 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07388 (oc0 != p0->owner) ||
07389 (oc1 != p1->owner) ||
07390 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07391 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07392 (oi0 != i0) ||
07393 (oi1 != i1)) {
07394 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07395 op0->channel, oi0, op1->channel, oi1);
07396 res = AST_BRIDGE_RETRY;
07397 goto return_from_bridge;
07398 }
07399
07400 #ifdef PRI_2BCT
07401 if (!triedtopribridge) {
07402 triedtopribridge = 1;
07403 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07404 ast_mutex_lock(&p0->pri->lock);
07405 switch (p0->sig) {
07406 case SIG_PRI_LIB_HANDLE_CASES:
07407 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07408 break;
07409 default:
07410 q931c0 = NULL;
07411 break;
07412 }
07413 switch (p1->sig) {
07414 case SIG_PRI_LIB_HANDLE_CASES:
07415 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07416 break;
07417 default:
07418 q931c1 = NULL;
07419 break;
07420 }
07421 if (q931c0 && q931c1) {
07422 pri_channel_bridge(q931c0, q931c1);
07423 }
07424 ast_mutex_unlock(&p0->pri->lock);
07425 }
07426 }
07427 #endif
07428
07429 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07430 if (!who) {
07431 ast_debug(1, "Ooh, empty read...\n");
07432 continue;
07433 }
07434 f = ast_read(who);
07435 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07436 *fo = f;
07437 *rc = who;
07438 res = AST_BRIDGE_COMPLETE;
07439 goto return_from_bridge;
07440 }
07441 if (f->frametype == AST_FRAME_DTMF) {
07442 if ((who == c0) && p0->pulsedial) {
07443 ast_write(c1, f);
07444 } else if ((who == c1) && p1->pulsedial) {
07445 ast_write(c0, f);
07446 } else {
07447 *fo = f;
07448 *rc = who;
07449 res = AST_BRIDGE_COMPLETE;
07450 goto return_from_bridge;
07451 }
07452 }
07453 ast_frfree(f);
07454
07455
07456 priority = !priority;
07457 }
07458
07459 return_from_bridge:
07460 if (op0 == p0)
07461 dahdi_enable_ec(p0);
07462
07463 if (op1 == p1)
07464 dahdi_enable_ec(p1);
07465
07466 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07467 enable_dtmf_detect(op0);
07468
07469 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07470 enable_dtmf_detect(op1);
07471
07472 dahdi_unlink(slave, master, 1);
07473
07474 return res;
07475 }
07476
07477 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07478 {
07479 struct dahdi_pvt *p = newchan->tech_pvt;
07480 int x;
07481
07482 ast_mutex_lock(&p->lock);
07483
07484 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07485 if (p->owner == oldchan) {
07486 p->owner = newchan;
07487 }
07488 for (x = 0; x < 3; x++) {
07489 if (p->subs[x].owner == oldchan) {
07490 if (!x) {
07491 dahdi_unlink(NULL, p, 0);
07492 }
07493 p->subs[x].owner = newchan;
07494 }
07495 }
07496 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07497 analog_fixup(oldchan, newchan, p->sig_pvt);
07498 #if defined(HAVE_PRI)
07499 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07500 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07501 #endif
07502 #if defined(HAVE_SS7)
07503 } else if (p->sig == SIG_SS7) {
07504 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07505 #endif
07506 }
07507 update_conf(p);
07508
07509 ast_mutex_unlock(&p->lock);
07510
07511 if (newchan->_state == AST_STATE_RINGING) {
07512 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07513 }
07514 return 0;
07515 }
07516
07517 static int dahdi_ring_phone(struct dahdi_pvt *p)
07518 {
07519 int x;
07520 int res;
07521
07522 x = 0;
07523 x = DAHDI_ONHOOK;
07524 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07525 do {
07526 x = DAHDI_RING;
07527 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07528 if (res) {
07529 switch (errno) {
07530 case EBUSY:
07531 case EINTR:
07532
07533 usleep(10000);
07534 continue;
07535 case EINPROGRESS:
07536 res = 0;
07537 break;
07538 default:
07539 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07540 res = 0;
07541 }
07542 }
07543 } while (res);
07544 return res;
07545 }
07546
07547 static void *analog_ss_thread(void *data);
07548
07549 static int attempt_transfer(struct dahdi_pvt *p)
07550 {
07551
07552
07553
07554 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07555
07556
07557 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07558 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07559 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07560 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07561 }
07562 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07563 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07564 }
07565 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07566 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07567 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07568 return -1;
07569 }
07570
07571 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07572 unalloc_sub(p, SUB_THREEWAY);
07573 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07574 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07575 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07576 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07577 }
07578 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07579 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07580 }
07581 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07582 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07583 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07584 return -1;
07585 }
07586
07587 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07588 ast_channel_unlock(p->subs[SUB_REAL].owner);
07589 unalloc_sub(p, SUB_THREEWAY);
07590
07591 return 1;
07592 } else {
07593 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07594 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07595 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07596 return -1;
07597 }
07598 return 0;
07599 }
07600
07601 static int check_for_conference(struct dahdi_pvt *p)
07602 {
07603 struct dahdi_confinfo ci;
07604
07605 if (p->master || (p->confno > -1))
07606 return 0;
07607 memset(&ci, 0, sizeof(ci));
07608 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07609 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07610 return 0;
07611 }
07612
07613
07614
07615 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07616 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07617 return 1;
07618 }
07619 return 0;
07620 }
07621
07622
07623
07624
07625
07626
07627 static int get_alarms(struct dahdi_pvt *p)
07628 {
07629 int res;
07630 struct dahdi_spaninfo zi;
07631 struct dahdi_params params;
07632
07633 memset(&zi, 0, sizeof(zi));
07634 zi.spanno = p->span;
07635
07636 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07637 if (zi.alarms != DAHDI_ALARM_NONE)
07638 return zi.alarms;
07639 } else {
07640 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07641 return 0;
07642 }
07643
07644
07645 memset(¶ms, 0, sizeof(params));
07646 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07647 return params.chan_alarms;
07648
07649 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07650
07651 return DAHDI_ALARM_NONE;
07652 }
07653
07654 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07655 {
07656 struct dahdi_pvt *p = ast->tech_pvt;
07657 struct ast_frame *f = *dest;
07658
07659 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07660 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07661 f->subclass.integer, f->subclass.integer, ast->name);
07662
07663 if (p->confirmanswer) {
07664 if (f->frametype == AST_FRAME_DTMF_END) {
07665 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07666
07667
07668 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07669 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07670
07671 p->confirmanswer = 0;
07672 } else {
07673 p->subs[idx].f.frametype = AST_FRAME_NULL;
07674 p->subs[idx].f.subclass.integer = 0;
07675 }
07676 *dest = &p->subs[idx].f;
07677 } else if (p->callwaitcas) {
07678 if (f->frametype == AST_FRAME_DTMF_END) {
07679 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07680 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07681 ast_free(p->cidspill);
07682 p->cidspill = NULL;
07683 send_cwcidspill(p);
07684 }
07685 p->callwaitcas = 0;
07686 }
07687 p->subs[idx].f.frametype = AST_FRAME_NULL;
07688 p->subs[idx].f.subclass.integer = 0;
07689 *dest = &p->subs[idx].f;
07690 } else if (f->subclass.integer == 'f') {
07691 if (f->frametype == AST_FRAME_DTMF_END) {
07692
07693 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07694
07695 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07696 struct dahdi_bufferinfo bi = {
07697 .txbufpolicy = p->faxbuf_policy,
07698 .bufsize = p->bufsize,
07699 .numbufs = p->faxbuf_no
07700 };
07701 int res;
07702
07703 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07704 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07705 } else {
07706 p->bufferoverrideinuse = 1;
07707 }
07708 }
07709 p->faxhandled = 1;
07710 if (p->dsp) {
07711 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07712 ast_dsp_set_features(p->dsp, p->dsp_features);
07713 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07714 }
07715 if (strcmp(ast->exten, "fax")) {
07716 const char *target_context = S_OR(ast->macrocontext, ast->context);
07717
07718
07719
07720
07721
07722 ast_mutex_unlock(&p->lock);
07723 ast_channel_unlock(ast);
07724 if (ast_exists_extension(ast, target_context, "fax", 1,
07725 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07726 ast_channel_lock(ast);
07727 ast_mutex_lock(&p->lock);
07728 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07729
07730 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07731 if (ast_async_goto(ast, target_context, "fax", 1))
07732 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07733 } else {
07734 ast_channel_lock(ast);
07735 ast_mutex_lock(&p->lock);
07736 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07737 }
07738 } else {
07739 ast_debug(1, "Already in a fax extension, not redirecting\n");
07740 }
07741 } else {
07742 ast_debug(1, "Fax already handled\n");
07743 }
07744 dahdi_confmute(p, 0);
07745 }
07746 p->subs[idx].f.frametype = AST_FRAME_NULL;
07747 p->subs[idx].f.subclass.integer = 0;
07748 *dest = &p->subs[idx].f;
07749 }
07750 }
07751
07752 static void handle_alarms(struct dahdi_pvt *p, int alms)
07753 {
07754 const char *alarm_str = alarm2str(alms);
07755
07756 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07757 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07758 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07759 "Alarm: %s\r\n"
07760 "Channel: %d\r\n",
07761 alarm_str, p->channel);
07762 }
07763
07764 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07765 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07766 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07767 "Alarm: %s\r\n"
07768 "Span: %d\r\n",
07769 alarm_str, p->span);
07770 }
07771 }
07772
07773 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07774 {
07775 int res, x;
07776 int idx, mysig;
07777 char *c;
07778 struct dahdi_pvt *p = ast->tech_pvt;
07779 pthread_t threadid;
07780 struct ast_channel *chan;
07781 struct ast_frame *f;
07782
07783 idx = dahdi_get_index(ast, p, 0);
07784 mysig = p->sig;
07785 if (p->outsigmod > -1)
07786 mysig = p->outsigmod;
07787 p->subs[idx].f.frametype = AST_FRAME_NULL;
07788 p->subs[idx].f.subclass.integer = 0;
07789 p->subs[idx].f.datalen = 0;
07790 p->subs[idx].f.samples = 0;
07791 p->subs[idx].f.mallocd = 0;
07792 p->subs[idx].f.offset = 0;
07793 p->subs[idx].f.src = "dahdi_handle_event";
07794 p->subs[idx].f.data.ptr = NULL;
07795 f = &p->subs[idx].f;
07796
07797 if (idx < 0)
07798 return &p->subs[idx].f;
07799 if (p->fake_event) {
07800 res = p->fake_event;
07801 p->fake_event = 0;
07802 } else
07803 res = dahdi_get_event(p->subs[idx].dfd);
07804
07805 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07806
07807 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07808 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07809 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07810 #if defined(HAVE_PRI)
07811 if (dahdi_sig_pri_lib_handles(p->sig)
07812 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07813 && p->pri
07814 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07815
07816 } else
07817 #endif
07818 {
07819
07820 dahdi_confmute(p, 0);
07821 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07822 p->subs[idx].f.subclass.integer = res & 0xff;
07823 dahdi_handle_dtmf(ast, idx, &f);
07824 }
07825 return f;
07826 }
07827
07828 if (res & DAHDI_EVENT_DTMFDOWN) {
07829 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07830 #if defined(HAVE_PRI)
07831 if (dahdi_sig_pri_lib_handles(p->sig)
07832 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07833 && p->pri
07834 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07835
07836 } else
07837 #endif
07838 {
07839
07840 dahdi_confmute(p, 1);
07841 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07842 p->subs[idx].f.subclass.integer = res & 0xff;
07843 dahdi_handle_dtmf(ast, idx, &f);
07844 }
07845 return &p->subs[idx].f;
07846 }
07847
07848 switch (res) {
07849 case DAHDI_EVENT_EC_DISABLED:
07850 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07851 p->echocanon = 0;
07852 break;
07853 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07854 case DAHDI_EVENT_TX_CED_DETECTED:
07855 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07856 break;
07857 case DAHDI_EVENT_RX_CED_DETECTED:
07858 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07859 break;
07860 case DAHDI_EVENT_EC_NLP_DISABLED:
07861 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07862 break;
07863 case DAHDI_EVENT_EC_NLP_ENABLED:
07864 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07865 break;
07866 #endif
07867 case DAHDI_EVENT_BITSCHANGED:
07868 #ifdef HAVE_OPENR2
07869 if (p->sig != SIG_MFCR2) {
07870 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07871 } else {
07872 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07873 openr2_chan_handle_cas(p->r2chan);
07874 }
07875 #else
07876 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07877 #endif
07878 case DAHDI_EVENT_PULSE_START:
07879
07880 if (!ast->pbx)
07881 tone_zone_play_tone(p->subs[idx].dfd, -1);
07882 break;
07883 case DAHDI_EVENT_DIALCOMPLETE:
07884 #ifdef HAVE_OPENR2
07885 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07886
07887
07888 break;
07889 }
07890 #endif
07891 if (p->inalarm) break;
07892 if ((p->radio || (p->oprmode < 0))) break;
07893 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07894 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07895 return NULL;
07896 }
07897 if (!x) {
07898 dahdi_enable_ec(p);
07899 if (p->echobreak) {
07900 dahdi_train_ec(p);
07901 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07902 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07903 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07904 p->echobreak = 0;
07905 } else {
07906 p->dialing = 0;
07907 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07908
07909 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07910 ast_setstate(ast, AST_STATE_UP);
07911 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07912 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07913 break;
07914 } else {
07915
07916 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07917 }
07918 }
07919 if (ast->_state == AST_STATE_DIALING) {
07920 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07921 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07922 } else if (p->confirmanswer || (!p->dialednone
07923 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07924 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07925 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07926 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07927 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07928 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07929 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07930 || (mysig == SIG_SF_FEATB)))) {
07931 ast_setstate(ast, AST_STATE_RINGING);
07932 } else if (!p->answeronpolarityswitch) {
07933 ast_setstate(ast, AST_STATE_UP);
07934 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07935 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07936
07937 p->polarity = POLARITY_REV;
07938 } else {
07939
07940 p->polarity = POLARITY_IDLE;
07941 }
07942 }
07943 }
07944 }
07945 break;
07946 case DAHDI_EVENT_ALARM:
07947 switch (p->sig) {
07948 #if defined(HAVE_PRI)
07949 case SIG_PRI_LIB_HANDLE_CASES:
07950 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07951 break;
07952 #endif
07953 #if defined(HAVE_SS7)
07954 case SIG_SS7:
07955 sig_ss7_set_alarm(p->sig_pvt, 1);
07956 break;
07957 #endif
07958 default:
07959 p->inalarm = 1;
07960 break;
07961 }
07962 res = get_alarms(p);
07963 handle_alarms(p, res);
07964 #ifdef HAVE_PRI
07965 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07966
07967 } else {
07968 break;
07969 }
07970 #endif
07971 #if defined(HAVE_SS7)
07972 if (p->sig == SIG_SS7)
07973 break;
07974 #endif
07975 #ifdef HAVE_OPENR2
07976 if (p->sig == SIG_MFCR2)
07977 break;
07978 #endif
07979 case DAHDI_EVENT_ONHOOK:
07980 if (p->radio) {
07981 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07982 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07983 break;
07984 }
07985 if (p->oprmode < 0)
07986 {
07987 if (p->oprmode != -1) break;
07988 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07989 {
07990
07991 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07992 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07993 save_conference(p->oprpeer);
07994 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07995 }
07996 break;
07997 }
07998 switch (p->sig) {
07999 case SIG_FXOLS:
08000 case SIG_FXOGS:
08001 case SIG_FXOKS:
08002
08003 if (idx == SUB_REAL) {
08004
08005 if (p->subs[SUB_CALLWAIT].owner) {
08006
08007 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08008 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08009 unalloc_sub(p, SUB_CALLWAIT);
08010 #if 0
08011 p->subs[idx].needanswer = 0;
08012 p->subs[idx].needringing = 0;
08013 #endif
08014 p->callwaitingrepeat = 0;
08015 p->cidcwexpire = 0;
08016 p->cid_suppress_expire = 0;
08017 p->owner = NULL;
08018
08019 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08020 p->dialing = 1;
08021 dahdi_ring_phone(p);
08022 } else if (p->subs[SUB_THREEWAY].owner) {
08023 unsigned int mssinceflash;
08024
08025
08026 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08027
08028 DLA_UNLOCK(&p->lock);
08029 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08030
08031
08032
08033 DLA_LOCK(&p->lock);
08034 if (p->owner != ast) {
08035 ast_log(LOG_WARNING, "This isn't good...\n");
08036 return NULL;
08037 }
08038 }
08039 if (!p->subs[SUB_THREEWAY].owner) {
08040 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08041 return NULL;
08042 }
08043 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08044 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08045 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08046
08047
08048 if (p->subs[SUB_THREEWAY].owner)
08049 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08050 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08051 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08052 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08053 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08054 if (p->transfer) {
08055
08056 p->subs[SUB_REAL].inthreeway = 0;
08057 p->subs[SUB_THREEWAY].inthreeway = 0;
08058
08059 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08060 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08061
08062 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08063 p->owner = NULL;
08064
08065 dahdi_ring_phone(p);
08066 } else {
08067 if ((res = attempt_transfer(p)) < 0) {
08068 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08069 if (p->subs[SUB_THREEWAY].owner)
08070 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08071 } else if (res) {
08072
08073 if (p->subs[SUB_THREEWAY].owner)
08074 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08075 break;
08076 }
08077 }
08078 } else {
08079 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08080 if (p->subs[SUB_THREEWAY].owner)
08081 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08082 }
08083 } else {
08084 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08085
08086 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08087 p->owner = NULL;
08088
08089 dahdi_ring_phone(p);
08090 }
08091 }
08092 } else {
08093 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08094 }
08095
08096 default:
08097 dahdi_disable_ec(p);
08098 return NULL;
08099 }
08100 break;
08101 case DAHDI_EVENT_RINGOFFHOOK:
08102 if (p->inalarm) break;
08103 if (p->oprmode < 0)
08104 {
08105 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08106 {
08107
08108 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08109 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08110 restore_conference(p->oprpeer);
08111 }
08112 break;
08113 }
08114 if (p->radio)
08115 {
08116 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08117 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08118 break;
08119 }
08120
08121
08122 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08123 c = strchr(p->dialdest, '/');
08124 if (c)
08125 c++;
08126 else
08127 c = p->dialdest;
08128 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08129 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08130 if (strlen(p->dop.dialstr) > 4) {
08131 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08132 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08133 p->echorest[sizeof(p->echorest) - 1] = '\0';
08134 p->echobreak = 1;
08135 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08136 } else
08137 p->echobreak = 0;
08138 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08139 int saveerr = errno;
08140
08141 x = DAHDI_ONHOOK;
08142 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08143 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08144 return NULL;
08145 }
08146 p->dialing = 1;
08147 return &p->subs[idx].f;
08148 }
08149 switch (p->sig) {
08150 case SIG_FXOLS:
08151 case SIG_FXOGS:
08152 case SIG_FXOKS:
08153 switch (ast->_state) {
08154 case AST_STATE_RINGING:
08155 dahdi_enable_ec(p);
08156 dahdi_train_ec(p);
08157 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08158 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08159
08160 p->subs[SUB_REAL].needringing = 0;
08161 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08162 ast_debug(1, "channel %d answered\n", p->channel);
08163
08164
08165 ast_free(p->cidspill);
08166 p->cidspill = NULL;
08167 restore_conference(p);
08168
08169 p->dialing = 0;
08170 p->callwaitcas = 0;
08171 if (p->confirmanswer) {
08172
08173 p->subs[idx].f.frametype = AST_FRAME_NULL;
08174 p->subs[idx].f.subclass.integer = 0;
08175 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08176
08177 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08178 if (res < 0) {
08179 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08180 p->dop.dialstr[0] = '\0';
08181 return NULL;
08182 } else {
08183 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08184 p->subs[idx].f.frametype = AST_FRAME_NULL;
08185 p->subs[idx].f.subclass.integer = 0;
08186 p->dialing = 1;
08187 }
08188 p->dop.dialstr[0] = '\0';
08189 ast_setstate(ast, AST_STATE_DIALING);
08190 } else
08191 ast_setstate(ast, AST_STATE_UP);
08192 return &p->subs[idx].f;
08193 case AST_STATE_DOWN:
08194 ast_setstate(ast, AST_STATE_RING);
08195 ast->rings = 1;
08196 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08197 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08198 ast_debug(1, "channel %d picked up\n", p->channel);
08199 return &p->subs[idx].f;
08200 case AST_STATE_UP:
08201
08202 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08203
08204 if (ast_bridged_channel(p->owner))
08205 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08206 p->subs[idx].needunhold = 1;
08207 break;
08208 case AST_STATE_RESERVED:
08209
08210 if (has_voicemail(p))
08211 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08212 else
08213 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08214 break;
08215 default:
08216 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08217 }
08218 break;
08219 case SIG_FXSLS:
08220 case SIG_FXSGS:
08221 case SIG_FXSKS:
08222 if (ast->_state == AST_STATE_RING) {
08223 p->ringt = p->ringt_base;
08224 }
08225
08226
08227
08228 ast_debug(1, "Setting IDLE polarity due "
08229 "to ring. Old polarity was %d\n",
08230 p->polarity);
08231 p->polarity = POLARITY_IDLE;
08232
08233
08234 case SIG_EM:
08235 case SIG_EM_E1:
08236 case SIG_EMWINK:
08237 case SIG_FEATD:
08238 case SIG_FEATDMF:
08239 case SIG_FEATDMF_TA:
08240 case SIG_E911:
08241 case SIG_FGC_CAMA:
08242 case SIG_FGC_CAMAMF:
08243 case SIG_FEATB:
08244 case SIG_SF:
08245 case SIG_SFWINK:
08246 case SIG_SF_FEATD:
08247 case SIG_SF_FEATDMF:
08248 case SIG_SF_FEATB:
08249 if (ast->_state == AST_STATE_PRERING)
08250 ast_setstate(ast, AST_STATE_RING);
08251 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08252 ast_debug(1, "Ring detected\n");
08253 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08254 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08255 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08256 ast_debug(1, "Line answered\n");
08257 if (p->confirmanswer) {
08258 p->subs[idx].f.frametype = AST_FRAME_NULL;
08259 p->subs[idx].f.subclass.integer = 0;
08260 } else {
08261 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08262 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08263 ast_setstate(ast, AST_STATE_UP);
08264 }
08265 } else if (ast->_state != AST_STATE_RING)
08266 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08267 break;
08268 default:
08269 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08270 }
08271 break;
08272 case DAHDI_EVENT_RINGBEGIN:
08273 switch (p->sig) {
08274 case SIG_FXSLS:
08275 case SIG_FXSGS:
08276 case SIG_FXSKS:
08277 if (ast->_state == AST_STATE_RING) {
08278 p->ringt = p->ringt_base;
08279 }
08280 break;
08281 }
08282 break;
08283 case DAHDI_EVENT_RINGERON:
08284 break;
08285 case DAHDI_EVENT_NOALARM:
08286 switch (p->sig) {
08287 #if defined(HAVE_PRI)
08288 case SIG_PRI_LIB_HANDLE_CASES:
08289 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08290 break;
08291 #endif
08292 #if defined(HAVE_SS7)
08293 case SIG_SS7:
08294 sig_ss7_set_alarm(p->sig_pvt, 0);
08295 break;
08296 #endif
08297 default:
08298 p->inalarm = 0;
08299 break;
08300 }
08301 handle_clear_alarms(p);
08302 break;
08303 case DAHDI_EVENT_WINKFLASH:
08304 if (p->inalarm) break;
08305 if (p->radio) break;
08306 if (p->oprmode < 0) break;
08307 if (p->oprmode > 1)
08308 {
08309 struct dahdi_params par;
08310
08311 memset(&par, 0, sizeof(par));
08312 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08313 {
08314 if (!par.rxisoffhook)
08315 {
08316
08317 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08318 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08319 save_conference(p);
08320 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08321 }
08322 }
08323 break;
08324 }
08325
08326 p->flashtime = ast_tvnow();
08327 switch (mysig) {
08328 case SIG_FXOLS:
08329 case SIG_FXOGS:
08330 case SIG_FXOKS:
08331 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08332 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08333
08334
08335 ast_free(p->cidspill);
08336 p->cidspill = NULL;
08337 restore_conference(p);
08338 p->callwaitcas = 0;
08339
08340 if (idx != SUB_REAL) {
08341 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08342 goto winkflashdone;
08343 }
08344
08345 if (p->subs[SUB_CALLWAIT].owner) {
08346
08347 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08348 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08349 p->owner = p->subs[SUB_REAL].owner;
08350 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08351 if (p->owner->_state == AST_STATE_RINGING) {
08352 ast_setstate(p->owner, AST_STATE_UP);
08353 p->subs[SUB_REAL].needanswer = 1;
08354 }
08355 p->callwaitingrepeat = 0;
08356 p->cidcwexpire = 0;
08357 p->cid_suppress_expire = 0;
08358
08359 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08360 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08361 S_OR(p->mohsuggest, NULL),
08362 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08363 }
08364 p->subs[SUB_CALLWAIT].needhold = 1;
08365 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08366 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08367 S_OR(p->mohsuggest, NULL),
08368 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08369 }
08370 p->subs[SUB_REAL].needunhold = 1;
08371 } else if (!p->subs[SUB_THREEWAY].owner) {
08372 if (!p->threewaycalling) {
08373
08374 p->subs[SUB_REAL].needflash = 1;
08375 goto winkflashdone;
08376 } else if (!check_for_conference(p)) {
08377 char cid_num[256];
08378 char cid_name[256];
08379
08380 cid_num[0] = 0;
08381 cid_name[0] = 0;
08382 if (p->dahditrcallerid && p->owner) {
08383 if (p->owner->caller.id.number.valid
08384 && p->owner->caller.id.number.str) {
08385 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08386 sizeof(cid_num));
08387 }
08388 if (p->owner->caller.id.name.valid
08389 && p->owner->caller.id.name.str) {
08390 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08391 sizeof(cid_name));
08392 }
08393 }
08394
08395
08396 if (!((ast->pbx) ||
08397 (ast->_state == AST_STATE_UP) ||
08398 (ast->_state == AST_STATE_RING))) {
08399 ast_debug(1, "Flash when call not up or ringing\n");
08400 goto winkflashdone;
08401 }
08402 if (alloc_sub(p, SUB_THREEWAY)) {
08403 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08404 goto winkflashdone;
08405 }
08406
08407 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08408 if (p->dahditrcallerid) {
08409 if (!p->origcid_num)
08410 p->origcid_num = ast_strdup(p->cid_num);
08411 if (!p->origcid_name)
08412 p->origcid_name = ast_strdup(p->cid_name);
08413 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08414 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08415 }
08416
08417 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08418
08419 dahdi_disable_ec(p);
08420 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08421 if (res)
08422 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08423 p->owner = chan;
08424 if (!chan) {
08425 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08426 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08427 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08428 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08429 dahdi_enable_ec(p);
08430 ast_hangup(chan);
08431 } else {
08432 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08433
08434
08435 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08436 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08437 S_OR(p->mohsuggest, NULL),
08438 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08439 }
08440 p->subs[SUB_THREEWAY].needhold = 1;
08441 }
08442 }
08443 } else {
08444
08445 if (p->subs[SUB_THREEWAY].inthreeway) {
08446
08447 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08448
08449 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08450
08451 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08452 p->owner = p->subs[SUB_REAL].owner;
08453 }
08454
08455 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08456 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08457 p->subs[SUB_REAL].inthreeway = 0;
08458 p->subs[SUB_THREEWAY].inthreeway = 0;
08459 } else {
08460
08461 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08462 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08463 int otherindex = SUB_THREEWAY;
08464
08465 ast_verb(3, "Building conference call with %s and %s\n",
08466 p->subs[SUB_THREEWAY].owner->name,
08467 p->subs[SUB_REAL].owner->name);
08468
08469 p->subs[SUB_THREEWAY].inthreeway = 1;
08470 p->subs[SUB_REAL].inthreeway = 1;
08471 if (ast->_state == AST_STATE_UP) {
08472 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08473 otherindex = SUB_REAL;
08474 }
08475 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08476 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08477 p->subs[otherindex].needunhold = 1;
08478 p->owner = p->subs[SUB_REAL].owner;
08479 } else {
08480 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08481 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08482 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08483 p->owner = p->subs[SUB_REAL].owner;
08484 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08485 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08486 p->subs[SUB_REAL].needunhold = 1;
08487 dahdi_enable_ec(p);
08488 }
08489 }
08490 }
08491 winkflashdone:
08492 update_conf(p);
08493 break;
08494 case SIG_EM:
08495 case SIG_EM_E1:
08496 case SIG_FEATD:
08497 case SIG_SF:
08498 case SIG_SFWINK:
08499 case SIG_SF_FEATD:
08500 case SIG_FXSLS:
08501 case SIG_FXSGS:
08502 if (p->dialing)
08503 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08504 else
08505 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08506 break;
08507 case SIG_FEATDMF_TA:
08508 switch (p->whichwink) {
08509 case 0:
08510 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08511 S_COR(p->owner->caller.ani.number.valid,
08512 p->owner->caller.ani.number.str, ""));
08513 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08514 p->owner->caller.ani2,
08515 S_COR(p->owner->caller.ani.number.valid,
08516 p->owner->caller.ani.number.str, ""));
08517 break;
08518 case 1:
08519 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08520 break;
08521 case 2:
08522 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08523 return NULL;
08524 }
08525 p->whichwink++;
08526
08527 case SIG_FEATDMF:
08528 case SIG_E911:
08529 case SIG_FGC_CAMAMF:
08530 case SIG_FGC_CAMA:
08531 case SIG_FEATB:
08532 case SIG_SF_FEATDMF:
08533 case SIG_SF_FEATB:
08534 case SIG_EMWINK:
08535
08536 if (!ast_strlen_zero(p->dop.dialstr)) {
08537 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08538 if (res < 0) {
08539 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08540 p->dop.dialstr[0] = '\0';
08541 return NULL;
08542 } else
08543 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08544 }
08545 p->dop.dialstr[0] = '\0';
08546 break;
08547 default:
08548 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08549 }
08550 break;
08551 case DAHDI_EVENT_HOOKCOMPLETE:
08552 if (p->inalarm) break;
08553 if ((p->radio || (p->oprmode < 0))) break;
08554 if (p->waitingfordt.tv_sec) break;
08555 switch (mysig) {
08556 case SIG_FXSLS:
08557 case SIG_FXSGS:
08558 case SIG_FXSKS:
08559 case SIG_EM:
08560 case SIG_EM_E1:
08561 case SIG_EMWINK:
08562 case SIG_FEATD:
08563 case SIG_SF:
08564 case SIG_SFWINK:
08565 case SIG_SF_FEATD:
08566 if (!ast_strlen_zero(p->dop.dialstr)) {
08567 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08568 if (res < 0) {
08569 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08570 p->dop.dialstr[0] = '\0';
08571 return NULL;
08572 } else
08573 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08574 }
08575 p->dop.dialstr[0] = '\0';
08576 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08577 break;
08578 case SIG_FEATDMF:
08579 case SIG_FEATDMF_TA:
08580 case SIG_E911:
08581 case SIG_FGC_CAMA:
08582 case SIG_FGC_CAMAMF:
08583 case SIG_FEATB:
08584 case SIG_SF_FEATDMF:
08585 case SIG_SF_FEATB:
08586 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08587 break;
08588 default:
08589 break;
08590 }
08591 break;
08592 case DAHDI_EVENT_POLARITY:
08593
08594
08595
08596
08597
08598
08599 if (p->polarity == POLARITY_IDLE) {
08600 p->polarity = POLARITY_REV;
08601 if (p->answeronpolarityswitch &&
08602 ((ast->_state == AST_STATE_DIALING) ||
08603 (ast->_state == AST_STATE_RINGING))) {
08604 ast_debug(1, "Answering on polarity switch!\n");
08605 ast_setstate(p->owner, AST_STATE_UP);
08606 if (p->hanguponpolarityswitch) {
08607 p->polaritydelaytv = ast_tvnow();
08608 }
08609 } else
08610 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08611 }
08612
08613
08614 if (p->hanguponpolarityswitch &&
08615 (p->polarityonanswerdelay > 0) &&
08616 (p->polarity == POLARITY_REV) &&
08617 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08618
08619 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) );
08620
08621 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08622 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08623 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08624 p->polarity = POLARITY_IDLE;
08625 } else
08626 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);
08627
08628 } else {
08629 p->polarity = POLARITY_IDLE;
08630 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08631 }
08632
08633 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) );
08634 break;
08635 default:
08636 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08637 }
08638 return &p->subs[idx].f;
08639 }
08640
08641 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08642 {
08643 int res;
08644 int idx;
08645 struct ast_frame *f;
08646 int usedindex = -1;
08647 struct dahdi_pvt *p = ast->tech_pvt;
08648
08649 idx = dahdi_get_index(ast, p, 1);
08650
08651 p->subs[idx].f.frametype = AST_FRAME_NULL;
08652 p->subs[idx].f.datalen = 0;
08653 p->subs[idx].f.samples = 0;
08654 p->subs[idx].f.mallocd = 0;
08655 p->subs[idx].f.offset = 0;
08656 p->subs[idx].f.subclass.integer = 0;
08657 p->subs[idx].f.delivery = ast_tv(0,0);
08658 p->subs[idx].f.src = "dahdi_exception";
08659 p->subs[idx].f.data.ptr = NULL;
08660
08661
08662 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08663
08664
08665
08666
08667
08668 if (p->fake_event) {
08669 res = p->fake_event;
08670 p->fake_event = 0;
08671 } else
08672 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08673
08674 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08675 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08676 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08677 p->owner = p->subs[SUB_REAL].owner;
08678 if (p->owner && ast_bridged_channel(p->owner))
08679 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08680 p->subs[SUB_REAL].needunhold = 1;
08681 }
08682 switch (res) {
08683 case DAHDI_EVENT_ONHOOK:
08684 dahdi_disable_ec(p);
08685 if (p->owner) {
08686 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08687 dahdi_ring_phone(p);
08688 p->callwaitingrepeat = 0;
08689 p->cidcwexpire = 0;
08690 p->cid_suppress_expire = 0;
08691 } else
08692 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08693 update_conf(p);
08694 break;
08695 case DAHDI_EVENT_RINGOFFHOOK:
08696 dahdi_enable_ec(p);
08697 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08698 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08699 p->subs[SUB_REAL].needanswer = 1;
08700 p->dialing = 0;
08701 }
08702 break;
08703 case DAHDI_EVENT_HOOKCOMPLETE:
08704 case DAHDI_EVENT_RINGERON:
08705 case DAHDI_EVENT_RINGEROFF:
08706
08707 break;
08708 case DAHDI_EVENT_WINKFLASH:
08709 p->flashtime = ast_tvnow();
08710 if (p->owner) {
08711 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08712 if (p->owner->_state != AST_STATE_UP) {
08713
08714 usedindex = dahdi_get_index(p->owner, p, 0);
08715 if (usedindex > -1) {
08716 p->subs[usedindex].needanswer = 1;
08717 }
08718 ast_setstate(p->owner, AST_STATE_UP);
08719 }
08720 p->callwaitingrepeat = 0;
08721 p->cidcwexpire = 0;
08722 p->cid_suppress_expire = 0;
08723 if (ast_bridged_channel(p->owner))
08724 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08725 p->subs[SUB_REAL].needunhold = 1;
08726 } else
08727 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08728 update_conf(p);
08729 break;
08730 default:
08731 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08732 }
08733 f = &p->subs[idx].f;
08734 return f;
08735 }
08736 if (!(p->radio || (p->oprmode < 0)))
08737 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08738
08739 if (ast != p->owner) {
08740 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08741 f = &p->subs[idx].f;
08742 return f;
08743 }
08744 f = dahdi_handle_event(ast);
08745
08746
08747 if (f == NULL) {
08748 ast_set_hangupsource(ast, ast->name, 0);
08749 }
08750
08751 return f;
08752 }
08753
08754 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08755 {
08756 struct dahdi_pvt *p = ast->tech_pvt;
08757 struct ast_frame *f;
08758 ast_mutex_lock(&p->lock);
08759 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08760 struct analog_pvt *analog_p = p->sig_pvt;
08761 f = analog_exception(analog_p, ast);
08762 } else {
08763 f = __dahdi_exception(ast);
08764 }
08765 ast_mutex_unlock(&p->lock);
08766 return f;
08767 }
08768
08769 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08770 {
08771 struct dahdi_pvt *p;
08772 int res;
08773 int idx;
08774 void *readbuf;
08775 struct ast_frame *f;
08776
08777
08778
08779
08780
08781
08782 p = ast->tech_pvt;
08783 while (ast_mutex_trylock(&p->lock)) {
08784 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08785
08786
08787
08788
08789
08790
08791 p = ast->tech_pvt;
08792 }
08793
08794 idx = dahdi_get_index(ast, p, 0);
08795
08796
08797 if (idx < 0) {
08798 ast_log(LOG_WARNING, "We don't exist?\n");
08799 ast_mutex_unlock(&p->lock);
08800 return NULL;
08801 }
08802
08803 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08804 ast_mutex_unlock(&p->lock);
08805 return NULL;
08806 }
08807
08808 p->subs[idx].f.frametype = AST_FRAME_NULL;
08809 p->subs[idx].f.datalen = 0;
08810 p->subs[idx].f.samples = 0;
08811 p->subs[idx].f.mallocd = 0;
08812 p->subs[idx].f.offset = 0;
08813 p->subs[idx].f.subclass.integer = 0;
08814 p->subs[idx].f.delivery = ast_tv(0,0);
08815 p->subs[idx].f.src = "dahdi_read";
08816 p->subs[idx].f.data.ptr = NULL;
08817
08818
08819 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08820 {
08821 struct dahdi_params ps;
08822
08823 memset(&ps, 0, sizeof(ps));
08824 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08825 ast_mutex_unlock(&p->lock);
08826 return NULL;
08827 }
08828 p->firstradio = 1;
08829 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08830 if (ps.rxisoffhook)
08831 {
08832 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08833 }
08834 else
08835 {
08836 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08837 }
08838 ast_mutex_unlock(&p->lock);
08839 return &p->subs[idx].f;
08840 }
08841 if (p->ringt > 0) {
08842 if (!(--p->ringt)) {
08843 ast_mutex_unlock(&p->lock);
08844 return NULL;
08845 }
08846 }
08847
08848 #ifdef HAVE_OPENR2
08849 if (p->mfcr2) {
08850 openr2_chan_process_event(p->r2chan);
08851 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08852 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08853
08854
08855 if (p->mfcr2_call_accepted &&
08856 !p->mfcr2_progress &&
08857 ast->_state == AST_STATE_RINGING) {
08858 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08859 ast_queue_frame(p->owner, &f);
08860 p->mfcr2_progress = 1;
08861 }
08862 }
08863 }
08864 #endif
08865
08866 if (p->subs[idx].needringing) {
08867
08868 p->subs[idx].needringing = 0;
08869 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08870 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08871 ast_setstate(ast, AST_STATE_RINGING);
08872 ast_mutex_unlock(&p->lock);
08873 return &p->subs[idx].f;
08874 }
08875
08876 if (p->subs[idx].needbusy) {
08877
08878 p->subs[idx].needbusy = 0;
08879 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08880 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08881 ast_mutex_unlock(&p->lock);
08882 return &p->subs[idx].f;
08883 }
08884
08885 if (p->subs[idx].needcongestion) {
08886
08887 p->subs[idx].needcongestion = 0;
08888 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08889 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08890 ast_mutex_unlock(&p->lock);
08891 return &p->subs[idx].f;
08892 }
08893
08894 if (p->subs[idx].needanswer) {
08895
08896 p->subs[idx].needanswer = 0;
08897 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08898 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08899 ast_mutex_unlock(&p->lock);
08900 return &p->subs[idx].f;
08901 }
08902 #ifdef HAVE_OPENR2
08903 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08904
08905
08906
08907
08908 ast_mutex_unlock(&p->lock);
08909 return &ast_null_frame;
08910 }
08911 #endif
08912
08913 if (p->subs[idx].needflash) {
08914
08915 p->subs[idx].needflash = 0;
08916 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08917 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08918 ast_mutex_unlock(&p->lock);
08919 return &p->subs[idx].f;
08920 }
08921
08922 if (p->subs[idx].needhold) {
08923
08924 p->subs[idx].needhold = 0;
08925 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08926 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08927 ast_mutex_unlock(&p->lock);
08928 ast_debug(1, "Sending hold on '%s'\n", ast->name);
08929 return &p->subs[idx].f;
08930 }
08931
08932 if (p->subs[idx].needunhold) {
08933
08934 p->subs[idx].needunhold = 0;
08935 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08936 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08937 ast_mutex_unlock(&p->lock);
08938 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08939 return &p->subs[idx].f;
08940 }
08941
08942
08943
08944
08945
08946 if (p->fake_event && p->owner == ast) {
08947 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08948 struct analog_pvt *analog_p = p->sig_pvt;
08949
08950 f = analog_exception(analog_p, ast);
08951 } else {
08952 f = __dahdi_exception(ast);
08953 }
08954 ast_mutex_unlock(&p->lock);
08955 return f;
08956 }
08957
08958 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08959 if (!p->subs[idx].linear) {
08960 p->subs[idx].linear = 1;
08961 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08962 if (res)
08963 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08964 }
08965 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08966 (ast->rawreadformat == AST_FORMAT_ALAW)) {
08967 if (p->subs[idx].linear) {
08968 p->subs[idx].linear = 0;
08969 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08970 if (res)
08971 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08972 }
08973 } else {
08974 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08975 ast_mutex_unlock(&p->lock);
08976 return NULL;
08977 }
08978 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08979 CHECK_BLOCKING(ast);
08980 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08981 ast_clear_flag(ast, AST_FLAG_BLOCKING);
08982
08983 if (res < 0) {
08984 f = NULL;
08985 if (res == -1) {
08986 if (errno == EAGAIN) {
08987
08988 ast_mutex_unlock(&p->lock);
08989 return &p->subs[idx].f;
08990 } else if (errno == ELAST) {
08991 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08992 struct analog_pvt *analog_p = p->sig_pvt;
08993 f = analog_exception(analog_p, ast);
08994 } else {
08995 f = __dahdi_exception(ast);
08996 }
08997 } else
08998 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08999 }
09000 ast_mutex_unlock(&p->lock);
09001 return f;
09002 }
09003 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09004 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09005 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09006 struct analog_pvt *analog_p = p->sig_pvt;
09007 f = analog_exception(analog_p, ast);
09008 } else {
09009 f = __dahdi_exception(ast);
09010 }
09011 ast_mutex_unlock(&p->lock);
09012 return f;
09013 }
09014 if (p->tdd) {
09015 int c;
09016
09017 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09018 if (c < 0) {
09019 ast_debug(1,"tdd_feed failed\n");
09020 ast_mutex_unlock(&p->lock);
09021 return NULL;
09022 }
09023 if (c) {
09024 p->subs[idx].f.subclass.integer = 0;
09025 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09026 p->subs[idx].f.mallocd = 0;
09027 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09028 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09029 p->subs[idx].f.datalen = 1;
09030 *((char *) p->subs[idx].f.data.ptr) = c;
09031 ast_mutex_unlock(&p->lock);
09032 return &p->subs[idx].f;
09033 }
09034 }
09035 if (idx == SUB_REAL) {
09036
09037 if (p->cidcwexpire) {
09038 if (!--p->cidcwexpire) {
09039
09040 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09041 restore_conference(p);
09042 }
09043 }
09044 if (p->cid_suppress_expire) {
09045 --p->cid_suppress_expire;
09046 }
09047 if (p->callwaitingrepeat) {
09048 if (!--p->callwaitingrepeat) {
09049
09050 ++p->callwaitrings;
09051 dahdi_callwait(ast);
09052 }
09053 }
09054 }
09055 if (p->subs[idx].linear) {
09056 p->subs[idx].f.datalen = READ_SIZE * 2;
09057 } else
09058 p->subs[idx].f.datalen = READ_SIZE;
09059
09060
09061 if ((p->owner == ast) && p->cidspill) {
09062 send_callerid(p);
09063 }
09064
09065 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09066 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09067 p->subs[idx].f.samples = READ_SIZE;
09068 p->subs[idx].f.mallocd = 0;
09069 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09070 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09071 #if 0
09072 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09073 #endif
09074 if (p->dialing || p->radio ||
09075 (idx && (ast->_state != AST_STATE_UP)) ||
09076 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09077 ) {
09078
09079
09080 p->subs[idx].f.frametype = AST_FRAME_NULL;
09081 p->subs[idx].f.subclass.integer = 0;
09082 p->subs[idx].f.samples = 0;
09083 p->subs[idx].f.mallocd = 0;
09084 p->subs[idx].f.offset = 0;
09085 p->subs[idx].f.data.ptr = NULL;
09086 p->subs[idx].f.datalen= 0;
09087 }
09088 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09089
09090 int mute;
09091
09092 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09093
09094
09095 mute = ast_dsp_was_muted(p->dsp);
09096 if (p->muting != mute) {
09097 p->muting = mute;
09098 dahdi_confmute(p, mute);
09099 }
09100
09101 if (f) {
09102 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09103 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09104
09105
09106 f = NULL;
09107 }
09108 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09109 || f->frametype == AST_FRAME_DTMF_END) {
09110 #ifdef HAVE_PRI
09111 if (dahdi_sig_pri_lib_handles(p->sig)
09112 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09113 && p->pri
09114 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09115 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09116
09117 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09118 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09119 f->subclass.integer, f->subclass.integer, ast->name);
09120
09121 f->frametype = AST_FRAME_NULL;
09122 f->subclass.integer = 0;
09123 }
09124 #endif
09125
09126 p->pulsedial = 0;
09127 } else if (p->waitingfordt.tv_sec) {
09128 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09129 p->waitingfordt.tv_sec = 0;
09130 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09131 f=NULL;
09132 } else if (f->frametype == AST_FRAME_VOICE) {
09133 f->frametype = AST_FRAME_NULL;
09134 f->subclass.integer = 0;
09135 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) {
09136 p->waitingfordt.tv_sec = 0;
09137 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09138 ast_dsp_set_features(p->dsp, p->dsp_features);
09139 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09140 if (!ast_strlen_zero(p->dop.dialstr)) {
09141 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09142 if (res < 0) {
09143 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09144 p->dop.dialstr[0] = '\0';
09145 ast_mutex_unlock(&p->lock);
09146 return NULL;
09147 } else {
09148 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09149 p->dialing = 1;
09150 p->dop.dialstr[0] = '\0';
09151 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09152 ast_setstate(ast, AST_STATE_DIALING);
09153 }
09154 }
09155 }
09156 }
09157 }
09158 }
09159 } else
09160 f = &p->subs[idx].f;
09161
09162 if (f) {
09163 switch (f->frametype) {
09164 case AST_FRAME_DTMF_BEGIN:
09165 case AST_FRAME_DTMF_END:
09166 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09167 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09168 } else {
09169 dahdi_handle_dtmf(ast, idx, &f);
09170 }
09171 break;
09172 case AST_FRAME_VOICE:
09173 if (p->cidspill || p->cid_suppress_expire) {
09174
09175 p->subs[idx].f.frametype = AST_FRAME_NULL;
09176 p->subs[idx].f.subclass.integer = 0;
09177 p->subs[idx].f.samples = 0;
09178 p->subs[idx].f.mallocd = 0;
09179 p->subs[idx].f.offset = 0;
09180 p->subs[idx].f.data.ptr = NULL;
09181 p->subs[idx].f.datalen= 0;
09182 }
09183 break;
09184 default:
09185 break;
09186 }
09187 }
09188
09189 ast_mutex_unlock(&p->lock);
09190 return f;
09191 }
09192
09193 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09194 {
09195 int sent=0;
09196 int size;
09197 int res;
09198 int fd;
09199 fd = p->subs[idx].dfd;
09200 while (len) {
09201 size = len;
09202 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09203 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09204 res = write(fd, buf, size);
09205 if (res != size) {
09206 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09207 return sent;
09208 }
09209 len -= size;
09210 buf += size;
09211 }
09212 return sent;
09213 }
09214
09215 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09216 {
09217 struct dahdi_pvt *p = ast->tech_pvt;
09218 int res;
09219 int idx;
09220 idx = dahdi_get_index(ast, p, 0);
09221 if (idx < 0) {
09222 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09223 return -1;
09224 }
09225
09226
09227 if (frame->frametype != AST_FRAME_VOICE) {
09228 if (frame->frametype != AST_FRAME_IMAGE)
09229 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09230 return 0;
09231 }
09232 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09233 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09234 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09235 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09236 return -1;
09237 }
09238 if (p->dialing) {
09239 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09240 return 0;
09241 }
09242 if (!p->owner) {
09243 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09244 return 0;
09245 }
09246 if (p->cidspill) {
09247 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09248 ast->name);
09249 return 0;
09250 }
09251
09252 if (!frame->data.ptr || !frame->datalen)
09253 return 0;
09254
09255 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09256 if (!p->subs[idx].linear) {
09257 p->subs[idx].linear = 1;
09258 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09259 if (res)
09260 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09261 }
09262 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09263 } else {
09264
09265 if (p->subs[idx].linear) {
09266 p->subs[idx].linear = 0;
09267 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09268 if (res)
09269 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09270 }
09271 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09272 }
09273 if (res < 0) {
09274 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09275 return -1;
09276 }
09277 return 0;
09278 }
09279
09280 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09281 {
09282 struct dahdi_pvt *p = chan->tech_pvt;
09283 int res=-1;
09284 int idx;
09285 int func = DAHDI_FLASH;
09286
09287 ast_mutex_lock(&p->lock);
09288 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09289 switch (p->sig) {
09290 #if defined(HAVE_PRI)
09291 case SIG_PRI_LIB_HANDLE_CASES:
09292 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09293 ast_mutex_unlock(&p->lock);
09294 return res;
09295 #endif
09296 #if defined(HAVE_SS7)
09297 case SIG_SS7:
09298 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09299 ast_mutex_unlock(&p->lock);
09300 return res;
09301 #endif
09302 default:
09303 break;
09304 }
09305 #ifdef HAVE_OPENR2
09306 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09307 ast_mutex_unlock(&p->lock);
09308
09309
09310 return 0;
09311 }
09312 #endif
09313 idx = dahdi_get_index(chan, p, 0);
09314 if (idx == SUB_REAL) {
09315 switch (condition) {
09316 case AST_CONTROL_BUSY:
09317 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09318 break;
09319 case AST_CONTROL_RINGING:
09320 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09321
09322 if (chan->_state != AST_STATE_UP) {
09323 if ((chan->_state != AST_STATE_RING) ||
09324 ((p->sig != SIG_FXSKS) &&
09325 (p->sig != SIG_FXSLS) &&
09326 (p->sig != SIG_FXSGS)))
09327 ast_setstate(chan, AST_STATE_RINGING);
09328 }
09329 break;
09330 case AST_CONTROL_INCOMPLETE:
09331 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09332
09333 res = 0;
09334 break;
09335 case AST_CONTROL_PROCEEDING:
09336 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09337
09338 res = 0;
09339 break;
09340 case AST_CONTROL_PROGRESS:
09341 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09342
09343 res = 0;
09344 break;
09345 case AST_CONTROL_CONGESTION:
09346
09347 switch (chan->hangupcause) {
09348 case AST_CAUSE_USER_BUSY:
09349 case AST_CAUSE_NORMAL_CLEARING:
09350 case 0:
09351
09352 chan->hangupcause = AST_CAUSE_CONGESTION;
09353 break;
09354 default:
09355 break;
09356 }
09357 break;
09358 case AST_CONTROL_HOLD:
09359 ast_moh_start(chan, data, p->mohinterpret);
09360 break;
09361 case AST_CONTROL_UNHOLD:
09362 ast_moh_stop(chan);
09363 break;
09364 case AST_CONTROL_RADIO_KEY:
09365 if (p->radio)
09366 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09367 res = 0;
09368 break;
09369 case AST_CONTROL_RADIO_UNKEY:
09370 if (p->radio)
09371 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09372 res = 0;
09373 break;
09374 case AST_CONTROL_FLASH:
09375
09376 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09377
09378 p->dop.dialstr[0] = '\0';
09379 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09380 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09381 chan->name, strerror(errno));
09382 } else
09383 res = 0;
09384 } else
09385 res = 0;
09386 break;
09387 case AST_CONTROL_SRCUPDATE:
09388 res = 0;
09389 break;
09390 case -1:
09391 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09392 break;
09393 }
09394 } else {
09395 res = 0;
09396 }
09397 ast_mutex_unlock(&p->lock);
09398 return res;
09399 }
09400
09401 #if defined(HAVE_PRI)
09402 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09403 #else
09404 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09405 #endif
09406 {
09407 struct ast_str *chan_name;
09408 int x, y;
09409
09410
09411 if (!(chan_name = ast_str_create(32))) {
09412 return NULL;
09413 }
09414 if (i->channel == CHAN_PSEUDO) {
09415 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09416 #if defined(HAVE_PRI)
09417 } else if (i->pri) {
09418 ast_mutex_lock(&i->pri->lock);
09419 y = ++i->pri->new_chan_seq;
09420 if (is_outgoing) {
09421 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09422 address[0] = '\0';
09423 } else if (ast_strlen_zero(i->cid_subaddr)) {
09424
09425 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09426 } else {
09427
09428 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09429 i->cid_subaddr, y);
09430 }
09431 ast_mutex_unlock(&i->pri->lock);
09432 #endif
09433 } else {
09434 y = 1;
09435 do {
09436 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09437 for (x = 0; x < 3; ++x) {
09438 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09439 i->subs[x].owner->name + 6)) {
09440 break;
09441 }
09442 }
09443 ++y;
09444 } while (x < 3);
09445 }
09446 return chan_name;
09447 }
09448
09449 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09450 {
09451 struct ast_channel *tmp;
09452 format_t deflaw;
09453 int x;
09454 int features;
09455 struct ast_str *chan_name;
09456 struct ast_variable *v;
09457 char *dashptr;
09458 char device_name[AST_CHANNEL_NAME];
09459
09460 if (i->subs[idx].owner) {
09461 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09462 return NULL;
09463 }
09464
09465 #if defined(HAVE_PRI)
09466
09467
09468
09469
09470 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09471 #else
09472 chan_name = create_channel_name(i);
09473 #endif
09474 if (!chan_name) {
09475 return NULL;
09476 }
09477
09478 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));
09479 ast_free(chan_name);
09480 if (!tmp)
09481 return NULL;
09482 tmp->tech = &dahdi_tech;
09483 #if defined(HAVE_PRI)
09484 if (i->pri) {
09485 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09486 }
09487 #endif
09488 ast_channel_cc_params_init(tmp, i->cc_params);
09489 if (law) {
09490 i->law = law;
09491 if (law == DAHDI_LAW_ALAW) {
09492 deflaw = AST_FORMAT_ALAW;
09493 } else {
09494 deflaw = AST_FORMAT_ULAW;
09495 }
09496 } else {
09497 switch (i->sig) {
09498 case SIG_PRI_LIB_HANDLE_CASES:
09499
09500 i->law = (i->law_default == DAHDI_LAW_ALAW)
09501 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09502 break;
09503 default:
09504 i->law = i->law_default;
09505 break;
09506 }
09507 if (i->law_default == DAHDI_LAW_ALAW) {
09508 deflaw = AST_FORMAT_ALAW;
09509 } else {
09510 deflaw = AST_FORMAT_ULAW;
09511 }
09512 }
09513 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09514 tmp->nativeformats = deflaw;
09515
09516 tmp->rawreadformat = deflaw;
09517 tmp->readformat = deflaw;
09518 tmp->rawwriteformat = deflaw;
09519 tmp->writeformat = deflaw;
09520 i->subs[idx].linear = 0;
09521 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09522 features = 0;
09523 if (idx == SUB_REAL) {
09524 if (i->busydetect && CANBUSYDETECT(i))
09525 features |= DSP_FEATURE_BUSY_DETECT;
09526 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09527 features |= DSP_FEATURE_CALL_PROGRESS;
09528 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09529 features |= DSP_FEATURE_WAITDIALTONE;
09530 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09531 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09532 features |= DSP_FEATURE_FAX_DETECT;
09533 }
09534 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09535 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09536 i->hardwaredtmf = 0;
09537 features |= DSP_FEATURE_DIGIT_DETECT;
09538 } else if (NEED_MFDETECT(i)) {
09539 i->hardwaredtmf = 1;
09540 features |= DSP_FEATURE_DIGIT_DETECT;
09541 }
09542 }
09543 if (features) {
09544 if (i->dsp) {
09545 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09546 } else {
09547 if (i->channel != CHAN_PSEUDO)
09548 i->dsp = ast_dsp_new();
09549 else
09550 i->dsp = NULL;
09551 if (i->dsp) {
09552 i->dsp_features = features;
09553 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09554
09555 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09556
09557
09558 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09559 features = 0;
09560 }
09561 #endif
09562 ast_dsp_set_features(i->dsp, features);
09563 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09564 if (!ast_strlen_zero(progzone))
09565 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09566 if (i->busydetect && CANBUSYDETECT(i)) {
09567 ast_dsp_set_busy_count(i->dsp, i->busycount);
09568 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09569 }
09570 }
09571 }
09572 }
09573
09574 if (state == AST_STATE_RING)
09575 tmp->rings = 1;
09576 tmp->tech_pvt = i;
09577 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09578
09579 tmp->callgroup = i->callgroup;
09580 tmp->pickupgroup = i->pickupgroup;
09581 }
09582 if (!ast_strlen_zero(i->parkinglot))
09583 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09584 if (!ast_strlen_zero(i->language))
09585 ast_string_field_set(tmp, language, i->language);
09586 if (!i->owner)
09587 i->owner = tmp;
09588 if (!ast_strlen_zero(i->accountcode))
09589 ast_string_field_set(tmp, accountcode, i->accountcode);
09590 if (i->amaflags)
09591 tmp->amaflags = i->amaflags;
09592 i->subs[idx].owner = tmp;
09593 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09594 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09595 ast_string_field_set(tmp, call_forward, i->call_forward);
09596 }
09597
09598 if (!i->adsi)
09599 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09600 if (!ast_strlen_zero(i->exten))
09601 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09602 if (!ast_strlen_zero(i->rdnis)) {
09603 tmp->redirecting.from.number.valid = 1;
09604 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09605 }
09606 if (!ast_strlen_zero(i->dnid)) {
09607 tmp->dialed.number.str = ast_strdup(i->dnid);
09608 }
09609
09610
09611
09612 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09613 if (!ast_strlen_zero(i->cid_ani)) {
09614 tmp->caller.ani.number.valid = 1;
09615 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09616 } else if (!ast_strlen_zero(i->cid_num)) {
09617 tmp->caller.ani.number.valid = 1;
09618 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09619 }
09620 #else
09621 if (!ast_strlen_zero(i->cid_num)) {
09622 tmp->caller.ani.number.valid = 1;
09623 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09624 }
09625 #endif
09626 tmp->caller.id.name.presentation = i->callingpres;
09627 tmp->caller.id.number.presentation = i->callingpres;
09628 tmp->caller.id.number.plan = i->cid_ton;
09629 tmp->caller.ani2 = i->cid_ani2;
09630 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09631
09632 i->fake_event = 0;
09633
09634 dahdi_confmute(i, 0);
09635 i->muting = 0;
09636
09637 ast_jb_configure(tmp, &global_jbconf);
09638
09639
09640 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09641 dashptr = strrchr(device_name, '-');
09642 if (dashptr) {
09643 *dashptr = '\0';
09644 }
09645 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09646
09647 for (v = i->vars ; v ; v = v->next)
09648 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09649
09650 ast_module_ref(ast_module_info->self);
09651
09652 dahdi_ami_channel_event(i, tmp);
09653 if (startpbx) {
09654 #ifdef HAVE_OPENR2
09655 if (i->mfcr2call) {
09656 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09657 }
09658 #endif
09659 if (ast_pbx_start(tmp)) {
09660 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09661 ast_hangup(tmp);
09662 return NULL;
09663 }
09664 }
09665 return tmp;
09666 }
09667
09668
09669 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09670 {
09671 char c;
09672
09673 *str = 0;
09674 for (;;)
09675 {
09676
09677 c = ast_waitfordigit(chan, ms);
09678
09679 if (c < 1)
09680 return c;
09681 *str++ = c;
09682 *str = 0;
09683 if (strchr(term, c))
09684 return 1;
09685 }
09686 }
09687
09688 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09689 {
09690 int j;
09691 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09692 for (;;)
09693 {
09694
09695 j = DAHDI_IOMUX_SIGEVENT;
09696
09697 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09698
09699 if (j & DAHDI_IOMUX_SIGEVENT) break;
09700 }
09701
09702 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09703 return 0;
09704 }
09705
09706
09707
09708
09709
09710
09711
09712
09713
09714
09715 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09716 {
09717 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09718 return analog_dnd(dahdichan->sig_pvt, flag);
09719 }
09720
09721 if (flag == -1) {
09722 return dahdichan->dnd;
09723 }
09724
09725
09726 dahdichan->dnd = flag;
09727 ast_verb(3, "%s DND on channel %d\n",
09728 flag? "Enabled" : "Disabled",
09729 dahdichan->channel);
09730 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09731 "Channel: DAHDI/%d\r\n"
09732 "Status: %s\r\n", dahdichan->channel,
09733 flag? "enabled" : "disabled");
09734
09735 return 0;
09736 }
09737
09738 static int canmatch_featurecode(const char *exten)
09739 {
09740 int extlen = strlen(exten);
09741 const char *pickup_ext;
09742 if (!extlen) {
09743 return 1;
09744 }
09745 pickup_ext = ast_pickup_ext();
09746 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09747 return 1;
09748 }
09749
09750 if (exten[0] == '*' && extlen < 3) {
09751 if (extlen == 1) {
09752 return 1;
09753 }
09754
09755 switch (exten[1]) {
09756 case '6':
09757 case '7':
09758 case '8':
09759 return 1;
09760 }
09761 }
09762 return 0;
09763 }
09764
09765 static void *analog_ss_thread(void *data)
09766 {
09767 struct ast_channel *chan = data;
09768 struct dahdi_pvt *p = chan->tech_pvt;
09769 char exten[AST_MAX_EXTENSION] = "";
09770 char exten2[AST_MAX_EXTENSION] = "";
09771 unsigned char buf[256];
09772 char dtmfcid[300];
09773 char dtmfbuf[300];
09774 struct callerid_state *cs = NULL;
09775 char *name = NULL, *number = NULL;
09776 int distMatches;
09777 int curRingData[3];
09778 int receivedRingT;
09779 int counter1;
09780 int counter;
09781 int samples = 0;
09782 struct ast_smdi_md_message *smdi_msg = NULL;
09783 int flags = 0;
09784 int i;
09785 int timeout;
09786 int getforward = 0;
09787 char *s1, *s2;
09788 int len = 0;
09789 int res;
09790 int idx;
09791
09792 ast_mutex_lock(&ss_thread_lock);
09793 ss_thread_count++;
09794 ast_mutex_unlock(&ss_thread_lock);
09795
09796
09797
09798 if (!p) {
09799 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09800 ast_hangup(chan);
09801 goto quit;
09802 }
09803 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09804 idx = dahdi_get_index(chan, p, 1);
09805 if (idx < 0) {
09806 ast_log(LOG_WARNING, "Huh?\n");
09807 ast_hangup(chan);
09808 goto quit;
09809 }
09810 if (p->dsp)
09811 ast_dsp_digitreset(p->dsp);
09812 switch (p->sig) {
09813 case SIG_FEATD:
09814 case SIG_FEATDMF:
09815 case SIG_FEATDMF_TA:
09816 case SIG_E911:
09817 case SIG_FGC_CAMAMF:
09818 case SIG_FEATB:
09819 case SIG_EMWINK:
09820 case SIG_SF_FEATD:
09821 case SIG_SF_FEATDMF:
09822 case SIG_SF_FEATB:
09823 case SIG_SFWINK:
09824 if (dahdi_wink(p, idx))
09825 goto quit;
09826
09827 case SIG_EM:
09828 case SIG_EM_E1:
09829 case SIG_SF:
09830 case SIG_FGC_CAMA:
09831 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09832 if (p->dsp)
09833 ast_dsp_digitreset(p->dsp);
09834
09835 if (p->dsp) {
09836 if (NEED_MFDETECT(p))
09837 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09838 else
09839 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09840 }
09841 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09842
09843 if (!p->immediate)
09844
09845 res = ast_waitfordigit(chan, 5000);
09846 else
09847 res = 0;
09848 if (res > 0) {
09849
09850 dtmfbuf[0] = res;
09851 switch (p->sig) {
09852 case SIG_FEATD:
09853 case SIG_SF_FEATD:
09854 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09855 if (res > 0)
09856 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09857 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09858 break;
09859 case SIG_FEATDMF_TA:
09860 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09861 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09862 if (dahdi_wink(p, idx)) goto quit;
09863 dtmfbuf[0] = 0;
09864
09865 res = ast_waitfordigit(chan, 5000);
09866 if (res <= 0) break;
09867 dtmfbuf[0] = res;
09868
09869 case SIG_FEATDMF:
09870 case SIG_E911:
09871 case SIG_FGC_CAMAMF:
09872 case SIG_SF_FEATDMF:
09873 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09874
09875 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09876 {
09877 if (dahdi_wink(p, idx)) goto quit;
09878 dtmfbuf[0] = 0;
09879
09880 res = ast_waitfordigit(chan, 5000);
09881 if (res <= 0) break;
09882 dtmfbuf[0] = res;
09883 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09884 }
09885 if (res > 0) {
09886
09887 if (p->sig == SIG_E911)
09888 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09889 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09890 }
09891 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09892 break;
09893 case SIG_FEATB:
09894 case SIG_SF_FEATB:
09895 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09896 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09897 break;
09898 case SIG_EMWINK:
09899
09900
09901
09902
09903 if (res == '*') {
09904 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09905 if (res > 0)
09906 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09907 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09908 break;
09909 }
09910 default:
09911
09912 len = 1;
09913 dtmfbuf[len] = '\0';
09914 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09915 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09916 timeout = matchdigittimeout;
09917 } else {
09918 timeout = gendigittimeout;
09919 }
09920 res = ast_waitfordigit(chan, timeout);
09921 if (res < 0) {
09922 ast_debug(1, "waitfordigit returned < 0...\n");
09923 ast_hangup(chan);
09924 goto quit;
09925 } else if (res) {
09926 dtmfbuf[len++] = res;
09927 dtmfbuf[len] = '\0';
09928 } else {
09929 break;
09930 }
09931 }
09932 break;
09933 }
09934 }
09935 if (res == -1) {
09936 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09937 ast_hangup(chan);
09938 goto quit;
09939 } else if (res < 0) {
09940 ast_debug(1, "Got hung up before digits finished\n");
09941 ast_hangup(chan);
09942 goto quit;
09943 }
09944
09945 if (p->sig == SIG_FGC_CAMA) {
09946 char anibuf[100];
09947
09948 if (ast_safe_sleep(chan,1000) == -1) {
09949 ast_hangup(chan);
09950 goto quit;
09951 }
09952 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09953 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09954 res = my_getsigstr(chan, anibuf, "#", 10000);
09955 if ((res > 0) && (strlen(anibuf) > 2)) {
09956 if (anibuf[strlen(anibuf) - 1] == '#')
09957 anibuf[strlen(anibuf) - 1] = 0;
09958 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09959 }
09960 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09961 }
09962
09963 ast_copy_string(exten, dtmfbuf, sizeof(exten));
09964 if (ast_strlen_zero(exten))
09965 ast_copy_string(exten, "s", sizeof(exten));
09966 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09967
09968 if (exten[0] == '*') {
09969 char *stringp=NULL;
09970 ast_copy_string(exten2, exten, sizeof(exten2));
09971
09972 stringp=exten2 +1;
09973 s1 = strsep(&stringp, "*");
09974 s2 = strsep(&stringp, "*");
09975 if (s2) {
09976 if (!ast_strlen_zero(p->cid_num))
09977 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09978 else
09979 ast_set_callerid(chan, s1, NULL, s1);
09980 ast_copy_string(exten, s2, sizeof(exten));
09981 } else
09982 ast_copy_string(exten, s1, sizeof(exten));
09983 } else if (p->sig == SIG_FEATD)
09984 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09985 }
09986 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09987 if (exten[0] == '*') {
09988 char *stringp=NULL;
09989 ast_copy_string(exten2, exten, sizeof(exten2));
09990
09991 stringp=exten2 +1;
09992 s1 = strsep(&stringp, "#");
09993 s2 = strsep(&stringp, "#");
09994 if (s2) {
09995 if (!ast_strlen_zero(p->cid_num))
09996 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09997 else
09998 if (*(s1 + 2))
09999 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10000 ast_copy_string(exten, s2 + 1, sizeof(exten));
10001 } else
10002 ast_copy_string(exten, s1 + 2, sizeof(exten));
10003 } else
10004 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10005 }
10006 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10007 if (exten[0] == '*') {
10008 char *stringp=NULL;
10009 ast_copy_string(exten2, exten, sizeof(exten2));
10010
10011 stringp=exten2 +1;
10012 s1 = strsep(&stringp, "#");
10013 s2 = strsep(&stringp, "#");
10014 if (s2 && (*(s2 + 1) == '0')) {
10015 if (*(s2 + 2))
10016 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10017 }
10018 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10019 else ast_copy_string(exten, "911", sizeof(exten));
10020 } else
10021 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10022 }
10023 if (p->sig == SIG_FEATB) {
10024 if (exten[0] == '*') {
10025 char *stringp=NULL;
10026 ast_copy_string(exten2, exten, sizeof(exten2));
10027
10028 stringp=exten2 +1;
10029 s1 = strsep(&stringp, "#");
10030 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10031 } else
10032 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10033 }
10034 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10035 dahdi_wink(p, idx);
10036
10037
10038
10039 if (ast_safe_sleep(chan, 100)) {
10040 ast_hangup(chan);
10041 goto quit;
10042 }
10043 }
10044 dahdi_enable_ec(p);
10045 if (NEED_MFDETECT(p)) {
10046 if (p->dsp) {
10047 if (!p->hardwaredtmf)
10048 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10049 else {
10050 ast_dsp_free(p->dsp);
10051 p->dsp = NULL;
10052 }
10053 }
10054 }
10055
10056 if (ast_exists_extension(chan, chan->context, exten, 1,
10057 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10058 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10059 if (p->dsp) ast_dsp_digitreset(p->dsp);
10060 res = ast_pbx_run(chan);
10061 if (res) {
10062 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10063 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10064 }
10065 goto quit;
10066 } else {
10067 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10068 sleep(2);
10069 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10070 if (res < 0)
10071 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10072 else
10073 sleep(1);
10074 res = ast_streamfile(chan, "ss-noservice", chan->language);
10075 if (res >= 0)
10076 ast_waitstream(chan, "");
10077 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10078 ast_hangup(chan);
10079 goto quit;
10080 }
10081 break;
10082 case SIG_FXOLS:
10083 case SIG_FXOGS:
10084 case SIG_FXOKS:
10085
10086 timeout = firstdigittimeout;
10087
10088
10089 if (p->subs[SUB_THREEWAY].owner)
10090 timeout = 999999;
10091 while (len < AST_MAX_EXTENSION-1) {
10092
10093
10094 if (p->immediate)
10095 res = 's';
10096 else
10097 res = ast_waitfordigit(chan, timeout);
10098 timeout = 0;
10099 if (res < 0) {
10100 ast_debug(1, "waitfordigit returned < 0...\n");
10101 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10102 ast_hangup(chan);
10103 goto quit;
10104 } else if (res) {
10105 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10106 exten[len++]=res;
10107 exten[len] = '\0';
10108 }
10109 if (!ast_ignore_pattern(chan->context, exten))
10110 tone_zone_play_tone(p->subs[idx].dfd, -1);
10111 else
10112 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10113 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10114 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10115 if (getforward) {
10116
10117 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10118 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10119 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10120 if (res)
10121 break;
10122 usleep(500000);
10123 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10124 sleep(1);
10125 memset(exten, 0, sizeof(exten));
10126 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10127 len = 0;
10128 getforward = 0;
10129 } else {
10130 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10131 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10132 if (!ast_strlen_zero(p->cid_num)) {
10133 if (!p->hidecallerid)
10134 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10135 else
10136 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10137 }
10138 if (!ast_strlen_zero(p->cid_name)) {
10139 if (!p->hidecallerid)
10140 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10141 }
10142 ast_setstate(chan, AST_STATE_RING);
10143 dahdi_enable_ec(p);
10144 res = ast_pbx_run(chan);
10145 if (res) {
10146 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10147 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10148 }
10149 goto quit;
10150 }
10151 } else {
10152
10153
10154 timeout = matchdigittimeout;
10155 }
10156 } else if (res == 0) {
10157 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10158 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10159 dahdi_wait_event(p->subs[idx].dfd);
10160 ast_hangup(chan);
10161 goto quit;
10162 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10163 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10164
10165 p->callwaiting = 0;
10166 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10167 if (res) {
10168 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10169 chan->name, strerror(errno));
10170 }
10171 len = 0;
10172 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10173 memset(exten, 0, sizeof(exten));
10174 timeout = firstdigittimeout;
10175
10176 } else if (!strcmp(exten,ast_pickup_ext())) {
10177
10178
10179
10180
10181 if (idx == SUB_REAL) {
10182
10183 if (p->subs[SUB_THREEWAY].owner) {
10184
10185
10186 alloc_sub(p, SUB_CALLWAIT);
10187 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10188 unalloc_sub(p, SUB_THREEWAY);
10189 }
10190 dahdi_enable_ec(p);
10191 if (ast_pickup_call(chan)) {
10192 ast_debug(1, "No call pickup possible...\n");
10193 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10194 dahdi_wait_event(p->subs[idx].dfd);
10195 }
10196 ast_hangup(chan);
10197 goto quit;
10198 } else {
10199 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10200 ast_hangup(chan);
10201 goto quit;
10202 }
10203
10204 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10205 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10206
10207 p->hidecallerid = 1;
10208 ast_party_number_free(&chan->caller.id.number);
10209 ast_party_number_init(&chan->caller.id.number);
10210 ast_party_name_free(&chan->caller.id.name);
10211 ast_party_name_init(&chan->caller.id.name);
10212 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10213 if (res) {
10214 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10215 chan->name, strerror(errno));
10216 }
10217 len = 0;
10218 memset(exten, 0, sizeof(exten));
10219 timeout = firstdigittimeout;
10220 } else if (p->callreturn && !strcmp(exten, "*69")) {
10221 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10222 break;
10223 } else if (!strcmp(exten, "*78")) {
10224 dahdi_dnd(p, 1);
10225
10226 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10227 getforward = 0;
10228 memset(exten, 0, sizeof(exten));
10229 len = 0;
10230 } else if (!strcmp(exten, "*79")) {
10231 dahdi_dnd(p, 0);
10232
10233 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10234 getforward = 0;
10235 memset(exten, 0, sizeof(exten));
10236 len = 0;
10237 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10238 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10239 getforward = 1;
10240 memset(exten, 0, sizeof(exten));
10241 len = 0;
10242 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10243 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10244 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10245 memset(p->call_forward, 0, sizeof(p->call_forward));
10246 getforward = 0;
10247 memset(exten, 0, sizeof(exten));
10248 len = 0;
10249 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10250 p->subs[SUB_THREEWAY].owner &&
10251 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10252
10253
10254 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10255 chan, exten, chan->context, 0, NULL);
10256 ast_verb(3, "Parking call to '%s'\n", chan->name);
10257 break;
10258 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10259 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10260
10261 p->hidecallerid = 0;
10262 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10263 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10264 if (res) {
10265 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10266 chan->name, strerror(errno));
10267 }
10268 len = 0;
10269 memset(exten, 0, sizeof(exten));
10270 timeout = firstdigittimeout;
10271 } else if (!strcmp(exten, "*0")) {
10272 struct ast_channel *nbridge =
10273 p->subs[SUB_THREEWAY].owner;
10274 struct dahdi_pvt *pbridge = NULL;
10275
10276 if (nbridge && ast_bridged_channel(nbridge))
10277 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10278 if (nbridge && pbridge &&
10279 (nbridge->tech == &dahdi_tech) &&
10280 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10281 ISTRUNK(pbridge)) {
10282 int func = DAHDI_FLASH;
10283
10284 p->dop.dialstr[0] = '\0';
10285
10286 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10287 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10288 nbridge->name, strerror(errno));
10289 }
10290 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10291 unalloc_sub(p, SUB_THREEWAY);
10292 p->owner = p->subs[SUB_REAL].owner;
10293 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10294 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10295 ast_hangup(chan);
10296 goto quit;
10297 } else {
10298 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10299 dahdi_wait_event(p->subs[idx].dfd);
10300 tone_zone_play_tone(p->subs[idx].dfd, -1);
10301 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10302 unalloc_sub(p, SUB_THREEWAY);
10303 p->owner = p->subs[SUB_REAL].owner;
10304 ast_hangup(chan);
10305 goto quit;
10306 }
10307 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10308 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10309 && !canmatch_featurecode(exten)) {
10310 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10311 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10312 chan->context);
10313 break;
10314 }
10315 if (!timeout)
10316 timeout = gendigittimeout;
10317 if (len && !ast_ignore_pattern(chan->context, exten))
10318 tone_zone_play_tone(p->subs[idx].dfd, -1);
10319 }
10320 break;
10321 case SIG_FXSLS:
10322 case SIG_FXSGS:
10323 case SIG_FXSKS:
10324
10325 if (p->use_smdi && p->smdi_iface) {
10326 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10327
10328 if (smdi_msg != NULL) {
10329 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10330
10331 if (smdi_msg->type == 'B')
10332 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10333 else if (smdi_msg->type == 'N')
10334 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10335
10336 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10337 } else {
10338 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10339 }
10340 }
10341
10342 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10343 number = smdi_msg->calling_st;
10344
10345
10346
10347
10348 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10349 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10350
10351 if (p->cid_signalling == CID_SIG_DTMF) {
10352 int k = 0;
10353 cs = NULL;
10354 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10355 dahdi_setlinear(p->subs[idx].dfd, 0);
10356
10357
10358
10359
10360
10361
10362 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10363 res = 4000;
10364 for (;;) {
10365 struct ast_frame *f;
10366 res = ast_waitfor(chan, res);
10367 if (res <= 0) {
10368
10369
10370
10371
10372
10373 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10374 "Exiting simple switch\n");
10375 ast_hangup(chan);
10376 goto quit;
10377 }
10378 f = ast_read(chan);
10379 if (!f)
10380 break;
10381 if (f->frametype == AST_FRAME_DTMF) {
10382 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10383 dtmfbuf[k++] = f->subclass.integer;
10384 }
10385 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10386 res = 4000;
10387 }
10388 ast_frfree(f);
10389 if (chan->_state == AST_STATE_RING ||
10390 chan->_state == AST_STATE_RINGING)
10391 break;
10392 }
10393 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10394 dtmfbuf[k] = '\0';
10395 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10396
10397 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10398 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10399 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10400
10401 if (!ast_strlen_zero(dtmfcid))
10402 number = dtmfcid;
10403 else
10404 number = NULL;
10405
10406 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10407 cs = callerid_new(p->cid_signalling);
10408 if (cs) {
10409 samples = 0;
10410 #if 1
10411 bump_gains(p);
10412 #endif
10413
10414 dahdi_setlinear(p->subs[idx].dfd, 0);
10415
10416
10417 for (;;) {
10418 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10419 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10420 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10421 callerid_free(cs);
10422 ast_hangup(chan);
10423 goto quit;
10424 }
10425 if (i & DAHDI_IOMUX_SIGEVENT) {
10426 res = dahdi_get_event(p->subs[idx].dfd);
10427 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10428 if (res == DAHDI_EVENT_NOALARM) {
10429 p->inalarm = 0;
10430 }
10431
10432 if (p->cid_signalling == CID_SIG_V23_JP) {
10433 if (res == DAHDI_EVENT_RINGBEGIN) {
10434 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10435 usleep(1);
10436 }
10437 } else {
10438 res = 0;
10439 break;
10440 }
10441 } else if (i & DAHDI_IOMUX_READ) {
10442 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10443 if (res < 0) {
10444 if (errno != ELAST) {
10445 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10446 callerid_free(cs);
10447 ast_hangup(chan);
10448 goto quit;
10449 }
10450 break;
10451 }
10452 samples += res;
10453
10454 if (p->cid_signalling == CID_SIG_V23_JP) {
10455 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10456 } else {
10457 res = callerid_feed(cs, buf, res, AST_LAW(p));
10458 }
10459 if (res < 0) {
10460
10461
10462
10463
10464 ast_log(LOG_WARNING,
10465 "Failed to decode CallerID on channel '%s'\n",
10466 chan->name);
10467 break;
10468 } else if (res)
10469 break;
10470 else if (samples > (8000 * 10))
10471 break;
10472 }
10473 }
10474 if (res == 1) {
10475 callerid_get(cs, &name, &number, &flags);
10476 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10477 }
10478
10479 if (p->cid_signalling == CID_SIG_V23_JP) {
10480 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10481 usleep(1);
10482 }
10483
10484
10485 res = 4000;
10486 for (;;) {
10487 struct ast_frame *f;
10488 res = ast_waitfor(chan, res);
10489 if (res <= 0) {
10490 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10491 "Exiting simple switch\n");
10492 ast_hangup(chan);
10493 goto quit;
10494 }
10495 if (!(f = ast_read(chan))) {
10496 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10497 ast_hangup(chan);
10498 goto quit;
10499 }
10500 ast_frfree(f);
10501 if (chan->_state == AST_STATE_RING ||
10502 chan->_state == AST_STATE_RINGING)
10503 break;
10504 }
10505
10506
10507
10508 if (p->usedistinctiveringdetection) {
10509 len = 0;
10510 distMatches = 0;
10511
10512 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10513 curRingData[receivedRingT] = 0;
10514 receivedRingT = 0;
10515 counter = 0;
10516 counter1 = 0;
10517
10518 if (strcmp(p->context,p->defcontext) != 0) {
10519 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10520 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10521 }
10522
10523 for (;;) {
10524 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10525 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10526 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10527 callerid_free(cs);
10528 ast_hangup(chan);
10529 goto quit;
10530 }
10531 if (i & DAHDI_IOMUX_SIGEVENT) {
10532 res = dahdi_get_event(p->subs[idx].dfd);
10533 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10534 if (res == DAHDI_EVENT_NOALARM) {
10535 p->inalarm = 0;
10536 }
10537 res = 0;
10538
10539
10540 curRingData[receivedRingT] = p->ringt;
10541
10542 if (p->ringt < p->ringt_base/2)
10543 break;
10544
10545
10546 if (++receivedRingT == ARRAY_LEN(curRingData))
10547 break;
10548 } else if (i & DAHDI_IOMUX_READ) {
10549 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10550 if (res < 0) {
10551 if (errno != ELAST) {
10552 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10553 callerid_free(cs);
10554 ast_hangup(chan);
10555 goto quit;
10556 }
10557 break;
10558 }
10559 if (p->ringt > 0) {
10560 if (!(--p->ringt)) {
10561 res = -1;
10562 break;
10563 }
10564 }
10565 }
10566 }
10567
10568 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10569 for (counter = 0; counter < 3; counter++) {
10570
10571
10572 distMatches = 0;
10573 for (counter1 = 0; counter1 < 3; counter1++) {
10574 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10575 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10576 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10577 curRingData[counter1]);
10578 distMatches++;
10579 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10580 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10581 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10582 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10583 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10584 distMatches++;
10585 }
10586 }
10587
10588 if (distMatches == 3) {
10589
10590 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10591 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10592 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10593 break;
10594 }
10595 }
10596 }
10597
10598 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10599 #if 1
10600 restore_gains(p);
10601 #endif
10602 } else
10603 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10604 } else {
10605 ast_log(LOG_WARNING, "Channel %s in prering "
10606 "state, but I have nothing to do. "
10607 "Terminating simple switch, should be "
10608 "restarted by the actual ring.\n",
10609 chan->name);
10610 ast_hangup(chan);
10611 goto quit;
10612 }
10613 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10614 if (p->cid_signalling == CID_SIG_DTMF) {
10615 int k = 0;
10616 cs = NULL;
10617 dahdi_setlinear(p->subs[idx].dfd, 0);
10618 res = 2000;
10619 for (;;) {
10620 struct ast_frame *f;
10621 res = ast_waitfor(chan, res);
10622 if (res <= 0) {
10623 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10624 "Exiting simple switch\n");
10625 ast_hangup(chan);
10626 goto quit;
10627 }
10628 f = ast_read(chan);
10629 if (!f) {
10630
10631 ast_hangup(chan);
10632 goto quit;
10633 }
10634 if (f->frametype == AST_FRAME_DTMF) {
10635 dtmfbuf[k++] = f->subclass.integer;
10636 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10637 res = 2000;
10638 }
10639 ast_frfree(f);
10640
10641 if (p->ringt_base == p->ringt)
10642 break;
10643 }
10644 dtmfbuf[k] = '\0';
10645 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10646
10647 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10648 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10649 dtmfcid, flags);
10650
10651 if (!ast_strlen_zero(dtmfcid))
10652 number = dtmfcid;
10653 else
10654 number = NULL;
10655
10656 } else {
10657
10658 cs = callerid_new(p->cid_signalling);
10659 if (cs) {
10660 #if 1
10661 bump_gains(p);
10662 #endif
10663 samples = 0;
10664 len = 0;
10665 distMatches = 0;
10666
10667 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10668 curRingData[receivedRingT] = 0;
10669 receivedRingT = 0;
10670 counter = 0;
10671 counter1 = 0;
10672
10673 if (strcmp(p->context,p->defcontext) != 0) {
10674 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10675 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10676 }
10677
10678
10679 dahdi_setlinear(p->subs[idx].dfd, 0);
10680 for (;;) {
10681 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10682 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10683 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10684 callerid_free(cs);
10685 ast_hangup(chan);
10686 goto quit;
10687 }
10688 if (i & DAHDI_IOMUX_SIGEVENT) {
10689 res = dahdi_get_event(p->subs[idx].dfd);
10690 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10691 if (res == DAHDI_EVENT_NOALARM) {
10692 p->inalarm = 0;
10693 }
10694
10695 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10696 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10697 p->polarity = POLARITY_IDLE;
10698 callerid_free(cs);
10699 ast_hangup(chan);
10700 goto quit;
10701 }
10702 res = 0;
10703
10704
10705 curRingData[receivedRingT] = p->ringt;
10706
10707 if (p->ringt < p->ringt_base/2)
10708 break;
10709
10710
10711 if (++receivedRingT == ARRAY_LEN(curRingData))
10712 break;
10713 } else if (i & DAHDI_IOMUX_READ) {
10714 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10715 if (res < 0) {
10716 if (errno != ELAST) {
10717 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10718 callerid_free(cs);
10719 ast_hangup(chan);
10720 goto quit;
10721 }
10722 break;
10723 }
10724 if (p->ringt > 0) {
10725 if (!(--p->ringt)) {
10726 res = -1;
10727 break;
10728 }
10729 }
10730 samples += res;
10731 res = callerid_feed(cs, buf, res, AST_LAW(p));
10732 if (res < 0) {
10733
10734
10735
10736
10737 ast_log(LOG_WARNING,
10738 "Failed to decode CallerID on channel '%s'\n",
10739 chan->name);
10740 break;
10741 } else if (res)
10742 break;
10743 else if (samples > (8000 * 10))
10744 break;
10745 }
10746 }
10747 if (res == 1) {
10748 callerid_get(cs, &name, &number, &flags);
10749 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10750 }
10751 if (distinctiveringaftercid == 1) {
10752
10753 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10754 curRingData[receivedRingT] = 0;
10755 }
10756 receivedRingT = 0;
10757 ast_verb(3, "Detecting post-CID distinctive ring\n");
10758 for (;;) {
10759 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10760 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10761 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10762 callerid_free(cs);
10763 ast_hangup(chan);
10764 goto quit;
10765 }
10766 if (i & DAHDI_IOMUX_SIGEVENT) {
10767 res = dahdi_get_event(p->subs[idx].dfd);
10768 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10769 if (res == DAHDI_EVENT_NOALARM) {
10770 p->inalarm = 0;
10771 }
10772 res = 0;
10773
10774
10775 curRingData[receivedRingT] = p->ringt;
10776
10777 if (p->ringt < p->ringt_base/2)
10778 break;
10779
10780
10781 if (++receivedRingT == ARRAY_LEN(curRingData))
10782 break;
10783 } else if (i & DAHDI_IOMUX_READ) {
10784 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10785 if (res < 0) {
10786 if (errno != ELAST) {
10787 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10788 callerid_free(cs);
10789 ast_hangup(chan);
10790 goto quit;
10791 }
10792 break;
10793 }
10794 if (p->ringt > 0) {
10795 if (!(--p->ringt)) {
10796 res = -1;
10797 break;
10798 }
10799 }
10800 }
10801 }
10802 }
10803 if (p->usedistinctiveringdetection) {
10804
10805 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10806
10807 for (counter = 0; counter < 3; counter++) {
10808
10809
10810
10811 ast_verb(3, "Checking %d,%d,%d\n",
10812 p->drings.ringnum[counter].ring[0],
10813 p->drings.ringnum[counter].ring[1],
10814 p->drings.ringnum[counter].ring[2]);
10815 distMatches = 0;
10816 for (counter1 = 0; counter1 < 3; counter1++) {
10817 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10818 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10819 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10820 curRingData[counter1]);
10821 distMatches++;
10822 }
10823 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10824 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10825 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10826 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10827 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10828 distMatches++;
10829 }
10830 }
10831 if (distMatches == 3) {
10832
10833 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10834 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10835 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10836 break;
10837 }
10838 }
10839 }
10840
10841 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10842 #if 1
10843 restore_gains(p);
10844 #endif
10845 if (res < 0) {
10846 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10847 }
10848 } else
10849 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10850 }
10851 } else
10852 cs = NULL;
10853
10854 if (number)
10855 ast_shrink_phone_number(number);
10856 ast_set_callerid(chan, number, name, number);
10857
10858 if (smdi_msg)
10859 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10860
10861 if (cs)
10862 callerid_free(cs);
10863
10864 my_handle_notify_message(chan, p, flags, -1);
10865
10866 ast_setstate(chan, AST_STATE_RING);
10867 chan->rings = 1;
10868 p->ringt = p->ringt_base;
10869 res = ast_pbx_run(chan);
10870 if (res) {
10871 ast_hangup(chan);
10872 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10873 }
10874 goto quit;
10875 default:
10876 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10877 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10878 if (res < 0)
10879 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10880 }
10881 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10882 if (res < 0)
10883 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10884 ast_hangup(chan);
10885 quit:
10886 ast_mutex_lock(&ss_thread_lock);
10887 ss_thread_count--;
10888 ast_cond_signal(&ss_thread_complete);
10889 ast_mutex_unlock(&ss_thread_lock);
10890 return NULL;
10891 }
10892
10893 struct mwi_thread_data {
10894 struct dahdi_pvt *pvt;
10895 unsigned char buf[READ_SIZE];
10896 size_t len;
10897 };
10898
10899 static int calc_energy(const unsigned char *buf, int len, format_t law)
10900 {
10901 int x;
10902 int sum = 0;
10903
10904 if (!len)
10905 return 0;
10906
10907 for (x = 0; x < len; x++)
10908 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10909
10910 return sum / len;
10911 }
10912
10913 static void *mwi_thread(void *data)
10914 {
10915 struct mwi_thread_data *mtd = data;
10916 struct callerid_state *cs;
10917 pthread_t threadid;
10918 int samples = 0;
10919 char *name, *number;
10920 int flags;
10921 int i, res;
10922 unsigned int spill_done = 0;
10923 int spill_result = -1;
10924
10925 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10926 mtd->pvt->mwimonitoractive = 0;
10927
10928 return NULL;
10929 }
10930
10931 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10932
10933 bump_gains(mtd->pvt);
10934
10935 for (;;) {
10936 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10937 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10938 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10939 goto quit;
10940 }
10941
10942 if (i & DAHDI_IOMUX_SIGEVENT) {
10943 struct ast_channel *chan;
10944
10945
10946
10947
10948 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10949
10950 switch (res) {
10951 case DAHDI_EVENT_NEONMWI_ACTIVE:
10952 case DAHDI_EVENT_NEONMWI_INACTIVE:
10953 case DAHDI_EVENT_NONE:
10954 case DAHDI_EVENT_BITSCHANGED:
10955 break;
10956 case DAHDI_EVENT_NOALARM:
10957 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10958 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10959
10960 analog_p->inalarm = 0;
10961 }
10962 mtd->pvt->inalarm = 0;
10963 handle_clear_alarms(mtd->pvt);
10964 break;
10965 case DAHDI_EVENT_ALARM:
10966 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10967 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10968
10969 analog_p->inalarm = 1;
10970 }
10971 mtd->pvt->inalarm = 1;
10972 res = get_alarms(mtd->pvt);
10973 handle_alarms(mtd->pvt, res);
10974 break;
10975 default:
10976 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
10977 callerid_free(cs);
10978
10979 restore_gains(mtd->pvt);
10980 mtd->pvt->ringt = mtd->pvt->ringt_base;
10981
10982 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10983 int result;
10984 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10985 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10986 } else {
10987 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10988 }
10989 if (result) {
10990 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10991 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10992 if (res < 0)
10993 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10994 ast_hangup(chan);
10995 goto quit;
10996 }
10997 goto quit_no_clean;
10998
10999 } else {
11000 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11001 }
11002 }
11003 } else if (i & DAHDI_IOMUX_READ) {
11004 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11005 if (errno != ELAST) {
11006 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11007 goto quit;
11008 }
11009 break;
11010 }
11011 samples += res;
11012 if (!spill_done) {
11013 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11014
11015
11016
11017
11018 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11019 break;
11020 } else if (spill_result) {
11021 spill_done = 1;
11022 }
11023 } else {
11024
11025
11026
11027 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11028 break;
11029 }
11030 if (samples > (8000 * 4))
11031 break;
11032 }
11033 }
11034
11035 if (spill_result == 1) {
11036 callerid_get(cs, &name, &number, &flags);
11037 if (flags & CID_MSGWAITING) {
11038 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11039 notify_message(mtd->pvt->mailbox, 1);
11040 } else if (flags & CID_NOMSGWAITING) {
11041 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11042 notify_message(mtd->pvt->mailbox, 0);
11043 } else {
11044 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11045 }
11046 }
11047
11048
11049 quit:
11050 callerid_free(cs);
11051
11052 restore_gains(mtd->pvt);
11053
11054 quit_no_clean:
11055 mtd->pvt->mwimonitoractive = 0;
11056
11057 ast_free(mtd);
11058
11059 return NULL;
11060 }
11061
11062
11063
11064
11065
11066
11067
11068
11069 static int mwi_send_init(struct dahdi_pvt * pvt)
11070 {
11071 int x;
11072
11073 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11074
11075 if (pvt->mwisend_rpas) {
11076 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11077 pvt->mwisendactive = 1;
11078 } else if (pvt->mwisend_fsk) {
11079 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11080 pvt->mwisendactive = 1;
11081 } else {
11082 pvt->mwisendactive = 0;
11083 return 0;
11084 }
11085 #else
11086 if (mwisend_rpas) {
11087 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11088 } else {
11089 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11090 }
11091 pvt->mwisendactive = 1;
11092 #endif
11093
11094 if (pvt->cidspill) {
11095 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11096 ast_free(pvt->cidspill);
11097 pvt->cidspill = NULL;
11098 pvt->cidpos = 0;
11099 pvt->cidlen = 0;
11100 }
11101 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11102 if (!pvt->cidspill) {
11103 pvt->mwisendactive = 0;
11104 return -1;
11105 }
11106 x = DAHDI_FLUSH_BOTH;
11107 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11108 x = 3000;
11109 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11110 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11111 if (pvt->mwisend_fsk) {
11112 #endif
11113 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11114 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11115 pvt->cidpos = 0;
11116 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11117 }
11118 #endif
11119 return 0;
11120 }
11121
11122 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11123 {
11124 struct timeval now;
11125 int res;
11126
11127
11128
11129
11130 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11131 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11132 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11133
11134 switch ( pvt->mwisend_data.mwisend_current) {
11135 case MWI_SEND_SA:
11136
11137 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11138 if (res) {
11139 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11140 goto quit;
11141 }
11142 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11143 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11144 break;
11145 case MWI_SEND_SA_WAIT:
11146 break;
11147 case MWI_SEND_PAUSE:
11148 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11149 if (pvt->mwisend_fsk) {
11150 #endif
11151 gettimeofday(&now, NULL);
11152 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11153 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11154 }
11155 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11156 } else {
11157 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11158 }
11159 #endif
11160 break;
11161 case MWI_SEND_SPILL:
11162
11163 if(0 < num_read) {
11164 if (num_read > pvt->cidlen - pvt->cidpos)
11165 num_read = pvt->cidlen - pvt->cidpos;
11166 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11167 if (res > 0) {
11168 pvt->cidpos += res;
11169 if (pvt->cidpos >= pvt->cidlen) {
11170 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11171 }
11172 } else {
11173 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11174 goto quit;
11175 }
11176 }
11177 break;
11178 case MWI_SEND_CLEANUP:
11179
11180 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11181 break;
11182 default:
11183
11184 goto quit;
11185 }
11186 }
11187
11188 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11189 if (pvt->cidspill) {
11190 ast_free(pvt->cidspill);
11191 pvt->cidspill = NULL;
11192 pvt->cidpos = 0;
11193 pvt->cidlen = 0;
11194 }
11195 pvt->mwisendactive = 0;
11196 }
11197 return 0;
11198 quit:
11199 if (pvt->cidspill) {
11200 ast_free(pvt->cidspill);
11201 pvt->cidspill = NULL;
11202 pvt->cidpos = 0;
11203 pvt->cidlen = 0;
11204 }
11205 pvt->mwisendactive = 0;
11206 return -1;
11207 }
11208
11209 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11210 {
11211 int handled = 0;
11212
11213 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11214 switch (event) {
11215 case DAHDI_EVENT_RINGEROFF:
11216 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11217 handled = 1;
11218
11219 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11220 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11221 ast_free(pvt->cidspill);
11222 pvt->cidspill = NULL;
11223 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11224 pvt->mwisendactive = 0;
11225 } else {
11226 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11227 gettimeofday(&pvt->mwisend_data.pause, NULL);
11228 }
11229 }
11230 break;
11231
11232 case DAHDI_EVENT_RINGOFFHOOK:
11233 if (pvt->cidspill) {
11234 ast_free(pvt->cidspill);
11235 pvt->cidspill = NULL;
11236 pvt->cidpos = 0;
11237 pvt->cidlen = 0;
11238 }
11239 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11240 pvt->mwisendactive = 0;
11241 break;
11242 case DAHDI_EVENT_RINGERON:
11243 case DAHDI_EVENT_HOOKCOMPLETE:
11244 break;
11245 default:
11246 break;
11247 }
11248 }
11249 return handled;
11250 }
11251
11252
11253 static int dahdi_destroy_channel_bynum(int channel)
11254 {
11255 struct dahdi_pvt *cur;
11256
11257 ast_mutex_lock(&iflock);
11258 for (cur = iflist; cur; cur = cur->next) {
11259 if (cur->channel == channel) {
11260 int x = DAHDI_FLASH;
11261
11262
11263 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11264
11265 destroy_channel(cur, 1);
11266 ast_mutex_unlock(&iflock);
11267 ast_module_unref(ast_module_info->self);
11268 return RESULT_SUCCESS;
11269 }
11270 }
11271 ast_mutex_unlock(&iflock);
11272 return RESULT_FAILURE;
11273 }
11274
11275 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11276 {
11277 int res;
11278 pthread_t threadid;
11279 struct ast_channel *chan;
11280
11281
11282
11283 switch (event) {
11284 case DAHDI_EVENT_NONE:
11285 case DAHDI_EVENT_BITSCHANGED:
11286 break;
11287 case DAHDI_EVENT_WINKFLASH:
11288 case DAHDI_EVENT_RINGOFFHOOK:
11289 if (i->inalarm) break;
11290 if (i->radio) break;
11291
11292 switch (i->sig) {
11293 case SIG_FXOLS:
11294 case SIG_FXOGS:
11295 case SIG_FXOKS:
11296 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11297 if (res && (errno == EBUSY))
11298 break;
11299
11300
11301 ast_free(i->cidspill);
11302 i->cidspill = NULL;
11303 restore_conference(i);
11304
11305 if (i->immediate) {
11306 dahdi_enable_ec(i);
11307
11308 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11309 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11310 if (!chan) {
11311 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11312 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11313 if (res < 0)
11314 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11315 }
11316 } else {
11317
11318 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11319 if (chan) {
11320 if (has_voicemail(i))
11321 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11322 else
11323 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11324 if (res < 0)
11325 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11326 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11327 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11328 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11329 if (res < 0)
11330 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11331 ast_hangup(chan);
11332 }
11333 } else
11334 ast_log(LOG_WARNING, "Unable to create channel\n");
11335 }
11336 break;
11337 case SIG_FXSLS:
11338 case SIG_FXSGS:
11339 case SIG_FXSKS:
11340 i->ringt = i->ringt_base;
11341
11342 case SIG_EMWINK:
11343 case SIG_FEATD:
11344 case SIG_FEATDMF:
11345 case SIG_FEATDMF_TA:
11346 case SIG_E911:
11347 case SIG_FGC_CAMA:
11348 case SIG_FGC_CAMAMF:
11349 case SIG_FEATB:
11350 case SIG_EM:
11351 case SIG_EM_E1:
11352 case SIG_SFWINK:
11353 case SIG_SF_FEATD:
11354 case SIG_SF_FEATDMF:
11355 case SIG_SF_FEATB:
11356 case SIG_SF:
11357
11358 if (i->cid_start == CID_START_POLARITY_IN) {
11359 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11360 } else {
11361 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11362 }
11363
11364 if (!chan) {
11365 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11366 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11367 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11368 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11369 if (res < 0) {
11370 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11371 }
11372 ast_hangup(chan);
11373 }
11374 break;
11375 default:
11376 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11377 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11378 if (res < 0)
11379 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11380 return NULL;
11381 }
11382 break;
11383 case DAHDI_EVENT_NOALARM:
11384 switch (i->sig) {
11385 #if defined(HAVE_PRI)
11386 case SIG_PRI_LIB_HANDLE_CASES:
11387 ast_mutex_lock(&i->lock);
11388 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11389 ast_mutex_unlock(&i->lock);
11390 break;
11391 #endif
11392 #if defined(HAVE_SS7)
11393 case SIG_SS7:
11394 sig_ss7_set_alarm(i->sig_pvt, 0);
11395 break;
11396 #endif
11397 default:
11398 i->inalarm = 0;
11399 break;
11400 }
11401 handle_clear_alarms(i);
11402 break;
11403 case DAHDI_EVENT_ALARM:
11404 switch (i->sig) {
11405 #if defined(HAVE_PRI)
11406 case SIG_PRI_LIB_HANDLE_CASES:
11407 ast_mutex_lock(&i->lock);
11408 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11409 ast_mutex_unlock(&i->lock);
11410 break;
11411 #endif
11412 #if defined(HAVE_SS7)
11413 case SIG_SS7:
11414 sig_ss7_set_alarm(i->sig_pvt, 1);
11415 break;
11416 #endif
11417 default:
11418 i->inalarm = 1;
11419 break;
11420 }
11421 res = get_alarms(i);
11422 handle_alarms(i, res);
11423
11424 case DAHDI_EVENT_ONHOOK:
11425 if (i->radio)
11426 break;
11427
11428 switch (i->sig) {
11429 case SIG_FXOLS:
11430 case SIG_FXOGS:
11431 case SIG_FEATD:
11432 case SIG_FEATDMF:
11433 case SIG_FEATDMF_TA:
11434 case SIG_E911:
11435 case SIG_FGC_CAMA:
11436 case SIG_FGC_CAMAMF:
11437 case SIG_FEATB:
11438 case SIG_EM:
11439 case SIG_EM_E1:
11440 case SIG_EMWINK:
11441 case SIG_SF_FEATD:
11442 case SIG_SF_FEATDMF:
11443 case SIG_SF_FEATB:
11444 case SIG_SF:
11445 case SIG_SFWINK:
11446 case SIG_FXSLS:
11447 case SIG_FXSGS:
11448 case SIG_FXSKS:
11449 case SIG_FXOKS:
11450 dahdi_disable_ec(i);
11451
11452 #ifdef ZHONE_HACK
11453 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11454 usleep(1);
11455 #endif
11456 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11457 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11458 break;
11459 case SIG_SS7:
11460 case SIG_PRI_LIB_HANDLE_CASES:
11461 dahdi_disable_ec(i);
11462 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11463 break;
11464 default:
11465 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11466 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11467 return NULL;
11468 }
11469 break;
11470 case DAHDI_EVENT_POLARITY:
11471 switch (i->sig) {
11472 case SIG_FXSLS:
11473 case SIG_FXSKS:
11474 case SIG_FXSGS:
11475
11476
11477
11478
11479 if (i->hanguponpolarityswitch)
11480 i->polarity = POLARITY_REV;
11481 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11482 i->polarity = POLARITY_REV;
11483 ast_verb(2, "Starting post polarity "
11484 "CID detection on channel %d\n",
11485 i->channel);
11486 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11487 if (!chan) {
11488 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11489 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11490 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11491 }
11492 }
11493 break;
11494 default:
11495 ast_log(LOG_WARNING, "handle_init_event detected "
11496 "polarity reversal on non-FXO (SIG_FXS) "
11497 "interface %d\n", i->channel);
11498 }
11499 break;
11500 case DAHDI_EVENT_REMOVED:
11501 ast_log(LOG_NOTICE,
11502 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11503 i->channel);
11504 return i;
11505 case DAHDI_EVENT_NEONMWI_ACTIVE:
11506 if (i->mwimonitor_neon) {
11507 notify_message(i->mailbox, 1);
11508 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11509 }
11510 break;
11511 case DAHDI_EVENT_NEONMWI_INACTIVE:
11512 if (i->mwimonitor_neon) {
11513 notify_message(i->mailbox, 0);
11514 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11515 }
11516 break;
11517 }
11518 return NULL;
11519 }
11520
11521 static void *do_monitor(void *data)
11522 {
11523 int count, res, res2, spoint, pollres=0;
11524 struct dahdi_pvt *i;
11525 struct dahdi_pvt *last = NULL;
11526 struct dahdi_pvt *doomed;
11527 time_t thispass = 0, lastpass = 0;
11528 int found;
11529 char buf[1024];
11530 struct pollfd *pfds=NULL;
11531 int lastalloc = -1;
11532
11533
11534
11535 #if 0
11536 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11537 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11538 return NULL;
11539 }
11540 ast_debug(1, "Monitor starting...\n");
11541 #endif
11542 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11543
11544 for (;;) {
11545
11546 ast_mutex_lock(&iflock);
11547 if (!pfds || (lastalloc != ifcount)) {
11548 if (pfds) {
11549 ast_free(pfds);
11550 pfds = NULL;
11551 }
11552 if (ifcount) {
11553 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11554 ast_mutex_unlock(&iflock);
11555 return NULL;
11556 }
11557 }
11558 lastalloc = ifcount;
11559 }
11560
11561
11562 count = 0;
11563 for (i = iflist; i; i = i->next) {
11564 ast_mutex_lock(&i->lock);
11565 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11566 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11567 struct analog_pvt *p = i->sig_pvt;
11568
11569 if (!p)
11570 ast_log(LOG_ERROR, "No sig_pvt?\n");
11571
11572 if (!p->owner && !p->subs[SUB_REAL].owner) {
11573
11574 pfds[count].fd = i->subs[SUB_REAL].dfd;
11575 pfds[count].events = POLLPRI;
11576 pfds[count].revents = 0;
11577
11578 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11579 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11580 pfds[count].events |= POLLIN;
11581 }
11582 count++;
11583 }
11584 } else {
11585 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11586
11587 pfds[count].fd = i->subs[SUB_REAL].dfd;
11588 pfds[count].events = POLLPRI;
11589 pfds[count].revents = 0;
11590
11591
11592 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11593 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11594 pfds[count].events |= POLLIN;
11595 }
11596 count++;
11597 }
11598 }
11599 }
11600 ast_mutex_unlock(&i->lock);
11601 }
11602
11603 ast_mutex_unlock(&iflock);
11604
11605 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11606 pthread_testcancel();
11607
11608 res = poll(pfds, count, 1000);
11609 pthread_testcancel();
11610 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11611
11612
11613 if (res < 0) {
11614 if ((errno != EAGAIN) && (errno != EINTR))
11615 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11616 continue;
11617 }
11618
11619
11620 ast_mutex_lock(&iflock);
11621 found = 0;
11622 spoint = 0;
11623 lastpass = thispass;
11624 thispass = time(NULL);
11625 doomed = NULL;
11626 for (i = iflist;; i = i->next) {
11627 if (doomed) {
11628 int res;
11629 res = dahdi_destroy_channel_bynum(doomed->channel);
11630 if (res != RESULT_SUCCESS) {
11631 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11632 }
11633 doomed = NULL;
11634 }
11635 if (!i) {
11636 break;
11637 }
11638
11639 if (thispass != lastpass) {
11640 if (!found && ((i == last) || ((i == iflist) && !last))) {
11641 last = i;
11642 if (last) {
11643 struct analog_pvt *analog_p = last->sig_pvt;
11644
11645 if (analog_p
11646 && !last->mwisendactive
11647 && (last->sig & __DAHDI_SIG_FXO)
11648 && !analog_p->fxsoffhookstate
11649 && !last->owner
11650 && !ast_strlen_zero(last->mailbox)
11651 && (thispass - analog_p->onhooktime > 3)) {
11652 res = has_voicemail(last);
11653 if (analog_p->msgstate != res) {
11654
11655 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11656 if (res2) {
11657
11658 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11659 }
11660
11661 if (mwi_send_init(last)) {
11662 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11663 }
11664 analog_p->msgstate = res;
11665 found ++;
11666 }
11667 }
11668 last = last->next;
11669 }
11670 }
11671 }
11672 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11673 if (i->radio && !i->owner)
11674 {
11675 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11676 if (res)
11677 {
11678 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11679
11680 ast_mutex_unlock(&iflock);
11681 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11682 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11683 else
11684 doomed = handle_init_event(i, res);
11685 ast_mutex_lock(&iflock);
11686 }
11687 continue;
11688 }
11689 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11690 if (pollres & POLLIN) {
11691 if (i->owner || i->subs[SUB_REAL].owner) {
11692 #ifdef HAVE_PRI
11693 if (!i->pri)
11694 #endif
11695 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11696 continue;
11697 }
11698 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11699 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11700 continue;
11701 }
11702 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11703 if (res > 0) {
11704 if (i->mwimonitor_fsk) {
11705 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11706 pthread_attr_t attr;
11707 pthread_t threadid;
11708 struct mwi_thread_data *mtd;
11709
11710 pthread_attr_init(&attr);
11711 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11712
11713 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11714 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11715 mtd->pvt = i;
11716 memcpy(mtd->buf, buf, res);
11717 mtd->len = res;
11718 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11719 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11720 ast_free(mtd);
11721 }
11722 i->mwimonitoractive = 1;
11723 }
11724 }
11725
11726 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11727 int energy;
11728 struct timeval now;
11729
11730
11731
11732 if (1 == i->dtmfcid_holdoff_state) {
11733 gettimeofday(&i->dtmfcid_delay, NULL);
11734 i->dtmfcid_holdoff_state = 2;
11735 } else if (2 == i->dtmfcid_holdoff_state) {
11736 gettimeofday(&now, NULL);
11737 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11738 i->dtmfcid_holdoff_state = 0;
11739 }
11740 } else {
11741 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11742 if (!i->mwisendactive && energy > dtmfcid_level) {
11743 pthread_t threadid;
11744 struct ast_channel *chan;
11745 ast_mutex_unlock(&iflock);
11746 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11747
11748 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11749 i->dtmfcid_holdoff_state = 1;
11750 } else {
11751 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11752 if (!chan) {
11753 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11754 } else {
11755 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11756 if (res) {
11757 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11758 } else {
11759 i->dtmfcid_holdoff_state = 1;
11760 }
11761 }
11762 }
11763 ast_mutex_lock(&iflock);
11764 }
11765 }
11766 }
11767 if (i->mwisendactive) {
11768 mwi_send_process_buffer(i, res);
11769 }
11770 } else {
11771 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11772 }
11773 }
11774 if (pollres & POLLPRI) {
11775 if (i->owner || i->subs[SUB_REAL].owner) {
11776 #ifdef HAVE_PRI
11777 if (!i->pri)
11778 #endif
11779 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11780 continue;
11781 }
11782 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11783 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11784
11785 ast_mutex_unlock(&iflock);
11786 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11787 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11788 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11789 else
11790 doomed = handle_init_event(i, res);
11791 }
11792 ast_mutex_lock(&iflock);
11793 }
11794 }
11795 }
11796 ast_mutex_unlock(&iflock);
11797 }
11798
11799 return NULL;
11800
11801 }
11802
11803 static int restart_monitor(void)
11804 {
11805
11806 if (monitor_thread == AST_PTHREADT_STOP)
11807 return 0;
11808 ast_mutex_lock(&monlock);
11809 if (monitor_thread == pthread_self()) {
11810 ast_mutex_unlock(&monlock);
11811 ast_log(LOG_WARNING, "Cannot kill myself\n");
11812 return -1;
11813 }
11814 if (monitor_thread != AST_PTHREADT_NULL) {
11815
11816 pthread_kill(monitor_thread, SIGURG);
11817 } else {
11818
11819 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11820 ast_mutex_unlock(&monlock);
11821 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11822 return -1;
11823 }
11824 }
11825 ast_mutex_unlock(&monlock);
11826 return 0;
11827 }
11828
11829 #if defined(HAVE_PRI)
11830 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11831 {
11832 int x;
11833 int trunkgroup;
11834
11835 trunkgroup = pris[*span].mastertrunkgroup;
11836 if (trunkgroup) {
11837
11838 for (x = 0; x < NUM_SPANS; x++) {
11839 if (pris[x].pri.trunkgroup == trunkgroup) {
11840 *span = x;
11841 return 0;
11842 }
11843 }
11844 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11845 *span = -1;
11846 } else {
11847 if (pris[*span].pri.trunkgroup) {
11848 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);
11849 *span = -1;
11850 } else if (pris[*span].mastertrunkgroup) {
11851 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11852 *span = -1;
11853 } else {
11854 if (si->totalchans == 31) {
11855
11856 pris[*span].dchannels[0] = 16 + offset;
11857 } else if (si->totalchans == 24) {
11858
11859 pris[*span].dchannels[0] = 24 + offset;
11860 } else if (si->totalchans == 3) {
11861
11862 pris[*span].dchannels[0] = 3 + offset;
11863 } else {
11864 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);
11865 *span = -1;
11866 return 0;
11867 }
11868 pris[*span].pri.span = *span + 1;
11869 }
11870 }
11871 return 0;
11872 }
11873 #endif
11874
11875 #if defined(HAVE_PRI)
11876 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11877 {
11878 struct dahdi_spaninfo si;
11879 struct dahdi_params p;
11880 int fd;
11881 int span;
11882 int ospan=0;
11883 int x,y;
11884 for (x = 0; x < NUM_SPANS; x++) {
11885 if (pris[x].pri.trunkgroup == trunkgroup) {
11886 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11887 return -1;
11888 }
11889 }
11890 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11891 if (!channels[y])
11892 break;
11893 memset(&si, 0, sizeof(si));
11894 memset(&p, 0, sizeof(p));
11895 fd = open("/dev/dahdi/channel", O_RDWR);
11896 if (fd < 0) {
11897 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11898 return -1;
11899 }
11900 x = channels[y];
11901 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11902 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11903 close(fd);
11904 return -1;
11905 }
11906 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11907 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11908 return -1;
11909 }
11910 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11911 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11912 close(fd);
11913 return -1;
11914 }
11915 span = p.spanno - 1;
11916 if (pris[span].pri.trunkgroup) {
11917 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11918 close(fd);
11919 return -1;
11920 }
11921 if (pris[span].pri.pvts[0]) {
11922 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11923 close(fd);
11924 return -1;
11925 }
11926 if (!y) {
11927 pris[span].pri.trunkgroup = trunkgroup;
11928 ospan = span;
11929 }
11930 pris[ospan].dchannels[y] = channels[y];
11931 pris[span].pri.span = span + 1;
11932 close(fd);
11933 }
11934 return 0;
11935 }
11936 #endif
11937
11938 #if defined(HAVE_PRI)
11939 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11940 {
11941 if (pris[span].mastertrunkgroup) {
11942 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);
11943 return -1;
11944 }
11945 pris[span].mastertrunkgroup = trunkgroup;
11946 pris[span].prilogicalspan = logicalspan;
11947 return 0;
11948 }
11949 #endif
11950
11951 #if defined(HAVE_SS7)
11952 static unsigned int parse_pointcode(const char *pcstring)
11953 {
11954 unsigned int code1, code2, code3;
11955 int numvals;
11956
11957 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11958 if (numvals == 1)
11959 return code1;
11960 if (numvals == 3)
11961 return (code1 << 16) | (code2 << 8) | code3;
11962
11963 return 0;
11964 }
11965 #endif
11966
11967 #if defined(HAVE_SS7)
11968 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11969 {
11970 if ((linkset < 0) || (linkset >= NUM_SPANS))
11971 return NULL;
11972 else
11973 return &linksets[linkset - 1];
11974 }
11975 #endif
11976
11977 #ifdef HAVE_OPENR2
11978 static void dahdi_r2_destroy_links(void)
11979 {
11980 int i = 0;
11981 if (!r2links) {
11982 return;
11983 }
11984 for (; i < r2links_count; i++) {
11985 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11986 pthread_cancel(r2links[i]->r2master);
11987 pthread_join(r2links[i]->r2master, NULL);
11988 openr2_context_delete(r2links[i]->protocol_context);
11989 }
11990 ast_free(r2links[i]);
11991 }
11992 ast_free(r2links);
11993 r2links = NULL;
11994 r2links_count = 0;
11995 }
11996
11997 #define R2_LINK_CAPACITY 10
11998 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11999 {
12000 struct dahdi_mfcr2 *new_r2link = NULL;
12001 struct dahdi_mfcr2 **new_r2links = NULL;
12002
12003
12004 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12005 new_r2link = ast_calloc(1, sizeof(**r2links));
12006 if (!new_r2link) {
12007 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12008 return NULL;
12009 }
12010 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12011 if (!new_r2links) {
12012 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12013 ast_free(new_r2link);
12014 return NULL;
12015 }
12016 r2links = new_r2links;
12017 new_r2link->r2master = AST_PTHREADT_NULL;
12018 r2links[r2links_count] = new_r2link;
12019 r2links_count++;
12020 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12021 }
12022 return r2links[r2links_count - 1];
12023 }
12024
12025 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12026 {
12027 char tmplogdir[] = "/tmp";
12028 char logdir[OR2_MAX_PATH];
12029 int threshold = 0;
12030 int snres = 0;
12031 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12032 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12033 conf->mfcr2.max_dnis);
12034 if (!r2_link->protocol_context) {
12035 return -1;
12036 }
12037 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12038 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12039 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12040 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12041 #endif
12042 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12043 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12044 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12045 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12046 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12047 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12048 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12049 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12050 }
12051 } else {
12052 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12053 if (snres >= sizeof(logdir)) {
12054 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12055 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12056 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12057 }
12058 } else {
12059 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12060 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12061 }
12062 }
12063 }
12064 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12065 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12066 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12067 }
12068 }
12069 r2_link->monitored_count = 0;
12070 return 0;
12071 }
12072 #endif
12073
12074
12075
12076
12077
12078
12079 static int sigtype_to_signalling(int sigtype)
12080 {
12081 return sigtype;
12082 }
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12097 {
12098 struct stat stbuf;
12099 int num;
12100
12101 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12102 if (stat(path, &stbuf) < 0) {
12103 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12104 return -errno;
12105 }
12106 if (!S_ISCHR(stbuf.st_mode)) {
12107 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12108 return -EINVAL;
12109 }
12110 num = minor(stbuf.st_rdev);
12111 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12112 return num;
12113
12114 }
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12131 {
12132
12133 struct dahdi_pvt *tmp;
12134 char fn[80];
12135 struct dahdi_bufferinfo bi;
12136
12137 int res;
12138 #if defined(HAVE_PRI)
12139 int span = 0;
12140 #endif
12141 int here = 0;
12142 int x;
12143 struct analog_pvt *analog_p = NULL;
12144 struct dahdi_params p;
12145 #if defined(HAVE_PRI)
12146 struct dahdi_spaninfo si;
12147 struct sig_pri_chan *pri_chan = NULL;
12148 #endif
12149 #if defined(HAVE_SS7)
12150 struct sig_ss7_chan *ss7_chan = NULL;
12151 #endif
12152
12153
12154 for (tmp = iflist; tmp; tmp = tmp->next) {
12155 if (!tmp->destroy) {
12156 if (tmp->channel == channel) {
12157
12158 here = 1;
12159 break;
12160 }
12161 if (tmp->channel > channel) {
12162
12163 tmp = NULL;
12164 break;
12165 }
12166 }
12167 }
12168
12169 if (!here && reloading != 1) {
12170 tmp = ast_calloc(1, sizeof(*tmp));
12171 if (!tmp) {
12172 return NULL;
12173 }
12174 tmp->cc_params = ast_cc_config_params_init();
12175 if (!tmp->cc_params) {
12176 ast_free(tmp);
12177 return NULL;
12178 }
12179 ast_mutex_init(&tmp->lock);
12180 ifcount++;
12181 for (x = 0; x < 3; x++)
12182 tmp->subs[x].dfd = -1;
12183 tmp->channel = channel;
12184 tmp->priindication_oob = conf->chan.priindication_oob;
12185 }
12186
12187 if (tmp) {
12188 int chan_sig = conf->chan.sig;
12189
12190
12191 if (reloading && tmp->vars) {
12192 ast_variables_destroy(tmp->vars);
12193 tmp->vars = NULL;
12194 }
12195
12196
12197 if (!here) {
12198
12199 if ((channel != CHAN_PSEUDO)) {
12200 int count = 0;
12201
12202 snprintf(fn, sizeof(fn), "%d", channel);
12203
12204 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12205 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12206 usleep(1);
12207 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12208 count++;
12209 }
12210
12211 if (tmp->subs[SUB_REAL].dfd < 0) {
12212 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);
12213 destroy_dahdi_pvt(tmp);
12214 return NULL;
12215 }
12216 memset(&p, 0, sizeof(p));
12217 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12218 if (res < 0) {
12219 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12220 destroy_dahdi_pvt(tmp);
12221 return NULL;
12222 }
12223 if (conf->is_sig_auto)
12224 chan_sig = sigtype_to_signalling(p.sigtype);
12225 if (p.sigtype != (chan_sig & 0x3ffff)) {
12226 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));
12227 destroy_dahdi_pvt(tmp);
12228 return NULL;
12229 }
12230 tmp->law_default = p.curlaw;
12231 tmp->law = p.curlaw;
12232 tmp->span = p.spanno;
12233 #if defined(HAVE_PRI)
12234 span = p.spanno - 1;
12235 #endif
12236 } else {
12237 chan_sig = 0;
12238 }
12239 tmp->sig = chan_sig;
12240 tmp->outsigmod = conf->chan.outsigmod;
12241
12242 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12243 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12244 if (!analog_p) {
12245 destroy_dahdi_pvt(tmp);
12246 return NULL;
12247 }
12248 tmp->sig_pvt = analog_p;
12249 }
12250 #if defined(HAVE_SS7)
12251 if (chan_sig == SIG_SS7) {
12252 struct dahdi_ss7 *ss7;
12253 int clear = 0;
12254
12255 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12256 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12257 destroy_dahdi_pvt(tmp);
12258 return NULL;
12259 }
12260
12261 ss7 = ss7_resolve_linkset(cur_linkset);
12262 if (!ss7) {
12263 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12264 destroy_dahdi_pvt(tmp);
12265 return NULL;
12266 }
12267 ss7->ss7.span = cur_linkset;
12268 if (cur_cicbeginswith < 0) {
12269 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12270 destroy_dahdi_pvt(tmp);
12271 return NULL;
12272 }
12273 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12274 if (!ss7_chan) {
12275 destroy_dahdi_pvt(tmp);
12276 return NULL;
12277 }
12278 tmp->sig_pvt = ss7_chan;
12279 tmp->ss7 = &ss7->ss7;
12280
12281 ss7_chan->channel = tmp->channel;
12282 ss7_chan->cic = cur_cicbeginswith++;
12283
12284
12285 ss7_chan->dpc = cur_defaultdpc;
12286
12287 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12288
12289 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12290 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12291 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12292 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12293
12294 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12295 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12296 }
12297 #endif
12298 #ifdef HAVE_OPENR2
12299 if (chan_sig == SIG_MFCR2) {
12300 struct dahdi_mfcr2 *r2_link;
12301 r2_link = dahdi_r2_get_link();
12302 if (!r2_link) {
12303 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12304 destroy_dahdi_pvt(tmp);
12305 return NULL;
12306 }
12307 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12308 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12309 destroy_dahdi_pvt(tmp);
12310 return NULL;
12311 }
12312 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12313 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12314 destroy_dahdi_pvt(tmp);
12315 return NULL;
12316 }
12317 r2_link->pvts[r2_link->numchans++] = tmp;
12318 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12319 tmp->subs[SUB_REAL].dfd,
12320 NULL, NULL);
12321 if (!tmp->r2chan) {
12322 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12323 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12324 destroy_dahdi_pvt(tmp);
12325 return NULL;
12326 }
12327 tmp->mfcr2 = r2_link;
12328 if (conf->mfcr2.call_files) {
12329 openr2_chan_enable_call_files(tmp->r2chan);
12330 }
12331 openr2_chan_set_client_data(tmp->r2chan, tmp);
12332
12333 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12334 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12335 tmp->mfcr2_category = conf->mfcr2.category;
12336 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12337 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12338 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12339 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12340 tmp->mfcr2call = 0;
12341 tmp->mfcr2_dnis_index = 0;
12342 tmp->mfcr2_ani_index = 0;
12343 r2_link->monitored_count++;
12344 }
12345 #endif
12346 #ifdef HAVE_PRI
12347 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12348 int offset;
12349 int matchesdchan;
12350 int x,y;
12351 int myswitchtype = 0;
12352
12353 offset = 0;
12354 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12355 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12356 destroy_dahdi_pvt(tmp);
12357 return NULL;
12358 }
12359 if (span >= NUM_SPANS) {
12360 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12361 destroy_dahdi_pvt(tmp);
12362 return NULL;
12363 } else {
12364 si.spanno = 0;
12365 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12366 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12367 destroy_dahdi_pvt(tmp);
12368 return NULL;
12369 }
12370
12371 tmp->logicalspan = pris[span].prilogicalspan;
12372 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12373 if (span < 0) {
12374 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12375 destroy_dahdi_pvt(tmp);
12376 return NULL;
12377 }
12378 myswitchtype = conf->pri.pri.switchtype;
12379
12380 matchesdchan=0;
12381 for (x = 0; x < NUM_SPANS; x++) {
12382 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12383 if (pris[x].dchannels[y] == tmp->channel) {
12384 matchesdchan = 1;
12385 break;
12386 }
12387 }
12388 }
12389 if (!matchesdchan) {
12390 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12391 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12392 destroy_dahdi_pvt(tmp);
12393 return NULL;
12394 }
12395 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12396 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12397 destroy_dahdi_pvt(tmp);
12398 return NULL;
12399 }
12400 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12401 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));
12402 destroy_dahdi_pvt(tmp);
12403 return NULL;
12404 }
12405 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12406 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12407 destroy_dahdi_pvt(tmp);
12408 return NULL;
12409 }
12410 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12411 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12412 destroy_dahdi_pvt(tmp);
12413 return NULL;
12414 }
12415 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12416 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12417 destroy_dahdi_pvt(tmp);
12418 return NULL;
12419 }
12420 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12421 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12422 destroy_dahdi_pvt(tmp);
12423 return NULL;
12424 }
12425 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12426 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12427 pris[span].pri.trunkgroup);
12428 destroy_dahdi_pvt(tmp);
12429 return NULL;
12430 }
12431
12432 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12433 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12434 if (!pri_chan) {
12435 destroy_dahdi_pvt(tmp);
12436 return NULL;
12437 }
12438 tmp->sig_pvt = pri_chan;
12439 tmp->pri = &pris[span].pri;
12440
12441 tmp->priexclusive = conf->chan.priexclusive;
12442
12443 if (!tmp->pri->cc_params) {
12444 tmp->pri->cc_params = ast_cc_config_params_init();
12445 if (!tmp->pri->cc_params) {
12446 destroy_dahdi_pvt(tmp);
12447 return NULL;
12448 }
12449 }
12450 ast_cc_copy_config_params(tmp->pri->cc_params,
12451 conf->chan.cc_params);
12452
12453 pris[span].pri.sig = chan_sig;
12454 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12455 pris[span].pri.switchtype = myswitchtype;
12456 pris[span].pri.nsf = conf->pri.pri.nsf;
12457 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12458 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12459 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12460 pris[span].pri.minunused = conf->pri.pri.minunused;
12461 pris[span].pri.minidle = conf->pri.pri.minidle;
12462 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12463 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12464 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12465 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12466 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12467 #endif
12468 #ifdef HAVE_PRI_INBANDDISCONNECT
12469 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12470 #endif
12471 #if defined(HAVE_PRI_CALL_HOLD)
12472 pris[span].pri.hold_disconnect_transfer =
12473 conf->pri.pri.hold_disconnect_transfer;
12474 #endif
12475 #if defined(HAVE_PRI_CCSS)
12476 pris[span].pri.cc_ptmp_recall_mode =
12477 conf->pri.pri.cc_ptmp_recall_mode;
12478 pris[span].pri.cc_qsig_signaling_link_req =
12479 conf->pri.pri.cc_qsig_signaling_link_req;
12480 pris[span].pri.cc_qsig_signaling_link_rsp =
12481 conf->pri.pri.cc_qsig_signaling_link_rsp;
12482 #endif
12483 #if defined(HAVE_PRI_CALL_WAITING)
12484 pris[span].pri.max_call_waiting_calls =
12485 conf->pri.pri.max_call_waiting_calls;
12486 pris[span].pri.allow_call_waiting_calls =
12487 conf->pri.pri.allow_call_waiting_calls;
12488 #endif
12489 pris[span].pri.transfer = conf->chan.transfer;
12490 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12491 #if defined(HAVE_PRI_L2_PERSISTENCE)
12492 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12493 #endif
12494 #if defined(HAVE_PRI_AOC_EVENTS)
12495 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12496 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12497 #endif
12498 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12499 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12500 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12501 #if defined(HAVE_PRI_MWI)
12502 ast_copy_string(pris[span].pri.mwi_mailboxes,
12503 conf->pri.pri.mwi_mailboxes,
12504 sizeof(pris[span].pri.mwi_mailboxes));
12505 #endif
12506 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12507 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12508 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12509 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12510 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12511 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12512 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12513 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12514
12515 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12516 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12517 }
12518
12519 #if defined(HAVE_PRI_CALL_WAITING)
12520
12521 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12522 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12523 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12524 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12525 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12526 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12527 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12528 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12529 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12530 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12531 #endif
12532 } else {
12533 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12534 destroy_dahdi_pvt(tmp);
12535 return NULL;
12536 }
12537 }
12538 }
12539 #endif
12540 } else {
12541
12542 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));
12543 chan_sig = tmp->sig;
12544 if (tmp->subs[SUB_REAL].dfd > -1) {
12545 memset(&p, 0, sizeof(p));
12546 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12547 }
12548 }
12549
12550 switch (chan_sig) {
12551 case SIG_FXSKS:
12552 case SIG_FXSLS:
12553 case SIG_EM:
12554 case SIG_EM_E1:
12555 case SIG_EMWINK:
12556 case SIG_FEATD:
12557 case SIG_FEATDMF:
12558 case SIG_FEATDMF_TA:
12559 case SIG_FEATB:
12560 case SIG_E911:
12561 case SIG_SF:
12562 case SIG_SFWINK:
12563 case SIG_FGC_CAMA:
12564 case SIG_FGC_CAMAMF:
12565 case SIG_SF_FEATD:
12566 case SIG_SF_FEATDMF:
12567 case SIG_SF_FEATB:
12568 p.starttime = 250;
12569 break;
12570 }
12571
12572 if (tmp->radio) {
12573
12574 p.channo = channel;
12575 p.rxwinktime = 1;
12576 p.rxflashtime = 1;
12577 p.starttime = 1;
12578 p.debouncetime = 5;
12579 } else {
12580 p.channo = channel;
12581
12582 if (conf->timing.prewinktime >= 0)
12583 p.prewinktime = conf->timing.prewinktime;
12584 if (conf->timing.preflashtime >= 0)
12585 p.preflashtime = conf->timing.preflashtime;
12586 if (conf->timing.winktime >= 0)
12587 p.winktime = conf->timing.winktime;
12588 if (conf->timing.flashtime >= 0)
12589 p.flashtime = conf->timing.flashtime;
12590 if (conf->timing.starttime >= 0)
12591 p.starttime = conf->timing.starttime;
12592 if (conf->timing.rxwinktime >= 0)
12593 p.rxwinktime = conf->timing.rxwinktime;
12594 if (conf->timing.rxflashtime >= 0)
12595 p.rxflashtime = conf->timing.rxflashtime;
12596 if (conf->timing.debouncetime >= 0)
12597 p.debouncetime = conf->timing.debouncetime;
12598 }
12599
12600
12601 if (tmp->subs[SUB_REAL].dfd >= 0)
12602 {
12603 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12604 if (res < 0) {
12605 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12606 destroy_dahdi_pvt(tmp);
12607 return NULL;
12608 }
12609 }
12610 #if 1
12611 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12612 memset(&bi, 0, sizeof(bi));
12613 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12614 if (!res) {
12615 bi.txbufpolicy = conf->chan.buf_policy;
12616 bi.rxbufpolicy = conf->chan.buf_policy;
12617 bi.numbufs = conf->chan.buf_no;
12618 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12619 if (res < 0) {
12620 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12621 }
12622 } else {
12623 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12624 }
12625 tmp->buf_policy = conf->chan.buf_policy;
12626 tmp->buf_no = conf->chan.buf_no;
12627 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12628 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12629 tmp->faxbuf_no = conf->chan.faxbuf_no;
12630
12631
12632
12633
12634 tmp->bufsize = bi.bufsize;
12635 }
12636 #endif
12637 tmp->immediate = conf->chan.immediate;
12638 tmp->transfertobusy = conf->chan.transfertobusy;
12639 if (chan_sig & __DAHDI_SIG_FXS) {
12640 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12641 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12642 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12643 }
12644 tmp->ringt_base = ringt_base;
12645 tmp->firstradio = 0;
12646 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12647 tmp->permcallwaiting = conf->chan.callwaiting;
12648 else
12649 tmp->permcallwaiting = 0;
12650
12651 tmp->destroy = 0;
12652 tmp->drings = conf->chan.drings;
12653
12654
12655 if (tmp->drings.ringnum[0].range == 0)
12656 tmp->drings.ringnum[0].range = 10;
12657 if (tmp->drings.ringnum[1].range == 0)
12658 tmp->drings.ringnum[1].range = 10;
12659 if (tmp->drings.ringnum[2].range == 0)
12660 tmp->drings.ringnum[2].range = 10;
12661
12662 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12663 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12664 tmp->threewaycalling = conf->chan.threewaycalling;
12665 tmp->adsi = conf->chan.adsi;
12666 tmp->use_smdi = conf->chan.use_smdi;
12667 tmp->permhidecallerid = conf->chan.hidecallerid;
12668 tmp->hidecalleridname = conf->chan.hidecalleridname;
12669 tmp->callreturn = conf->chan.callreturn;
12670 tmp->echocancel = conf->chan.echocancel;
12671 tmp->echotraining = conf->chan.echotraining;
12672 tmp->pulse = conf->chan.pulse;
12673 if (tmp->echocancel.head.tap_length) {
12674 tmp->echocanbridged = conf->chan.echocanbridged;
12675 } else {
12676 if (conf->chan.echocanbridged)
12677 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12678 tmp->echocanbridged = 0;
12679 }
12680 tmp->busydetect = conf->chan.busydetect;
12681 tmp->busycount = conf->chan.busycount;
12682 tmp->busy_tonelength = conf->chan.busy_tonelength;
12683 tmp->busy_quietlength = conf->chan.busy_quietlength;
12684 tmp->callprogress = conf->chan.callprogress;
12685 tmp->waitfordialtone = conf->chan.waitfordialtone;
12686 tmp->cancallforward = conf->chan.cancallforward;
12687 tmp->dtmfrelax = conf->chan.dtmfrelax;
12688 tmp->callwaiting = tmp->permcallwaiting;
12689 tmp->hidecallerid = tmp->permhidecallerid;
12690 tmp->channel = channel;
12691 tmp->stripmsd = conf->chan.stripmsd;
12692 tmp->use_callerid = conf->chan.use_callerid;
12693 tmp->cid_signalling = conf->chan.cid_signalling;
12694 tmp->cid_start = conf->chan.cid_start;
12695 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12696 tmp->restrictcid = conf->chan.restrictcid;
12697 tmp->use_callingpres = conf->chan.use_callingpres;
12698 if (tmp->usedistinctiveringdetection) {
12699 if (!tmp->use_callerid) {
12700 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12701 tmp->use_callerid = 1;
12702 }
12703 }
12704
12705 if (tmp->cid_signalling == CID_SIG_SMDI) {
12706 if (!tmp->use_smdi) {
12707 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12708 tmp->use_smdi = 1;
12709 }
12710 }
12711 if (tmp->use_smdi) {
12712 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12713 if (!(tmp->smdi_iface)) {
12714 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12715 tmp->use_smdi = 0;
12716 }
12717 }
12718
12719 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12720 tmp->amaflags = conf->chan.amaflags;
12721 if (!here) {
12722 tmp->confno = -1;
12723 tmp->propconfno = -1;
12724 }
12725 tmp->canpark = conf->chan.canpark;
12726 tmp->transfer = conf->chan.transfer;
12727 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12728 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12729 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12730 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12731 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12732 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12733 tmp->cid_ton = 0;
12734 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12735 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12736 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12737 } else {
12738 tmp->cid_num[0] = '\0';
12739 tmp->cid_name[0] = '\0';
12740 }
12741 #if defined(HAVE_PRI)
12742 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12743 tmp->cid_tag[0] = '\0';
12744 } else
12745 #endif
12746 {
12747 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12748 }
12749 tmp->cid_subaddr[0] = '\0';
12750 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12751 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12752 char *mailbox, *context;
12753 mailbox = context = ast_strdupa(tmp->mailbox);
12754 strsep(&context, "@");
12755 if (ast_strlen_zero(context))
12756 context = "default";
12757 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12758 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12759 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12760 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12761 AST_EVENT_IE_END);
12762 }
12763 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12764 tmp->mwisend_setting = conf->chan.mwisend_setting;
12765 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12766 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12767 #endif
12768
12769 tmp->group = conf->chan.group;
12770 tmp->callgroup = conf->chan.callgroup;
12771 tmp->pickupgroup= conf->chan.pickupgroup;
12772 if (conf->chan.vars) {
12773 struct ast_variable *v, *tmpvar;
12774 for (v = conf->chan.vars ; v ; v = v->next) {
12775 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12776 tmpvar->next = tmp->vars;
12777 tmp->vars = tmpvar;
12778 }
12779 }
12780 }
12781 tmp->cid_rxgain = conf->chan.cid_rxgain;
12782 tmp->rxgain = conf->chan.rxgain;
12783 tmp->txgain = conf->chan.txgain;
12784 tmp->txdrc = conf->chan.txdrc;
12785 tmp->rxdrc = conf->chan.rxdrc;
12786 tmp->tonezone = conf->chan.tonezone;
12787 if (tmp->subs[SUB_REAL].dfd > -1) {
12788 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12789 if (tmp->dsp)
12790 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12791 update_conf(tmp);
12792 if (!here) {
12793 switch (chan_sig) {
12794 case SIG_PRI_LIB_HANDLE_CASES:
12795 case SIG_SS7:
12796 case SIG_MFCR2:
12797 break;
12798 default:
12799
12800 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12801 break;
12802 }
12803 }
12804 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12805 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12806
12807 switch (tmp->sig) {
12808 #ifdef HAVE_PRI
12809 case SIG_PRI_LIB_HANDLE_CASES:
12810 sig_pri_set_alarm(tmp->sig_pvt, 1);
12811 break;
12812 #endif
12813 #if defined(HAVE_SS7)
12814 case SIG_SS7:
12815 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12816 break;
12817 #endif
12818 default:
12819
12820 analog_p = tmp->sig_pvt;
12821 if (analog_p) {
12822 analog_p->inalarm = 1;
12823 }
12824 tmp->inalarm = 1;
12825 break;
12826 }
12827 handle_alarms(tmp, res);
12828 }
12829 }
12830
12831 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12832 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12833 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12834 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12835 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12836
12837 if (!here) {
12838 tmp->locallyblocked = 0;
12839 tmp->remotelyblocked = 0;
12840 switch (tmp->sig) {
12841 #if defined(HAVE_PRI)
12842 case SIG_PRI_LIB_HANDLE_CASES:
12843 tmp->inservice = 1;
12844 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12845 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12846 if (chan_sig == SIG_PRI) {
12847 char db_chan_name[20];
12848 char db_answer[5];
12849
12850
12851
12852
12853
12854 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12855 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12856 unsigned *why;
12857
12858 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12859 if (tmp->pri->enable_service_message_support) {
12860 char state;
12861
12862 sscanf(db_answer, "%1c:%30u", &state, why);
12863
12864
12865 *why &= (SRVST_NEAREND | SRVST_FAREND);
12866 }
12867 if (!*why) {
12868 ast_db_del(db_chan_name, SRVST_DBKEY);
12869 }
12870 }
12871 }
12872 #endif
12873 break;
12874 #endif
12875 #if defined(HAVE_SS7)
12876 case SIG_SS7:
12877 tmp->inservice = 0;
12878 break;
12879 #endif
12880 default:
12881
12882 tmp->inservice = 1;
12883 break;
12884 }
12885 }
12886
12887 switch (tmp->sig) {
12888 #if defined(HAVE_PRI)
12889 case SIG_PRI_LIB_HANDLE_CASES:
12890 if (pri_chan) {
12891 pri_chan->channel = tmp->channel;
12892 pri_chan->hidecallerid = tmp->hidecallerid;
12893 pri_chan->hidecalleridname = tmp->hidecalleridname;
12894 pri_chan->immediate = tmp->immediate;
12895 pri_chan->inalarm = tmp->inalarm;
12896 pri_chan->priexclusive = tmp->priexclusive;
12897 pri_chan->priindication_oob = tmp->priindication_oob;
12898 pri_chan->use_callerid = tmp->use_callerid;
12899 pri_chan->use_callingpres = tmp->use_callingpres;
12900 ast_copy_string(pri_chan->context, tmp->context,
12901 sizeof(pri_chan->context));
12902 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12903 sizeof(pri_chan->mohinterpret));
12904 pri_chan->stripmsd = tmp->stripmsd;
12905 }
12906 break;
12907 #endif
12908 #if defined(HAVE_SS7)
12909 case SIG_SS7:
12910 if (ss7_chan) {
12911 ss7_chan->inalarm = tmp->inalarm;
12912
12913 ss7_chan->stripmsd = tmp->stripmsd;
12914 ss7_chan->hidecallerid = tmp->hidecallerid;
12915 ss7_chan->use_callerid = tmp->use_callerid;
12916 ss7_chan->use_callingpres = tmp->use_callingpres;
12917 ss7_chan->immediate = tmp->immediate;
12918 ss7_chan->locallyblocked = tmp->locallyblocked;
12919 ss7_chan->remotelyblocked = tmp->remotelyblocked;
12920 ast_copy_string(ss7_chan->context, tmp->context,
12921 sizeof(ss7_chan->context));
12922 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12923 sizeof(ss7_chan->mohinterpret));
12924 }
12925 break;
12926 #endif
12927 default:
12928
12929 analog_p = tmp->sig_pvt;
12930 if (analog_p) {
12931 analog_p->channel = tmp->channel;
12932 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12933 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12934 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12935 analog_p->permcallwaiting = conf->chan.callwaiting;
12936 analog_p->callreturn = conf->chan.callreturn;
12937 analog_p->cancallforward = conf->chan.cancallforward;
12938 analog_p->canpark = conf->chan.canpark;
12939 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12940 analog_p->immediate = conf->chan.immediate;
12941 analog_p->permhidecallerid = conf->chan.permhidecallerid;
12942 analog_p->pulse = conf->chan.pulse;
12943 analog_p->threewaycalling = conf->chan.threewaycalling;
12944 analog_p->transfer = conf->chan.transfer;
12945 analog_p->transfertobusy = conf->chan.transfertobusy;
12946 analog_p->use_callerid = tmp->use_callerid;
12947 analog_p->use_smdi = tmp->use_smdi;
12948 analog_p->smdi_iface = tmp->smdi_iface;
12949 analog_p->outsigmod = ANALOG_SIG_NONE;
12950 analog_p->echotraining = conf->chan.echotraining;
12951 analog_p->cid_signalling = conf->chan.cid_signalling;
12952 analog_p->stripmsd = conf->chan.stripmsd;
12953 switch (conf->chan.cid_start) {
12954 case CID_START_POLARITY:
12955 analog_p->cid_start = ANALOG_CID_START_POLARITY;
12956 break;
12957 case CID_START_POLARITY_IN:
12958 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12959 break;
12960 case CID_START_DTMF_NOALERT:
12961 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12962 break;
12963 default:
12964 analog_p->cid_start = ANALOG_CID_START_RING;
12965 break;
12966 }
12967 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12968 analog_p->ringt = conf->chan.ringt;
12969 analog_p->ringt_base = ringt_base;
12970 analog_p->chan_tech = &dahdi_tech;
12971 analog_p->onhooktime = time(NULL);
12972 if (chan_sig & __DAHDI_SIG_FXO) {
12973 memset(&p, 0, sizeof(p));
12974 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12975 if (!res) {
12976 analog_p->fxsoffhookstate = p.rxisoffhook;
12977 }
12978 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12979 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12980 #endif
12981 }
12982 analog_p->msgstate = -1;
12983
12984 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12985 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12986 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12987
12988 analog_config_complete(analog_p);
12989 }
12990 break;
12991 }
12992 #if defined(HAVE_PRI)
12993 if (tmp->channel == CHAN_PSEUDO) {
12994
12995
12996
12997
12998 dahdi_pseudo_parms.buf_no = tmp->buf_no;
12999 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13000 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13001 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13002 }
13003 #endif
13004 }
13005 if (tmp && !here) {
13006
13007 dahdi_iflist_insert(tmp);
13008 }
13009 return tmp;
13010 }
13011
13012 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13013 {
13014 #if defined(HAVE_PRI)
13015 if (0 < span) {
13016
13017 if (!p->pri || p->pri->span != span) {
13018 return 0;
13019 }
13020 if (!groupmatch && channelmatch == -1) {
13021
13022 *groupmatched = 1;
13023 return 1;
13024 }
13025 }
13026 #endif
13027
13028 if (groupmatch) {
13029 if ((p->group & groupmatch) != groupmatch)
13030
13031 return 0;
13032 *groupmatched = 1;
13033 }
13034
13035 if (channelmatch != -1) {
13036 if (p->channel != channelmatch)
13037
13038 return 0;
13039 *channelmatched = 1;
13040 }
13041
13042 return 1;
13043 }
13044
13045 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13046 {
13047 struct dahdi_pvt *p = *pvt;
13048
13049 if (p->inalarm)
13050 return 0;
13051
13052 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13053 return analog_available(p->sig_pvt);
13054
13055 switch (p->sig) {
13056 #if defined(HAVE_PRI)
13057 case SIG_PRI_LIB_HANDLE_CASES:
13058 {
13059 struct sig_pri_chan *pvt_chan;
13060 int res;
13061
13062 pvt_chan = p->sig_pvt;
13063 res = sig_pri_available(&pvt_chan, is_specific_channel);
13064 *pvt = pvt_chan->chan_pvt;
13065 return res;
13066 }
13067 #endif
13068 #if defined(HAVE_SS7)
13069 case SIG_SS7:
13070 return sig_ss7_available(p->sig_pvt);
13071 #endif
13072 default:
13073 break;
13074 }
13075
13076 if (p->locallyblocked || p->remotelyblocked) {
13077 return 0;
13078 }
13079
13080
13081 if (!p->owner) {
13082 #ifdef HAVE_OPENR2
13083
13084 if (p->mfcr2) {
13085 if (p->mfcr2call) {
13086 return 0;
13087 } else {
13088 return 1;
13089 }
13090 }
13091 #endif
13092 return 1;
13093 }
13094
13095 return 0;
13096 }
13097
13098 #if defined(HAVE_PRI)
13099 #if defined(HAVE_PRI_CALL_WAITING)
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13113 {
13114 struct dahdi_pvt *pvt = priv;
13115
13116 pvt->stripmsd = pri->ch_cfg.stripmsd;
13117 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13118 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13119 pvt->immediate = pri->ch_cfg.immediate;
13120 pvt->priexclusive = pri->ch_cfg.priexclusive;
13121 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13122 pvt->use_callerid = pri->ch_cfg.use_callerid;
13123 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13124 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13125 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13126 }
13127 #endif
13128 #endif
13129
13130 #if defined(HAVE_PRI)
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13144 {
13145 int pvt_idx;
13146 int res;
13147 unsigned idx;
13148 struct dahdi_pvt *pvt;
13149 struct sig_pri_chan *chan;
13150 struct dahdi_bufferinfo bi;
13151
13152 static int nobch_channel = CHAN_PSEUDO;
13153
13154
13155 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13156 if (!pri->pvts[pvt_idx]) {
13157 break;
13158 }
13159 }
13160 if (pri->numchans == pvt_idx) {
13161 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13162 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13163 return -1;
13164 }
13165
13166
13167 pri->pvts[pvt_idx] = NULL;
13168 ++pri->numchans;
13169 }
13170
13171 pvt = ast_calloc(1, sizeof(*pvt));
13172 if (!pvt) {
13173 return -1;
13174 }
13175 pvt->cc_params = ast_cc_config_params_init();
13176 if (!pvt->cc_params) {
13177 ast_free(pvt);
13178 return -1;
13179 }
13180 ast_mutex_init(&pvt->lock);
13181 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13182 pvt->subs[idx].dfd = -1;
13183 }
13184 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13185 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13186 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13187 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13188
13189 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13190 if (!chan) {
13191 destroy_dahdi_pvt(pvt);
13192 return -1;
13193 }
13194 chan->no_b_channel = 1;
13195
13196
13197
13198
13199
13200
13201 pvt->law_default = DAHDI_LAW_ALAW;
13202
13203 pvt->sig = pri->sig;
13204 pvt->outsigmod = -1;
13205 pvt->pri = pri;
13206 pvt->sig_pvt = chan;
13207 pri->pvts[pvt_idx] = chan;
13208
13209 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13210 if (pvt->subs[SUB_REAL].dfd < 0) {
13211 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13212 strerror(errno));
13213 destroy_dahdi_pvt(pvt);
13214 return -1;
13215 }
13216 memset(&bi, 0, sizeof(bi));
13217 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13218 if (!res) {
13219 pvt->bufsize = bi.bufsize;
13220 bi.txbufpolicy = pvt->buf_policy;
13221 bi.rxbufpolicy = pvt->buf_policy;
13222 bi.numbufs = pvt->buf_no;
13223 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13224 if (res < 0) {
13225 ast_log(LOG_WARNING,
13226 "Unable to set buffer policy on no B channel interface: %s\n",
13227 strerror(errno));
13228 }
13229 } else
13230 ast_log(LOG_WARNING,
13231 "Unable to check buffer policy on no B channel interface: %s\n",
13232 strerror(errno));
13233
13234 --nobch_channel;
13235 if (CHAN_PSEUDO < nobch_channel) {
13236 nobch_channel = CHAN_PSEUDO - 1;
13237 }
13238 pvt->channel = nobch_channel;
13239 pvt->span = pri->span;
13240 chan->channel = pvt->channel;
13241
13242 dahdi_nobch_insert(pri, pvt);
13243
13244 return pvt_idx;
13245 }
13246 #endif
13247
13248
13249
13250
13251
13252
13253 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13254 {
13255 struct dahdi_pvt *p;
13256 struct dahdi_bufferinfo bi;
13257 int res;
13258
13259 p = ast_malloc(sizeof(*p));
13260 if (!p) {
13261 return NULL;
13262 }
13263 *p = *src;
13264
13265
13266 p->cc_params = ast_cc_config_params_init();
13267 if (!p->cc_params) {
13268 ast_free(p);
13269 return NULL;
13270 }
13271 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13272
13273 p->which_iflist = DAHDI_IFLIST_NONE;
13274 p->next = NULL;
13275 p->prev = NULL;
13276 ast_mutex_init(&p->lock);
13277 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13278 if (p->subs[SUB_REAL].dfd < 0) {
13279 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13280 destroy_dahdi_pvt(p);
13281 return NULL;
13282 }
13283 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13284 if (!res) {
13285 bi.txbufpolicy = src->buf_policy;
13286 bi.rxbufpolicy = src->buf_policy;
13287 bi.numbufs = src->buf_no;
13288 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13289 if (res < 0) {
13290 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13291 }
13292 } else
13293 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13294 p->destroy = 1;
13295 dahdi_iflist_insert(p);
13296 return p;
13297 }
13298
13299 struct dahdi_starting_point {
13300
13301 ast_group_t groupmatch;
13302
13303 int channelmatch;
13304
13305 int rr_starting_point;
13306
13307 int span;
13308
13309 int cadance;
13310
13311 char opt;
13312
13313 char backwards;
13314
13315 char roundrobin;
13316 };
13317 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13318 {
13319 char *dest;
13320 char *s;
13321 int x;
13322 int res = 0;
13323 struct dahdi_pvt *p;
13324 char *subdir = NULL;
13325 AST_DECLARE_APP_ARGS(args,
13326 AST_APP_ARG(group);
13327
13328
13329 AST_APP_ARG(other);
13330 );
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
13349
13350
13351
13352
13353
13354
13355 if (data) {
13356 dest = ast_strdupa(data);
13357 } else {
13358 ast_log(LOG_WARNING, "Channel requested with no data\n");
13359 return NULL;
13360 }
13361 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13362 if (!args.argc || ast_strlen_zero(args.group)) {
13363 ast_log(LOG_WARNING, "No channel/group specified\n");
13364 return NULL;
13365 }
13366
13367
13368 memset(param, 0, sizeof(*param));
13369 param->channelmatch = -1;
13370
13371 if (strchr(args.group, '!') != NULL) {
13372 char *prev = args.group;
13373 while ((s = strchr(prev, '!')) != NULL) {
13374 *s++ = '/';
13375 prev = s;
13376 }
13377 *(prev - 1) = '\0';
13378 subdir = args.group;
13379 args.group = prev;
13380 } else if (args.group[0] == 'i') {
13381
13382 res = sscanf(args.group + 1, "%30d", &x);
13383 if (res < 1) {
13384 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13385 return NULL;
13386 }
13387 param->span = x;
13388
13389
13390 s = strchr(args.group, '-');
13391 if (!s) {
13392
13393 return iflist;
13394 }
13395 args.group = s + 1;
13396 res = 0;
13397 }
13398 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13399
13400 s = args.group + 1;
13401 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13402 if (res < 1) {
13403 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13404 return NULL;
13405 }
13406 param->groupmatch = ((ast_group_t) 1 << x);
13407
13408 if (toupper(args.group[0]) == 'G') {
13409 if (args.group[0] == 'G') {
13410 param->backwards = 1;
13411 p = ifend;
13412 } else
13413 p = iflist;
13414 } else {
13415 if (ARRAY_LEN(round_robin) <= x) {
13416 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13417 x, data);
13418 return NULL;
13419 }
13420 if (args.group[0] == 'R') {
13421 param->backwards = 1;
13422 p = round_robin[x] ? round_robin[x]->prev : ifend;
13423 if (!p)
13424 p = ifend;
13425 } else {
13426 p = round_robin[x] ? round_robin[x]->next : iflist;
13427 if (!p)
13428 p = iflist;
13429 }
13430 param->roundrobin = 1;
13431 param->rr_starting_point = x;
13432 }
13433 } else {
13434 s = args.group;
13435 if (!strcasecmp(s, "pseudo")) {
13436
13437 x = CHAN_PSEUDO;
13438 param->channelmatch = x;
13439 } else {
13440 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13441 if (res < 1) {
13442 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13443 return NULL;
13444 } else {
13445 param->channelmatch = x;
13446 }
13447 }
13448 if (subdir) {
13449 char path[PATH_MAX];
13450 struct stat stbuf;
13451
13452 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13453 subdir, param->channelmatch);
13454 if (stat(path, &stbuf) < 0) {
13455 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13456 path, strerror(errno));
13457 return NULL;
13458 }
13459 if (!S_ISCHR(stbuf.st_mode)) {
13460 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13461 path);
13462 return NULL;
13463 }
13464 param->channelmatch = minor(stbuf.st_rdev);
13465 }
13466
13467 p = iflist;
13468 }
13469
13470 if (param->opt == 'r' && res < 3) {
13471 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13472 param->opt = '\0';
13473 }
13474
13475 return p;
13476 }
13477
13478 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13479 {
13480 int callwait = 0;
13481 struct dahdi_pvt *p;
13482 struct ast_channel *tmp = NULL;
13483 struct dahdi_pvt *exitpvt;
13484 int channelmatched = 0;
13485 int groupmatched = 0;
13486 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13487 int transcapdigital = 0;
13488 #endif
13489 struct dahdi_starting_point start;
13490
13491 ast_mutex_lock(&iflock);
13492 p = determine_starting_point(data, &start);
13493 if (!p) {
13494
13495 ast_mutex_unlock(&iflock);
13496 return NULL;
13497 }
13498
13499
13500 exitpvt = p;
13501 while (p && !tmp) {
13502 if (start.roundrobin)
13503 round_robin[start.rr_starting_point] = p;
13504
13505 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13506 && available(&p, channelmatched)) {
13507 ast_debug(1, "Using channel %d\n", p->channel);
13508
13509 callwait = (p->owner != NULL);
13510 #ifdef HAVE_OPENR2
13511 if (p->mfcr2) {
13512 ast_mutex_lock(&p->lock);
13513 if (p->mfcr2call) {
13514 ast_mutex_unlock(&p->lock);
13515 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13516 goto next;
13517 }
13518 p->mfcr2call = 1;
13519 ast_mutex_unlock(&p->lock);
13520 }
13521 #endif
13522 if (p->channel == CHAN_PSEUDO) {
13523 p = duplicate_pseudo(p);
13524 if (!p) {
13525 break;
13526 }
13527 }
13528
13529 p->distinctivering = 0;
13530
13531 switch (start.opt) {
13532 case '\0':
13533
13534 break;
13535 case 'c':
13536
13537 p->confirmanswer = 1;
13538 break;
13539 case 'r':
13540
13541 p->distinctivering = start.cadance;
13542 break;
13543 case 'd':
13544 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13545
13546 transcapdigital = AST_TRANS_CAP_DIGITAL;
13547 #endif
13548 break;
13549 default:
13550 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13551 break;
13552 }
13553
13554 p->outgoing = 1;
13555 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13556 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13557 #ifdef HAVE_PRI
13558 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13559
13560
13561
13562
13563
13564 ast_mutex_lock(&p->lock);
13565 ast_mutex_unlock(&p->lock);
13566
13567 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13568 sizeof(p->dnid));
13569 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13570 #endif
13571 #if defined(HAVE_SS7)
13572 } else if (p->sig == SIG_SS7) {
13573 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13574 #endif
13575 } else {
13576 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13577 }
13578 if (!tmp) {
13579 p->outgoing = 0;
13580 #if defined(HAVE_PRI)
13581 switch (p->sig) {
13582 case SIG_PRI_LIB_HANDLE_CASES:
13583 #if defined(HAVE_PRI_CALL_WAITING)
13584 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13585 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13586 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13587 }
13588 #endif
13589
13590
13591
13592
13593 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13594 break;
13595 default:
13596 break;
13597 }
13598 #endif
13599 } else {
13600 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13601 }
13602 break;
13603 }
13604 #ifdef HAVE_OPENR2
13605 next:
13606 #endif
13607 if (start.backwards) {
13608 p = p->prev;
13609 if (!p)
13610 p = ifend;
13611 } else {
13612 p = p->next;
13613 if (!p)
13614 p = iflist;
13615 }
13616
13617 if (p == exitpvt)
13618 break;
13619 }
13620 ast_mutex_unlock(&iflock);
13621 restart_monitor();
13622 if (cause && !tmp) {
13623 if (callwait || channelmatched) {
13624 *cause = AST_CAUSE_BUSY;
13625 } else if (groupmatched) {
13626 *cause = AST_CAUSE_CONGESTION;
13627 } else {
13628
13629
13630
13631
13632 }
13633 }
13634
13635 return tmp;
13636 }
13637
13638
13639
13640
13641
13642
13643
13644
13645
13646
13647
13648 static int dahdi_devicestate(void *data)
13649 {
13650 #if defined(HAVE_PRI)
13651 char *device;
13652 unsigned span;
13653 int res;
13654
13655 device = data;
13656
13657 if (*device != 'I') {
13658
13659 return AST_DEVICE_UNKNOWN;
13660 }
13661 res = sscanf(device, "I%30u", &span);
13662 if (res != 1 || !span || NUM_SPANS < span) {
13663
13664 return AST_DEVICE_UNKNOWN;
13665 }
13666 device = strchr(device, '/');
13667 if (!device) {
13668
13669 return AST_DEVICE_UNKNOWN;
13670 }
13671
13672
13673
13674
13675
13676 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13677 ++device;
13678 if (!strcmp(device, "congestion"))
13679 #endif
13680 {
13681 return pris[span - 1].pri.congestion_devstate;
13682 }
13683 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13684 else if (!strcmp(device, "threshold")) {
13685 return pris[span - 1].pri.threshold_devstate;
13686 }
13687 return AST_DEVICE_UNKNOWN;
13688 #endif
13689 #else
13690 return AST_DEVICE_UNKNOWN;
13691 #endif
13692 }
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704
13705
13706
13707
13708
13709
13710 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13711 {
13712 struct dahdi_pvt *p;
13713 struct dahdi_pvt *exitpvt;
13714 struct dahdi_starting_point start;
13715 int groupmatched = 0;
13716 int channelmatched = 0;
13717
13718 ast_mutex_lock(&iflock);
13719 p = determine_starting_point(dest, &start);
13720 if (!p) {
13721 ast_mutex_unlock(&iflock);
13722 return -1;
13723 }
13724 exitpvt = p;
13725 for (;;) {
13726 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13727
13728 struct ast_str *device_name;
13729 char *dash;
13730 const char *monitor_type;
13731 char dialstring[AST_CHANNEL_NAME];
13732 char full_device_name[AST_CHANNEL_NAME];
13733
13734 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13735 case AST_CC_MONITOR_NEVER:
13736 break;
13737 case AST_CC_MONITOR_NATIVE:
13738 case AST_CC_MONITOR_ALWAYS:
13739 case AST_CC_MONITOR_GENERIC:
13740 #if defined(HAVE_PRI)
13741 if (dahdi_sig_pri_lib_handles(p->sig)) {
13742
13743
13744
13745
13746 snprintf(full_device_name, sizeof(full_device_name),
13747 "DAHDI/I%d/congestion", p->pri->span);
13748 } else
13749 #endif
13750 {
13751 #if defined(HAVE_PRI)
13752 device_name = create_channel_name(p, 1, "");
13753 #else
13754 device_name = create_channel_name(p);
13755 #endif
13756 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13757 device_name ? ast_str_buffer(device_name) : "");
13758 ast_free(device_name);
13759
13760
13761
13762
13763
13764 dash = strrchr(full_device_name, '-');
13765 if (dash) {
13766 *dash = '\0';
13767 }
13768 }
13769 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13770
13771
13772
13773
13774
13775
13776
13777 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13778 callback(inbound,
13779 #if defined(HAVE_PRI)
13780 p->pri ? p->pri->cc_params : p->cc_params,
13781 #else
13782 p->cc_params,
13783 #endif
13784 monitor_type, full_device_name, dialstring, NULL);
13785 break;
13786 }
13787 }
13788 p = start.backwards ? p->prev : p->next;
13789 if (!p) {
13790 p = start.backwards ? ifend : iflist;
13791 }
13792 if (p == exitpvt) {
13793 break;
13794 }
13795 }
13796 ast_mutex_unlock(&iflock);
13797 return 0;
13798 }
13799
13800 #if defined(HAVE_SS7)
13801 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13802 {
13803 int i;
13804
13805 if (ss7) {
13806 for (i = 0; i < NUM_SPANS; i++) {
13807 if (linksets[i].ss7.ss7 == ss7) {
13808 ast_verbose("[%d] %s", i + 1, s);
13809 return;
13810 }
13811 }
13812 }
13813 ast_verbose("%s", s);
13814 }
13815 #endif
13816
13817 #if defined(HAVE_SS7)
13818 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13819 {
13820 int i;
13821
13822 if (ss7) {
13823 for (i = 0; i < NUM_SPANS; i++) {
13824 if (linksets[i].ss7.ss7 == ss7) {
13825 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13826 return;
13827 }
13828 }
13829 }
13830 ast_log(LOG_ERROR, "%s", s);
13831 }
13832 #endif
13833
13834 #if defined(HAVE_OPENR2)
13835 static void *mfcr2_monitor(void *data)
13836 {
13837 struct dahdi_mfcr2 *mfcr2 = data;
13838
13839
13840
13841
13842
13843 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13844 int res = 0;
13845 int i = 0;
13846 int oldstate = 0;
13847 int quit_loop = 0;
13848 int maxsleep = 20;
13849 int was_idle = 0;
13850 int pollsize = 0;
13851
13852
13853 for (i = 0; i < mfcr2->numchans; i++) {
13854 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13855 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13856 }
13857 while (1) {
13858
13859
13860 pollsize = 0;
13861 for (i = 0; i < mfcr2->numchans; i++) {
13862 pollers[i].revents = 0;
13863 pollers[i].events = 0;
13864 if (mfcr2->pvts[i]->owner) {
13865 continue;
13866 }
13867 if (!mfcr2->pvts[i]->r2chan) {
13868 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13869 quit_loop = 1;
13870 break;
13871 }
13872 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13873 pollers[i].events = POLLIN | POLLPRI;
13874 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13875 pollsize++;
13876 }
13877 if (quit_loop) {
13878 break;
13879 }
13880 if (pollsize == 0) {
13881 if (!was_idle) {
13882 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13883 was_idle = 1;
13884 }
13885 poll(NULL, 0, maxsleep);
13886 continue;
13887 }
13888 was_idle = 0;
13889
13890
13891 pthread_testcancel();
13892 res = poll(pollers, mfcr2->numchans, maxsleep);
13893 pthread_testcancel();
13894 if ((res < 0) && (errno != EINTR)) {
13895 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13896 break;
13897 }
13898
13899 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13900 for (i = 0; i < mfcr2->numchans; i++) {
13901 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13902 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13903 }
13904 }
13905 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13906 }
13907 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13908 return 0;
13909 }
13910 #endif
13911
13912 #if defined(HAVE_PRI)
13913 #ifndef PRI_RESTART
13914 #error "Upgrade your libpri"
13915 #endif
13916 static void dahdi_pri_message(struct pri *pri, char *s)
13917 {
13918 int x;
13919 int y;
13920 int dchan = -1;
13921 int span = -1;
13922 int dchancount = 0;
13923
13924 if (pri) {
13925 for (x = 0; x < NUM_SPANS; x++) {
13926 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13927 if (pris[x].pri.dchans[y]) {
13928 dchancount++;
13929 }
13930
13931 if (pris[x].pri.dchans[y] == pri) {
13932 dchan = y;
13933 }
13934 }
13935 if (dchan >= 0) {
13936 span = x;
13937 break;
13938 }
13939 dchancount = 0;
13940 }
13941 if (-1 < span) {
13942 if (1 < dchancount) {
13943 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13944 } else {
13945 ast_verbose("PRI Span: %d %s", span + 1, s);
13946 }
13947 } else {
13948 ast_verbose("PRI Span: ? %s", s);
13949 }
13950 } else {
13951 ast_verbose("PRI Span: ? %s", s);
13952 }
13953
13954 ast_mutex_lock(&pridebugfdlock);
13955
13956 if (pridebugfd >= 0) {
13957 if (write(pridebugfd, s, strlen(s)) < 0) {
13958 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13959 }
13960 }
13961
13962 ast_mutex_unlock(&pridebugfdlock);
13963 }
13964 #endif
13965
13966 #if defined(HAVE_PRI)
13967 static void dahdi_pri_error(struct pri *pri, char *s)
13968 {
13969 int x;
13970 int y;
13971 int dchan = -1;
13972 int span = -1;
13973 int dchancount = 0;
13974
13975 if (pri) {
13976 for (x = 0; x < NUM_SPANS; x++) {
13977 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13978 if (pris[x].pri.dchans[y]) {
13979 dchancount++;
13980 }
13981
13982 if (pris[x].pri.dchans[y] == pri) {
13983 dchan = y;
13984 }
13985 }
13986 if (dchan >= 0) {
13987 span = x;
13988 break;
13989 }
13990 dchancount = 0;
13991 }
13992 if (-1 < span) {
13993 if (1 < dchancount) {
13994 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13995 } else {
13996 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
13997 }
13998 } else {
13999 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14000 }
14001 } else {
14002 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14003 }
14004
14005 ast_mutex_lock(&pridebugfdlock);
14006
14007 if (pridebugfd >= 0) {
14008 if (write(pridebugfd, s, strlen(s)) < 0) {
14009 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14010 }
14011 }
14012
14013 ast_mutex_unlock(&pridebugfdlock);
14014 }
14015 #endif
14016
14017 #if defined(HAVE_PRI)
14018 static int prepare_pri(struct dahdi_pri *pri)
14019 {
14020 int i, res, x;
14021 struct dahdi_params p;
14022 struct dahdi_bufferinfo bi;
14023 struct dahdi_spaninfo si;
14024
14025 pri->pri.calls = &dahdi_pri_callbacks;
14026
14027 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14028 if (!pri->dchannels[i])
14029 break;
14030 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14031 x = pri->dchannels[i];
14032 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14033 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14034 return -1;
14035 }
14036 memset(&p, 0, sizeof(p));
14037 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14038 if (res) {
14039 dahdi_close_pri_fd(pri, i);
14040 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14041 return -1;
14042 }
14043 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14044 dahdi_close_pri_fd(pri, i);
14045 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14046 return -1;
14047 }
14048 memset(&si, 0, sizeof(si));
14049 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14050 if (res) {
14051 dahdi_close_pri_fd(pri, i);
14052 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14053 }
14054 if (!si.alarms) {
14055 pri_event_noalarm(&pri->pri, i, 1);
14056 } else {
14057 pri_event_alarm(&pri->pri, i, 1);
14058 }
14059 memset(&bi, 0, sizeof(bi));
14060 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14061 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14062 bi.numbufs = 32;
14063 bi.bufsize = 1024;
14064 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14065 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14066 dahdi_close_pri_fd(pri, i);
14067 return -1;
14068 }
14069 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14070 }
14071 return 0;
14072 }
14073 #endif
14074
14075 #if defined(HAVE_PRI)
14076 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14077 {
14078 int which, span;
14079 char *ret = NULL;
14080
14081 if (pos != rpos)
14082 return ret;
14083
14084 for (which = span = 0; span < NUM_SPANS; span++) {
14085 if (pris[span].pri.pri && ++which > state) {
14086 if (asprintf(&ret, "%d", span + 1) < 0) {
14087 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14088 }
14089 break;
14090 }
14091 }
14092 return ret;
14093 }
14094 #endif
14095
14096 #if defined(HAVE_PRI)
14097 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14098 {
14099 return complete_span_helper(line,word,pos,state,3);
14100 }
14101 #endif
14102
14103 #if defined(HAVE_PRI)
14104 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14105 {
14106 int myfd;
14107 switch (cmd) {
14108 case CLI_INIT:
14109 e->command = "pri set debug file";
14110 e->usage = "Usage: pri set debug file [output-file]\n"
14111 " Sends PRI debug output to the specified output file\n";
14112 return NULL;
14113 case CLI_GENERATE:
14114 return NULL;
14115 }
14116 if (a->argc < 5)
14117 return CLI_SHOWUSAGE;
14118
14119 if (ast_strlen_zero(a->argv[4]))
14120 return CLI_SHOWUSAGE;
14121
14122 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14123 if (myfd < 0) {
14124 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14125 return CLI_SUCCESS;
14126 }
14127
14128 ast_mutex_lock(&pridebugfdlock);
14129
14130 if (pridebugfd >= 0)
14131 close(pridebugfd);
14132
14133 pridebugfd = myfd;
14134 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14135 ast_mutex_unlock(&pridebugfdlock);
14136 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14137 return CLI_SUCCESS;
14138 }
14139 #endif
14140
14141 #if defined(HAVE_PRI)
14142 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14143 {
14144 int span;
14145 int x;
14146 int level = 0;
14147 switch (cmd) {
14148 case CLI_INIT:
14149 e->command = "pri set debug {on|off|0|1|2} span";
14150 e->usage =
14151 "Usage: pri set debug {<level>|on|off} span <span>\n"
14152 " Enables debugging on a given PRI span\n";
14153 return NULL;
14154 case CLI_GENERATE:
14155 return complete_span_4(a->line, a->word, a->pos, a->n);
14156 }
14157 if (a->argc < 6) {
14158 return CLI_SHOWUSAGE;
14159 }
14160
14161 if (!strcasecmp(a->argv[3], "on")) {
14162 level = 1;
14163 } else if (!strcasecmp(a->argv[3], "off")) {
14164 level = 0;
14165 } else {
14166 level = atoi(a->argv[3]);
14167 }
14168 span = atoi(a->argv[5]);
14169 if ((span < 1) || (span > NUM_SPANS)) {
14170 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14171 return CLI_SUCCESS;
14172 }
14173 if (!pris[span-1].pri.pri) {
14174 ast_cli(a->fd, "No PRI running on span %d\n", span);
14175 return CLI_SUCCESS;
14176 }
14177
14178
14179 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14180 if (pris[span - 1].pri.dchans[x]) {
14181 switch (level) {
14182 case 0:
14183 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14184 break;
14185 case 1:
14186 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14187 break;
14188 default:
14189 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14190 break;
14191 }
14192 }
14193 }
14194 if (level == 0) {
14195
14196 ast_mutex_lock(&pridebugfdlock);
14197 if (0 <= pridebugfd) {
14198 close(pridebugfd);
14199 pridebugfd = -1;
14200 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14201 pridebugfilename);
14202 }
14203 ast_mutex_unlock(&pridebugfdlock);
14204 }
14205 pris[span - 1].pri.debug = (level) ? 1 : 0;
14206 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14207 return CLI_SUCCESS;
14208 }
14209 #endif
14210
14211 #if defined(HAVE_PRI)
14212 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14213 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14214 {
14215 unsigned *why;
14216 int channel;
14217 int trunkgroup;
14218 int x, y, fd = a->fd;
14219 int interfaceid = 0;
14220 char *c;
14221 char db_chan_name[20], db_answer[5];
14222 struct dahdi_pvt *tmp;
14223 struct dahdi_pri *pri;
14224
14225 if (a->argc < 5 || a->argc > 6)
14226 return CLI_SHOWUSAGE;
14227 if ((c = strchr(a->argv[4], ':'))) {
14228 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14229 return CLI_SHOWUSAGE;
14230 if ((trunkgroup < 1) || (channel < 1))
14231 return CLI_SHOWUSAGE;
14232 pri = NULL;
14233 for (x=0;x<NUM_SPANS;x++) {
14234 if (pris[x].pri.trunkgroup == trunkgroup) {
14235 pri = pris + x;
14236 break;
14237 }
14238 }
14239 if (!pri) {
14240 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14241 return CLI_FAILURE;
14242 }
14243 } else
14244 channel = atoi(a->argv[4]);
14245
14246 if (a->argc == 6)
14247 interfaceid = atoi(a->argv[5]);
14248
14249
14250 for (x = 0; x < NUM_SPANS; x++) {
14251 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14252 if (pris[x].dchannels[y] == channel) {
14253 pri = pris + x;
14254 if (pri->pri.enable_service_message_support) {
14255 ast_mutex_lock(&pri->pri.lock);
14256 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14257 ast_mutex_unlock(&pri->pri.lock);
14258 } else {
14259 ast_cli(fd,
14260 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14261 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14262 }
14263 return CLI_SUCCESS;
14264 }
14265 }
14266 }
14267
14268
14269 ast_mutex_lock(&iflock);
14270 for (tmp = iflist; tmp; tmp = tmp->next) {
14271 if (tmp->pri && tmp->channel == channel) {
14272 ast_mutex_unlock(&iflock);
14273 ast_mutex_lock(&tmp->pri->lock);
14274 if (!tmp->pri->enable_service_message_support) {
14275 ast_mutex_unlock(&tmp->pri->lock);
14276 ast_cli(fd,
14277 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14278 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14279 return CLI_SUCCESS;
14280 }
14281 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14282 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14283 switch(changestatus) {
14284 case 0:
14285
14286 ast_db_del(db_chan_name, SRVST_DBKEY);
14287 *why &= ~SRVST_NEAREND;
14288 if (*why) {
14289 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14290 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14291 } else {
14292 dahdi_pri_update_span_devstate(tmp->pri);
14293 }
14294 break;
14295
14296 case 2:
14297
14298 ast_db_del(db_chan_name, SRVST_DBKEY);
14299 *why |= SRVST_NEAREND;
14300 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14301 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14302 dahdi_pri_update_span_devstate(tmp->pri);
14303 break;
14304
14305
14306 default:
14307 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14308 break;
14309 }
14310 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14311 ast_mutex_unlock(&tmp->pri->lock);
14312 return CLI_SUCCESS;
14313 }
14314 }
14315 ast_mutex_unlock(&iflock);
14316
14317 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14318 return CLI_FAILURE;
14319 }
14320
14321 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14322 {
14323 switch (cmd) {
14324 case CLI_INIT:
14325 e->command = "pri service enable channel";
14326 e->usage =
14327 "Usage: pri service enable channel <channel> [<interface id>]\n"
14328 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14329 " to restore a channel to service, with optional interface id\n"
14330 " as agreed upon with remote switch operator\n";
14331 return NULL;
14332 case CLI_GENERATE:
14333 return NULL;
14334 }
14335 return handle_pri_service_generic(e, cmd, a, 0);
14336 }
14337
14338 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14339 {
14340 switch (cmd) {
14341 case CLI_INIT:
14342 e->command = "pri service disable channel";
14343 e->usage =
14344 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14345 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14346 " to remove a channel from service, with optional interface id\n"
14347 " as agreed upon with remote switch operator\n";
14348 return NULL;
14349 case CLI_GENERATE:
14350 return NULL;
14351 }
14352 return handle_pri_service_generic(e, cmd, a, 2);
14353 }
14354 #endif
14355 #endif
14356
14357 #if defined(HAVE_PRI)
14358 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14359 {
14360 int span;
14361
14362 switch (cmd) {
14363 case CLI_INIT:
14364 e->command = "pri show channels";
14365 e->usage =
14366 "Usage: pri show channels\n"
14367 " Displays PRI channel information such as the current mapping\n"
14368 " of DAHDI B channels to Asterisk channel names and which calls\n"
14369 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14370 " are not associated with any B channel.\n";
14371 return NULL;
14372 case CLI_GENERATE:
14373 return NULL;
14374 }
14375
14376 if (a->argc != 3)
14377 return CLI_SHOWUSAGE;
14378
14379 sig_pri_cli_show_channels_header(a->fd);
14380 for (span = 0; span < NUM_SPANS; ++span) {
14381 if (pris[span].pri.pri) {
14382 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14383 }
14384 }
14385 return CLI_SUCCESS;
14386 }
14387 #endif
14388
14389 #if defined(HAVE_PRI)
14390 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14391 {
14392 int span;
14393
14394 switch (cmd) {
14395 case CLI_INIT:
14396 e->command = "pri show spans";
14397 e->usage =
14398 "Usage: pri show spans\n"
14399 " Displays PRI span information\n";
14400 return NULL;
14401 case CLI_GENERATE:
14402 return NULL;
14403 }
14404
14405 if (a->argc != 3)
14406 return CLI_SHOWUSAGE;
14407
14408 for (span = 0; span < NUM_SPANS; span++) {
14409 if (pris[span].pri.pri) {
14410 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14411 }
14412 }
14413 return CLI_SUCCESS;
14414 }
14415 #endif
14416
14417 #if defined(HAVE_PRI)
14418 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14419 {
14420 int span;
14421
14422 switch (cmd) {
14423 case CLI_INIT:
14424 e->command = "pri show span";
14425 e->usage =
14426 "Usage: pri show span <span>\n"
14427 " Displays PRI Information on a given PRI span\n";
14428 return NULL;
14429 case CLI_GENERATE:
14430 return complete_span_4(a->line, a->word, a->pos, a->n);
14431 }
14432
14433 if (a->argc < 4)
14434 return CLI_SHOWUSAGE;
14435 span = atoi(a->argv[3]);
14436 if ((span < 1) || (span > NUM_SPANS)) {
14437 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14438 return CLI_SUCCESS;
14439 }
14440 if (!pris[span-1].pri.pri) {
14441 ast_cli(a->fd, "No PRI running on span %d\n", span);
14442 return CLI_SUCCESS;
14443 }
14444
14445 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14446
14447 return CLI_SUCCESS;
14448 }
14449 #endif
14450
14451 #if defined(HAVE_PRI)
14452 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14453 {
14454 int x;
14455 int span;
14456 int count=0;
14457 int debug;
14458
14459 switch (cmd) {
14460 case CLI_INIT:
14461 e->command = "pri show debug";
14462 e->usage =
14463 "Usage: pri show debug\n"
14464 " Show the debug state of pri spans\n";
14465 return NULL;
14466 case CLI_GENERATE:
14467 return NULL;
14468 }
14469
14470 for (span = 0; span < NUM_SPANS; span++) {
14471 if (pris[span].pri.pri) {
14472 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14473 if (pris[span].pri.dchans[x]) {
14474 debug = pri_get_debug(pris[span].pri.dchans[x]);
14475 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" );
14476 count++;
14477 }
14478 }
14479 }
14480
14481 }
14482 ast_mutex_lock(&pridebugfdlock);
14483 if (pridebugfd >= 0)
14484 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14485 ast_mutex_unlock(&pridebugfdlock);
14486
14487 if (!count)
14488 ast_cli(a->fd, "No PRI running\n");
14489 return CLI_SUCCESS;
14490 }
14491 #endif
14492
14493 #if defined(HAVE_PRI)
14494 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14495 {
14496 switch (cmd) {
14497 case CLI_INIT:
14498 e->command = "pri show version";
14499 e->usage =
14500 "Usage: pri show version\n"
14501 "Show libpri version information\n";
14502 return NULL;
14503 case CLI_GENERATE:
14504 return NULL;
14505 }
14506
14507 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14508
14509 return CLI_SUCCESS;
14510 }
14511 #endif
14512
14513 #if defined(HAVE_PRI)
14514 static struct ast_cli_entry dahdi_pri_cli[] = {
14515 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14516 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14517 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14518 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14519 #endif
14520 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14521 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14522 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14523 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14524 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14525 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14526 };
14527 #endif
14528
14529 #ifdef HAVE_OPENR2
14530
14531 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14532 {
14533 switch (cmd) {
14534 case CLI_INIT:
14535 e->command = "mfcr2 show version";
14536 e->usage =
14537 "Usage: mfcr2 show version\n"
14538 " Shows the version of the OpenR2 library being used.\n";
14539 return NULL;
14540 case CLI_GENERATE:
14541 return NULL;
14542 }
14543 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14544 return CLI_SUCCESS;
14545 }
14546
14547 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14548 {
14549 #define FORMAT "%4s %40s\n"
14550 int i = 0;
14551 int numvariants = 0;
14552 const openr2_variant_entry_t *variants;
14553 switch (cmd) {
14554 case CLI_INIT:
14555 e->command = "mfcr2 show variants";
14556 e->usage =
14557 "Usage: mfcr2 show variants\n"
14558 " Shows the list of MFC/R2 variants supported.\n";
14559 return NULL;
14560 case CLI_GENERATE:
14561 return NULL;
14562 }
14563 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14564 ast_cli(a->fd, "Failed to get list of variants.\n");
14565 return CLI_FAILURE;
14566 }
14567 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14568 for (i = 0; i < numvariants; i++) {
14569 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14570 }
14571 return CLI_SUCCESS;
14572 #undef FORMAT
14573 }
14574
14575 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14576 {
14577 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14578 int filtertype = 0;
14579 int targetnum = 0;
14580 char channo[5];
14581 char anino[5];
14582 char dnisno[5];
14583 struct dahdi_pvt *p;
14584 openr2_context_t *r2context;
14585 openr2_variant_t r2variant;
14586 switch (cmd) {
14587 case CLI_INIT:
14588 e->command = "mfcr2 show channels [group|context]";
14589 e->usage =
14590 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14591 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14592 return NULL;
14593 case CLI_GENERATE:
14594 return NULL;
14595 }
14596 if (!((a->argc == 3) || (a->argc == 5))) {
14597 return CLI_SHOWUSAGE;
14598 }
14599 if (a->argc == 5) {
14600 if (!strcasecmp(a->argv[3], "group")) {
14601 targetnum = atoi(a->argv[4]);
14602 if ((targetnum < 0) || (targetnum > 63))
14603 return CLI_SHOWUSAGE;
14604 targetnum = 1 << targetnum;
14605 filtertype = 1;
14606 } else if (!strcasecmp(a->argv[3], "context")) {
14607 filtertype = 2;
14608 } else {
14609 return CLI_SHOWUSAGE;
14610 }
14611 }
14612 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14613 ast_mutex_lock(&iflock);
14614 for (p = iflist; p; p = p->next) {
14615 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14616 continue;
14617 }
14618 if (filtertype) {
14619 switch(filtertype) {
14620 case 1:
14621 if (p->group != targetnum) {
14622 continue;
14623 }
14624 break;
14625 case 2:
14626 if (strcasecmp(p->context, a->argv[4])) {
14627 continue;
14628 }
14629 break;
14630 default:
14631 ;
14632 }
14633 }
14634 r2context = openr2_chan_get_context(p->r2chan);
14635 r2variant = openr2_context_get_variant(r2context);
14636 snprintf(channo, sizeof(channo), "%d", p->channel);
14637 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14638 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14639 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14640 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14641 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14642 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14643 }
14644 ast_mutex_unlock(&iflock);
14645 return CLI_SUCCESS;
14646 #undef FORMAT
14647 }
14648
14649 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14650 {
14651 struct dahdi_pvt *p = NULL;
14652 int channo = 0;
14653 char *toklevel = NULL;
14654 char *saveptr = NULL;
14655 char *logval = NULL;
14656 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14657 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14658 switch (cmd) {
14659 case CLI_INIT:
14660 e->command = "mfcr2 set debug";
14661 e->usage =
14662 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14663 " Set a new logging level for the specified channel.\n"
14664 " If no channel is specified the logging level will be applied to all channels.\n";
14665 return NULL;
14666 case CLI_GENERATE:
14667 return NULL;
14668 }
14669 if (a->argc < 4) {
14670 return CLI_SHOWUSAGE;
14671 }
14672 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14673 logval = ast_strdupa(a->argv[3]);
14674 toklevel = strtok_r(logval, ",", &saveptr);
14675 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14676 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14677 return CLI_FAILURE;
14678 } else if (OR2_LOG_NOTHING == tmplevel) {
14679 loglevel = tmplevel;
14680 } else {
14681 loglevel |= tmplevel;
14682 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14683 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14684 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14685 continue;
14686 }
14687 loglevel |= tmplevel;
14688 }
14689 }
14690 ast_mutex_lock(&iflock);
14691 for (p = iflist; p; p = p->next) {
14692 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14693 continue;
14694 }
14695 if ((channo != -1) && (p->channel != channo )) {
14696 continue;
14697 }
14698 openr2_chan_set_log_level(p->r2chan, loglevel);
14699 if (channo != -1) {
14700 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14701 break;
14702 }
14703 }
14704 if ((channo != -1) && !p) {
14705 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14706 }
14707 if (channo == -1) {
14708 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14709 }
14710 ast_mutex_unlock(&iflock);
14711 return CLI_SUCCESS;
14712 }
14713
14714 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14715 {
14716 struct dahdi_pvt *p = NULL;
14717 int channo = 0;
14718 switch (cmd) {
14719 case CLI_INIT:
14720 e->command = "mfcr2 call files [on|off]";
14721 e->usage =
14722 "Usage: mfcr2 call files [on|off] <channel>\n"
14723 " Enable call files creation on the specified channel.\n"
14724 " If no channel is specified call files creation policy will be applied to all channels.\n";
14725 return NULL;
14726 case CLI_GENERATE:
14727 return NULL;
14728 }
14729 if (a->argc < 4) {
14730 return CLI_SHOWUSAGE;
14731 }
14732 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14733 ast_mutex_lock(&iflock);
14734 for (p = iflist; p; p = p->next) {
14735 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14736 continue;
14737 }
14738 if ((channo != -1) && (p->channel != channo )) {
14739 continue;
14740 }
14741 if (ast_true(a->argv[3])) {
14742 openr2_chan_enable_call_files(p->r2chan);
14743 } else {
14744 openr2_chan_disable_call_files(p->r2chan);
14745 }
14746 if (channo != -1) {
14747 if (ast_true(a->argv[3])) {
14748 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14749 } else {
14750 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14751 }
14752 break;
14753 }
14754 }
14755 if ((channo != -1) && !p) {
14756 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14757 }
14758 if (channo == -1) {
14759 if (ast_true(a->argv[3])) {
14760 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14761 } else {
14762 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14763 }
14764 }
14765 ast_mutex_unlock(&iflock);
14766 return CLI_SUCCESS;
14767 }
14768
14769 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14770 {
14771 struct dahdi_pvt *p = NULL;
14772 int channo = 0;
14773 switch (cmd) {
14774 case CLI_INIT:
14775 e->command = "mfcr2 set idle";
14776 e->usage =
14777 "Usage: mfcr2 set idle <channel>\n"
14778 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14779 " Force the given channel into IDLE state.\n"
14780 " If no channel is specified, all channels will be set to IDLE.\n";
14781 return NULL;
14782 case CLI_GENERATE:
14783 return NULL;
14784 }
14785 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14786 ast_mutex_lock(&iflock);
14787 for (p = iflist; p; p = p->next) {
14788 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14789 continue;
14790 }
14791 if ((channo != -1) && (p->channel != channo )) {
14792 continue;
14793 }
14794 openr2_chan_set_idle(p->r2chan);
14795 ast_mutex_lock(&p->lock);
14796 p->locallyblocked = 0;
14797 p->mfcr2call = 0;
14798 ast_mutex_unlock(&p->lock);
14799 if (channo != -1) {
14800 break;
14801 }
14802 }
14803 if ((channo != -1) && !p) {
14804 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14805 }
14806 ast_mutex_unlock(&iflock);
14807 return CLI_SUCCESS;
14808 }
14809
14810 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14811 {
14812 struct dahdi_pvt *p = NULL;
14813 int channo = 0;
14814 switch (cmd) {
14815 case CLI_INIT:
14816 e->command = "mfcr2 set blocked";
14817 e->usage =
14818 "Usage: mfcr2 set blocked <channel>\n"
14819 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14820 " Force the given channel into BLOCKED state.\n"
14821 " If no channel is specified, all channels will be set to BLOCKED.\n";
14822 return NULL;
14823 case CLI_GENERATE:
14824 return NULL;
14825 }
14826 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14827 ast_mutex_lock(&iflock);
14828 for (p = iflist; p; p = p->next) {
14829 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14830 continue;
14831 }
14832 if ((channo != -1) && (p->channel != channo )) {
14833 continue;
14834 }
14835 openr2_chan_set_blocked(p->r2chan);
14836 ast_mutex_lock(&p->lock);
14837 p->locallyblocked = 1;
14838 ast_mutex_unlock(&p->lock);
14839 if (channo != -1) {
14840 break;
14841 }
14842 }
14843 if ((channo != -1) && !p) {
14844 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14845 }
14846 ast_mutex_unlock(&iflock);
14847 return CLI_SUCCESS;
14848 }
14849
14850 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14851 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14852 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14853 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14854 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14855 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14856 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14857 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14858 };
14859
14860 #endif
14861
14862 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14863 {
14864 int channel;
14865 int ret;
14866 switch (cmd) {
14867 case CLI_INIT:
14868 e->command = "dahdi destroy channel";
14869 e->usage =
14870 "Usage: dahdi destroy channel <chan num>\n"
14871 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14872 return NULL;
14873 case CLI_GENERATE:
14874 return NULL;
14875 }
14876 if (a->argc != 4)
14877 return CLI_SHOWUSAGE;
14878
14879 channel = atoi(a->argv[3]);
14880 ret = dahdi_destroy_channel_bynum(channel);
14881 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14882 }
14883
14884 static void dahdi_softhangup_all(void)
14885 {
14886 struct dahdi_pvt *p;
14887 retry:
14888 ast_mutex_lock(&iflock);
14889 for (p = iflist; p; p = p->next) {
14890 ast_mutex_lock(&p->lock);
14891 if (p->owner && !p->restartpending) {
14892 if (ast_channel_trylock(p->owner)) {
14893 if (option_debug > 2)
14894 ast_verbose("Avoiding deadlock\n");
14895
14896 ast_mutex_unlock(&p->lock);
14897 ast_mutex_unlock(&iflock);
14898 goto retry;
14899 }
14900 if (option_debug > 2)
14901 ast_verbose("Softhanging up on %s\n", p->owner->name);
14902 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14903 p->restartpending = 1;
14904 num_restart_pending++;
14905 ast_channel_unlock(p->owner);
14906 }
14907 ast_mutex_unlock(&p->lock);
14908 }
14909 ast_mutex_unlock(&iflock);
14910 }
14911
14912 static int setup_dahdi(int reload);
14913 static int dahdi_restart(void)
14914 {
14915 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14916 int i, j;
14917 #endif
14918 int cancel_code;
14919 struct dahdi_pvt *p;
14920
14921 ast_mutex_lock(&restart_lock);
14922 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14923 dahdi_softhangup_all();
14924 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14925 #ifdef HAVE_OPENR2
14926 dahdi_r2_destroy_links();
14927 #endif
14928
14929 #if defined(HAVE_PRI)
14930 for (i = 0; i < NUM_SPANS; i++) {
14931 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14932 cancel_code = pthread_cancel(pris[i].pri.master);
14933 pthread_kill(pris[i].pri.master, SIGURG);
14934 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);
14935 pthread_join(pris[i].pri.master, NULL);
14936 ast_debug(4, "Joined thread of span %d\n", i);
14937 }
14938 }
14939 #endif
14940
14941 #if defined(HAVE_SS7)
14942 for (i = 0; i < NUM_SPANS; i++) {
14943 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14944 cancel_code = pthread_cancel(linksets[i].ss7.master);
14945 pthread_kill(linksets[i].ss7.master, SIGURG);
14946 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);
14947 pthread_join(linksets[i].ss7.master, NULL);
14948 ast_debug(4, "Joined thread of span %d\n", i);
14949 }
14950 }
14951 #endif
14952
14953 ast_mutex_lock(&monlock);
14954 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14955 cancel_code = pthread_cancel(monitor_thread);
14956 pthread_kill(monitor_thread, SIGURG);
14957 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14958 pthread_join(monitor_thread, NULL);
14959 ast_debug(4, "Joined monitor thread\n");
14960 }
14961 monitor_thread = AST_PTHREADT_NULL;
14962
14963 ast_mutex_lock(&ss_thread_lock);
14964 while (ss_thread_count > 0) {
14965 int x = DAHDI_FLASH;
14966 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14967
14968 ast_mutex_lock(&iflock);
14969 for (p = iflist; p; p = p->next) {
14970 if (p->owner) {
14971
14972 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14973 }
14974 }
14975 ast_mutex_unlock(&iflock);
14976 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14977 }
14978
14979
14980 dahdi_softhangup_all();
14981 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14982 destroy_all_channels();
14983 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14984
14985 ast_mutex_unlock(&monlock);
14986
14987 #ifdef HAVE_PRI
14988 for (i = 0; i < NUM_SPANS; i++) {
14989 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14990 dahdi_close_pri_fd(&(pris[i]), j);
14991 }
14992
14993 memset(pris, 0, sizeof(pris));
14994 for (i = 0; i < NUM_SPANS; i++) {
14995 sig_pri_init_pri(&pris[i].pri);
14996 }
14997 pri_set_error(dahdi_pri_error);
14998 pri_set_message(dahdi_pri_message);
14999 #endif
15000 #if defined(HAVE_SS7)
15001 for (i = 0; i < NUM_SPANS; i++) {
15002 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15003 dahdi_close_ss7_fd(&(linksets[i]), j);
15004 }
15005
15006 memset(linksets, 0, sizeof(linksets));
15007 for (i = 0; i < NUM_SPANS; i++) {
15008 sig_ss7_init_linkset(&linksets[i].ss7);
15009 }
15010 ss7_set_error(dahdi_ss7_error);
15011 ss7_set_message(dahdi_ss7_message);
15012 #endif
15013
15014 if (setup_dahdi(2) != 0) {
15015 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15016 ast_mutex_unlock(&ss_thread_lock);
15017 return 1;
15018 }
15019 ast_mutex_unlock(&ss_thread_lock);
15020 ast_mutex_unlock(&restart_lock);
15021 return 0;
15022 }
15023
15024 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15025 {
15026 switch (cmd) {
15027 case CLI_INIT:
15028 e->command = "dahdi restart";
15029 e->usage =
15030 "Usage: dahdi restart\n"
15031 " Restarts the DAHDI channels: destroys them all and then\n"
15032 " re-reads them from chan_dahdi.conf.\n"
15033 " Note that this will STOP any running CALL on DAHDI channels.\n"
15034 "";
15035 return NULL;
15036 case CLI_GENERATE:
15037 return NULL;
15038 }
15039 if (a->argc != 2)
15040 return CLI_SHOWUSAGE;
15041
15042 if (dahdi_restart() != 0)
15043 return CLI_FAILURE;
15044 return CLI_SUCCESS;
15045 }
15046
15047 static int action_dahdirestart(struct mansession *s, const struct message *m)
15048 {
15049 if (dahdi_restart() != 0) {
15050 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15051 return 1;
15052 }
15053 astman_send_ack(s, m, "DAHDIRestart: Success");
15054 return 0;
15055 }
15056
15057 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15058 {
15059 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15060 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15061 unsigned int targetnum = 0;
15062 int filtertype = 0;
15063 struct dahdi_pvt *tmp = NULL;
15064 char tmps[20] = "";
15065 char statestr[20] = "";
15066 char blockstr[20] = "";
15067
15068 switch (cmd) {
15069 case CLI_INIT:
15070 e->command = "dahdi show channels [group|context]";
15071 e->usage =
15072 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15073 " Shows a list of available channels with optional filtering\n"
15074 " <group> must be a number between 0 and 63\n";
15075 return NULL;
15076 case CLI_GENERATE:
15077 return NULL;
15078 }
15079
15080
15081
15082 if (!((a->argc == 3) || (a->argc == 5)))
15083 return CLI_SHOWUSAGE;
15084
15085 if (a->argc == 5) {
15086 if (!strcasecmp(a->argv[3], "group")) {
15087 targetnum = atoi(a->argv[4]);
15088 if ((targetnum < 0) || (targetnum > 63))
15089 return CLI_SHOWUSAGE;
15090 targetnum = 1 << targetnum;
15091 filtertype = 1;
15092 } else if (!strcasecmp(a->argv[3], "context")) {
15093 filtertype = 2;
15094 }
15095 }
15096
15097 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15098 ast_mutex_lock(&iflock);
15099 for (tmp = iflist; tmp; tmp = tmp->next) {
15100 if (filtertype) {
15101 switch(filtertype) {
15102 case 1:
15103 if (!(tmp->group & targetnum)) {
15104 continue;
15105 }
15106 break;
15107 case 2:
15108 if (strcasecmp(tmp->context, a->argv[4])) {
15109 continue;
15110 }
15111 break;
15112 default:
15113 break;
15114 }
15115 }
15116 if (tmp->channel > 0) {
15117 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15118 } else
15119 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15120
15121 if (tmp->locallyblocked)
15122 blockstr[0] = 'L';
15123 else
15124 blockstr[0] = ' ';
15125
15126 if (tmp->remotelyblocked)
15127 blockstr[1] = 'R';
15128 else
15129 blockstr[1] = ' ';
15130
15131 blockstr[2] = '\0';
15132
15133 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15134
15135 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15136 }
15137 ast_mutex_unlock(&iflock);
15138 return CLI_SUCCESS;
15139 #undef FORMAT
15140 #undef FORMAT2
15141 }
15142
15143 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15144 {
15145 int channel;
15146 struct dahdi_pvt *tmp = NULL;
15147 struct dahdi_confinfo ci;
15148 struct dahdi_params ps;
15149 int x;
15150
15151 switch (cmd) {
15152 case CLI_INIT:
15153 e->command = "dahdi show channel";
15154 e->usage =
15155 "Usage: dahdi show channel <chan num>\n"
15156 " Detailed information about a given channel\n";
15157 return NULL;
15158 case CLI_GENERATE:
15159 return NULL;
15160 }
15161
15162 if (a->argc != 4)
15163 return CLI_SHOWUSAGE;
15164
15165 channel = atoi(a->argv[3]);
15166
15167 ast_mutex_lock(&iflock);
15168 for (tmp = iflist; tmp; tmp = tmp->next) {
15169 if (tmp->channel == channel) {
15170 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15171 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15172 ast_cli(a->fd, "Span: %d\n", tmp->span);
15173 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15174 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15175 ast_cli(a->fd, "Context: %s\n", tmp->context);
15176 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15177 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15178 #if defined(HAVE_PRI)
15179 #if defined(HAVE_PRI_SUBADDR)
15180 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15181 #endif
15182 #endif
15183 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15184 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15185 if (tmp->vars) {
15186 struct ast_variable *v;
15187 ast_cli(a->fd, "Variables:\n");
15188 for (v = tmp->vars ; v ; v = v->next)
15189 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15190 }
15191 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15192 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15193 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15194 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15195 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15196 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)" : "");
15197 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)" : "");
15198 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)" : "");
15199 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15200 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15201 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15202 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15203 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15204 if (tmp->busydetect) {
15205 #if defined(BUSYDETECT_TONEONLY)
15206 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15207 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15208 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15209 #endif
15210 #ifdef BUSYDETECT_DEBUG
15211 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15212 #endif
15213 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15214 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15215 }
15216 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15217 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15218 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15219 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15220 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15221 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15222 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15223 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15224 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15225 ast_cli(a->fd, "Echo Cancellation:\n");
15226
15227 if (tmp->echocancel.head.tap_length) {
15228 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15229 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15230 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15231 }
15232 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15233 } else {
15234 ast_cli(a->fd, "\tnone\n");
15235 }
15236 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15237 if (tmp->master)
15238 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15239 for (x = 0; x < MAX_SLAVES; x++) {
15240 if (tmp->slaves[x])
15241 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15242 }
15243 #ifdef HAVE_OPENR2
15244 if (tmp->mfcr2) {
15245 char calldir[OR2_MAX_PATH];
15246 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15247 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15248 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15249 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15250 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15251 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15252 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15253 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15254 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15255 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15256 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15257 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15258 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15259 #endif
15260 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15261 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15262 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15263 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15264 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15265 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15266 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15267 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15268 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15269 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15270 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15271 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15272 }
15273 #endif
15274 #if defined(HAVE_SS7)
15275 if (tmp->ss7) {
15276 struct sig_ss7_chan *chan = tmp->sig_pvt;
15277
15278 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15279 }
15280 #endif
15281 #ifdef HAVE_PRI
15282 if (tmp->pri) {
15283 struct sig_pri_chan *chan = tmp->sig_pvt;
15284
15285 ast_cli(a->fd, "PRI Flags: ");
15286 if (chan->resetting)
15287 ast_cli(a->fd, "Resetting ");
15288 if (chan->call)
15289 ast_cli(a->fd, "Call ");
15290 if (chan->allocated) {
15291 ast_cli(a->fd, "Allocated ");
15292 }
15293 ast_cli(a->fd, "\n");
15294 if (tmp->logicalspan)
15295 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15296 else
15297 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15298 }
15299 #endif
15300 memset(&ci, 0, sizeof(ci));
15301 ps.channo = tmp->channel;
15302 if (tmp->subs[SUB_REAL].dfd > -1) {
15303 memset(&ci, 0, sizeof(ci));
15304 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15305 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15306 }
15307 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15308 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15309 }
15310 memset(&ps, 0, sizeof(ps));
15311 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15312 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15313 } else {
15314 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15315 }
15316 }
15317 ast_mutex_unlock(&iflock);
15318 return CLI_SUCCESS;
15319 }
15320 }
15321 ast_mutex_unlock(&iflock);
15322
15323 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15324 return CLI_FAILURE;
15325 }
15326
15327 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15328 {
15329 int i, j;
15330 switch (cmd) {
15331 case CLI_INIT:
15332 e->command = "dahdi show cadences";
15333 e->usage =
15334 "Usage: dahdi show cadences\n"
15335 " Shows all cadences currently defined\n";
15336 return NULL;
15337 case CLI_GENERATE:
15338 return NULL;
15339 }
15340 for (i = 0; i < num_cadence; i++) {
15341 char output[1024];
15342 char tmp[16], tmp2[64];
15343 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15344 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15345
15346 for (j = 0; j < 16; j++) {
15347 if (cadences[i].ringcadence[j] == 0)
15348 break;
15349 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15350 if (cidrings[i] * 2 - 1 == j)
15351 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15352 else
15353 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15354 if (j != 0)
15355 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15356 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15357 }
15358 ast_cli(a->fd,"%s\n",output);
15359 }
15360 return CLI_SUCCESS;
15361 }
15362
15363
15364 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15365 {
15366 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15367 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15368 int span;
15369 int res;
15370 char alarmstr[50];
15371
15372 int ctl;
15373 struct dahdi_spaninfo s;
15374
15375 switch (cmd) {
15376 case CLI_INIT:
15377 e->command = "dahdi show status";
15378 e->usage =
15379 "Usage: dahdi show status\n"
15380 " Shows a list of DAHDI cards with status\n";
15381 return NULL;
15382 case CLI_GENERATE:
15383 return NULL;
15384 }
15385 ctl = open("/dev/dahdi/ctl", O_RDWR);
15386 if (ctl < 0) {
15387 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15388 return CLI_FAILURE;
15389 }
15390 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15391
15392 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15393 s.spanno = span;
15394 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15395 if (res) {
15396 continue;
15397 }
15398 alarmstr[0] = '\0';
15399 if (s.alarms > 0) {
15400 if (s.alarms & DAHDI_ALARM_BLUE)
15401 strcat(alarmstr, "BLU/");
15402 if (s.alarms & DAHDI_ALARM_YELLOW)
15403 strcat(alarmstr, "YEL/");
15404 if (s.alarms & DAHDI_ALARM_RED)
15405 strcat(alarmstr, "RED/");
15406 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15407 strcat(alarmstr, "LB/");
15408 if (s.alarms & DAHDI_ALARM_RECOVER)
15409 strcat(alarmstr, "REC/");
15410 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15411 strcat(alarmstr, "NOP/");
15412 if (!strlen(alarmstr))
15413 strcat(alarmstr, "UUU/");
15414 if (strlen(alarmstr)) {
15415
15416 alarmstr[strlen(alarmstr) - 1] = '\0';
15417 }
15418 } else {
15419 if (s.numchans)
15420 strcpy(alarmstr, "OK");
15421 else
15422 strcpy(alarmstr, "UNCONFIGURED");
15423 }
15424
15425 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15426 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15427 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15428 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15429 "CAS",
15430 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15431 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15432 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15433 "Unk",
15434 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15435 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15436 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15437 lbostr[s.lbo]
15438 );
15439 }
15440 close(ctl);
15441
15442 return CLI_SUCCESS;
15443 #undef FORMAT
15444 #undef FORMAT2
15445 }
15446
15447 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15448 {
15449 int pseudo_fd = -1;
15450 struct dahdi_versioninfo vi;
15451
15452 switch (cmd) {
15453 case CLI_INIT:
15454 e->command = "dahdi show version";
15455 e->usage =
15456 "Usage: dahdi show version\n"
15457 " Shows the DAHDI version in use\n";
15458 return NULL;
15459 case CLI_GENERATE:
15460 return NULL;
15461 }
15462 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15463 ast_cli(a->fd, "Failed to open control file to get version.\n");
15464 return CLI_SUCCESS;
15465 }
15466
15467 strcpy(vi.version, "Unknown");
15468 strcpy(vi.echo_canceller, "Unknown");
15469
15470 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15471 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15472 else
15473 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15474
15475 close(pseudo_fd);
15476
15477 return CLI_SUCCESS;
15478 }
15479
15480 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15481 {
15482 int channel;
15483 int gain;
15484 int tx;
15485 struct dahdi_hwgain hwgain;
15486 struct dahdi_pvt *tmp = NULL;
15487
15488 switch (cmd) {
15489 case CLI_INIT:
15490 e->command = "dahdi set hwgain";
15491 e->usage =
15492 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15493 " Sets the hardware gain on a a given channel, overriding the\n"
15494 " value provided at module loadtime, whether the channel is in\n"
15495 " use or not. Changes take effect immediately.\n"
15496 " <rx|tx> which direction do you want to change (relative to our module)\n"
15497 " <chan num> is the channel number relative to the device\n"
15498 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15499 return NULL;
15500 case CLI_GENERATE:
15501 return NULL;
15502 }
15503
15504 if (a->argc != 6)
15505 return CLI_SHOWUSAGE;
15506
15507 if (!strcasecmp("rx", a->argv[3]))
15508 tx = 0;
15509 else if (!strcasecmp("tx", a->argv[3]))
15510 tx = 1;
15511 else
15512 return CLI_SHOWUSAGE;
15513
15514 channel = atoi(a->argv[4]);
15515 gain = atof(a->argv[5])*10.0;
15516
15517 ast_mutex_lock(&iflock);
15518
15519 for (tmp = iflist; tmp; tmp = tmp->next) {
15520
15521 if (tmp->channel != channel)
15522 continue;
15523
15524 if (tmp->subs[SUB_REAL].dfd == -1)
15525 break;
15526
15527 hwgain.newgain = gain;
15528 hwgain.tx = tx;
15529 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15530 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15531 ast_mutex_unlock(&iflock);
15532 return CLI_FAILURE;
15533 }
15534 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15535 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15536 break;
15537 }
15538
15539 ast_mutex_unlock(&iflock);
15540
15541 if (tmp)
15542 return CLI_SUCCESS;
15543
15544 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15545 return CLI_FAILURE;
15546
15547 }
15548
15549 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15550 {
15551 int channel;
15552 float gain;
15553 int tx;
15554 int res;
15555 struct dahdi_pvt *tmp = NULL;
15556
15557 switch (cmd) {
15558 case CLI_INIT:
15559 e->command = "dahdi set swgain";
15560 e->usage =
15561 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15562 " Sets the software gain on a a given channel, overriding the\n"
15563 " value provided at module loadtime, whether the channel is in\n"
15564 " use or not. Changes take effect immediately.\n"
15565 " <rx|tx> which direction do you want to change (relative to our module)\n"
15566 " <chan num> is the channel number relative to the device\n"
15567 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15568 return NULL;
15569 case CLI_GENERATE:
15570 return NULL;
15571 }
15572
15573 if (a->argc != 6)
15574 return CLI_SHOWUSAGE;
15575
15576 if (!strcasecmp("rx", a->argv[3]))
15577 tx = 0;
15578 else if (!strcasecmp("tx", a->argv[3]))
15579 tx = 1;
15580 else
15581 return CLI_SHOWUSAGE;
15582
15583 channel = atoi(a->argv[4]);
15584 gain = atof(a->argv[5]);
15585
15586 ast_mutex_lock(&iflock);
15587 for (tmp = iflist; tmp; tmp = tmp->next) {
15588
15589 if (tmp->channel != channel)
15590 continue;
15591
15592 if (tmp->subs[SUB_REAL].dfd == -1)
15593 break;
15594
15595 if (tx)
15596 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15597 else
15598 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15599
15600 if (res) {
15601 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15602 ast_mutex_unlock(&iflock);
15603 return CLI_FAILURE;
15604 }
15605
15606 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15607 tx ? "tx" : "rx", gain, channel);
15608 break;
15609 }
15610 ast_mutex_unlock(&iflock);
15611
15612 if (tmp)
15613 return CLI_SUCCESS;
15614
15615 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15616 return CLI_FAILURE;
15617
15618 }
15619
15620 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15621 {
15622 int channel;
15623 int on;
15624 struct dahdi_pvt *dahdi_chan = NULL;
15625
15626 switch (cmd) {
15627 case CLI_INIT:
15628 e->command = "dahdi set dnd";
15629 e->usage =
15630 "Usage: dahdi set dnd <chan#> <on|off>\n"
15631 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15632 " Changes take effect immediately.\n"
15633 " <chan num> is the channel number\n"
15634 " <on|off> Enable or disable DND mode?\n"
15635 ;
15636 return NULL;
15637 case CLI_GENERATE:
15638 return NULL;
15639 }
15640
15641 if (a->argc != 5)
15642 return CLI_SHOWUSAGE;
15643
15644 if ((channel = atoi(a->argv[3])) <= 0) {
15645 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15646 return CLI_SHOWUSAGE;
15647 }
15648
15649 if (ast_true(a->argv[4]))
15650 on = 1;
15651 else if (ast_false(a->argv[4]))
15652 on = 0;
15653 else {
15654 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15655 return CLI_SHOWUSAGE;
15656 }
15657
15658 ast_mutex_lock(&iflock);
15659 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15660 if (dahdi_chan->channel != channel)
15661 continue;
15662
15663
15664 dahdi_dnd(dahdi_chan, on);
15665 break;
15666 }
15667 ast_mutex_unlock(&iflock);
15668
15669 if (!dahdi_chan) {
15670 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15671 return CLI_FAILURE;
15672 }
15673
15674 return CLI_SUCCESS;
15675 }
15676
15677 static struct ast_cli_entry dahdi_cli[] = {
15678 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15679 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15680 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15681 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15682 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15683 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15684 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15685 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15686 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15687 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15688 };
15689
15690 #define TRANSFER 0
15691 #define HANGUP 1
15692
15693 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15694 {
15695 if (p) {
15696 switch (mode) {
15697 case TRANSFER:
15698 p->fake_event = DAHDI_EVENT_WINKFLASH;
15699 break;
15700 case HANGUP:
15701 p->fake_event = DAHDI_EVENT_ONHOOK;
15702 break;
15703 default:
15704 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15705 }
15706 }
15707 return 0;
15708 }
15709 static struct dahdi_pvt *find_channel(int channel)
15710 {
15711 struct dahdi_pvt *p;
15712
15713 ast_mutex_lock(&iflock);
15714 for (p = iflist; p; p = p->next) {
15715 if (p->channel == channel) {
15716 break;
15717 }
15718 }
15719 ast_mutex_unlock(&iflock);
15720 return p;
15721 }
15722
15723
15724
15725
15726
15727
15728
15729
15730
15731
15732 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15733 {
15734 int chan_num;
15735
15736 if (sscanf(channel, "%30d", &chan_num) != 1) {
15737
15738 return NULL;
15739 }
15740
15741 return find_channel(chan_num);
15742 }
15743
15744 static int action_dahdidndon(struct mansession *s, const struct message *m)
15745 {
15746 struct dahdi_pvt *p;
15747 const char *channel = astman_get_header(m, "DAHDIChannel");
15748
15749 if (ast_strlen_zero(channel)) {
15750 astman_send_error(s, m, "No channel specified");
15751 return 0;
15752 }
15753 p = find_channel_from_str(channel);
15754 if (!p) {
15755 astman_send_error(s, m, "No such channel");
15756 return 0;
15757 }
15758 dahdi_dnd(p, 1);
15759 astman_send_ack(s, m, "DND Enabled");
15760 return 0;
15761 }
15762
15763 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15764 {
15765 struct dahdi_pvt *p;
15766 const char *channel = astman_get_header(m, "DAHDIChannel");
15767
15768 if (ast_strlen_zero(channel)) {
15769 astman_send_error(s, m, "No channel specified");
15770 return 0;
15771 }
15772 p = find_channel_from_str(channel);
15773 if (!p) {
15774 astman_send_error(s, m, "No such channel");
15775 return 0;
15776 }
15777 dahdi_dnd(p, 0);
15778 astman_send_ack(s, m, "DND Disabled");
15779 return 0;
15780 }
15781
15782 static int action_transfer(struct mansession *s, const struct message *m)
15783 {
15784 struct dahdi_pvt *p;
15785 const char *channel = astman_get_header(m, "DAHDIChannel");
15786
15787 if (ast_strlen_zero(channel)) {
15788 astman_send_error(s, m, "No channel specified");
15789 return 0;
15790 }
15791 p = find_channel_from_str(channel);
15792 if (!p) {
15793 astman_send_error(s, m, "No such channel");
15794 return 0;
15795 }
15796 if (!analog_lib_handles(p->sig, 0, 0)) {
15797 astman_send_error(s, m, "Channel signaling is not analog");
15798 return 0;
15799 }
15800 dahdi_fake_event(p,TRANSFER);
15801 astman_send_ack(s, m, "DAHDITransfer");
15802 return 0;
15803 }
15804
15805 static int action_transferhangup(struct mansession *s, const struct message *m)
15806 {
15807 struct dahdi_pvt *p;
15808 const char *channel = astman_get_header(m, "DAHDIChannel");
15809
15810 if (ast_strlen_zero(channel)) {
15811 astman_send_error(s, m, "No channel specified");
15812 return 0;
15813 }
15814 p = find_channel_from_str(channel);
15815 if (!p) {
15816 astman_send_error(s, m, "No such channel");
15817 return 0;
15818 }
15819 if (!analog_lib_handles(p->sig, 0, 0)) {
15820 astman_send_error(s, m, "Channel signaling is not analog");
15821 return 0;
15822 }
15823 dahdi_fake_event(p,HANGUP);
15824 astman_send_ack(s, m, "DAHDIHangup");
15825 return 0;
15826 }
15827
15828 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15829 {
15830 struct dahdi_pvt *p;
15831 const char *channel = astman_get_header(m, "DAHDIChannel");
15832 const char *number = astman_get_header(m, "Number");
15833 int i;
15834
15835 if (ast_strlen_zero(channel)) {
15836 astman_send_error(s, m, "No channel specified");
15837 return 0;
15838 }
15839 if (ast_strlen_zero(number)) {
15840 astman_send_error(s, m, "No number specified");
15841 return 0;
15842 }
15843 p = find_channel_from_str(channel);
15844 if (!p) {
15845 astman_send_error(s, m, "No such channel");
15846 return 0;
15847 }
15848 if (!p->owner) {
15849 astman_send_error(s, m, "Channel does not have it's owner");
15850 return 0;
15851 }
15852 for (i = 0; i < strlen(number); i++) {
15853 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15854 dahdi_queue_frame(p, &f);
15855 }
15856 astman_send_ack(s, m, "DAHDIDialOffhook");
15857 return 0;
15858 }
15859
15860 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15861 {
15862 struct dahdi_pvt *tmp = NULL;
15863 const char *id = astman_get_header(m, "ActionID");
15864 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15865 char idText[256] = "";
15866 int channels = 0;
15867 int dahdichanquery;
15868
15869 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15870
15871 dahdichanquery = -1;
15872 }
15873
15874 astman_send_ack(s, m, "DAHDI channel status will follow");
15875 if (!ast_strlen_zero(id))
15876 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15877
15878 ast_mutex_lock(&iflock);
15879
15880 for (tmp = iflist; tmp; tmp = tmp->next) {
15881 if (tmp->channel > 0) {
15882 int alm;
15883
15884
15885 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15886 continue;
15887
15888 alm = get_alarms(tmp);
15889 channels++;
15890 if (tmp->owner) {
15891
15892 astman_append(s,
15893 "Event: DAHDIShowChannels\r\n"
15894 "DAHDIChannel: %d\r\n"
15895 "Channel: %s\r\n"
15896 "Uniqueid: %s\r\n"
15897 "AccountCode: %s\r\n"
15898 "Signalling: %s\r\n"
15899 "SignallingCode: %d\r\n"
15900 "Context: %s\r\n"
15901 "DND: %s\r\n"
15902 "Alarm: %s\r\n"
15903 "%s"
15904 "\r\n",
15905 tmp->channel,
15906 tmp->owner->name,
15907 tmp->owner->uniqueid,
15908 tmp->owner->accountcode,
15909 sig2str(tmp->sig),
15910 tmp->sig,
15911 tmp->context,
15912 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15913 alarm2str(alm), idText);
15914 } else {
15915 astman_append(s,
15916 "Event: DAHDIShowChannels\r\n"
15917 "DAHDIChannel: %d\r\n"
15918 "Signalling: %s\r\n"
15919 "SignallingCode: %d\r\n"
15920 "Context: %s\r\n"
15921 "DND: %s\r\n"
15922 "Alarm: %s\r\n"
15923 "%s"
15924 "\r\n",
15925 tmp->channel, sig2str(tmp->sig), tmp->sig,
15926 tmp->context,
15927 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15928 alarm2str(alm), idText);
15929 }
15930 }
15931 }
15932
15933 ast_mutex_unlock(&iflock);
15934
15935 astman_append(s,
15936 "Event: DAHDIShowChannelsComplete\r\n"
15937 "%s"
15938 "Items: %d\r\n"
15939 "\r\n",
15940 idText,
15941 channels);
15942 return 0;
15943 }
15944
15945 #if defined(HAVE_SS7)
15946 static int linkset_addsigchan(int sigchan)
15947 {
15948 struct dahdi_ss7 *link;
15949 int res;
15950 int curfd;
15951 struct dahdi_params params;
15952 struct dahdi_bufferinfo bi;
15953 struct dahdi_spaninfo si;
15954
15955 if (sigchan < 0) {
15956 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15957 return -1;
15958 }
15959 if (cur_ss7type < 0) {
15960 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15961 return -1;
15962 }
15963 if (cur_pointcode < 0) {
15964 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15965 return -1;
15966 }
15967 if (cur_adjpointcode < 0) {
15968 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15969 return -1;
15970 }
15971 if (cur_defaultdpc < 0) {
15972 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15973 return -1;
15974 }
15975 if (cur_networkindicator < 0) {
15976 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15977 return -1;
15978 }
15979 link = ss7_resolve_linkset(cur_linkset);
15980 if (!link) {
15981 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15982 return -1;
15983 }
15984 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15985 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15986 return -1;
15987 }
15988
15989 curfd = link->ss7.numsigchans;
15990
15991
15992 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15993 if (link->ss7.fds[curfd] < 0) {
15994 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15995 strerror(errno));
15996 return -1;
15997 }
15998 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15999 dahdi_close_ss7_fd(link, curfd);
16000 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16001 strerror(errno));
16002 return -1;
16003 }
16004
16005
16006 memset(¶ms, 0, sizeof(params));
16007 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16008 if (res) {
16009 dahdi_close_ss7_fd(link, curfd);
16010 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16011 strerror(errno));
16012 return -1;
16013 }
16014 if (params.sigtype != DAHDI_SIG_HDLCFCS
16015 && params.sigtype != DAHDI_SIG_HARDHDLC
16016 && params.sigtype != DAHDI_SIG_MTP2) {
16017 dahdi_close_ss7_fd(link, curfd);
16018 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16019 return -1;
16020 }
16021
16022
16023 memset(&bi, 0, sizeof(bi));
16024 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16025 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16026 bi.numbufs = 32;
16027 bi.bufsize = 512;
16028 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16029 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16030 sigchan, strerror(errno));
16031 dahdi_close_ss7_fd(link, curfd);
16032 return -1;
16033 }
16034
16035
16036 memset(&si, 0, sizeof(si));
16037 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16038 if (res) {
16039 dahdi_close_ss7_fd(link, curfd);
16040 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16041 strerror(errno));
16042 }
16043
16044 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16045 (params.sigtype == DAHDI_SIG_MTP2)
16046 ? SS7_TRANSPORT_DAHDIMTP2
16047 : SS7_TRANSPORT_DAHDIDCHAN,
16048 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16049 if (res) {
16050 dahdi_close_ss7_fd(link, curfd);
16051 return -1;
16052 }
16053
16054 ++link->ss7.numsigchans;
16055
16056 return 0;
16057 }
16058 #endif
16059
16060 #if defined(HAVE_SS7)
16061 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16062 {
16063 int span;
16064 switch (cmd) {
16065 case CLI_INIT:
16066 e->command = "ss7 set debug {on|off} linkset";
16067 e->usage =
16068 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16069 " Enables debugging on a given SS7 linkset\n";
16070 return NULL;
16071 case CLI_GENERATE:
16072 return NULL;
16073 }
16074 if (a->argc < 6)
16075 return CLI_SHOWUSAGE;
16076 span = atoi(a->argv[5]);
16077 if ((span < 1) || (span > NUM_SPANS)) {
16078 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16079 return CLI_SUCCESS;
16080 }
16081 if (!linksets[span-1].ss7.ss7) {
16082 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16083 } else {
16084 if (!strcasecmp(a->argv[3], "on")) {
16085 linksets[span - 1].ss7.debug = 1;
16086 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16087 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16088 } else {
16089 linksets[span - 1].ss7.debug = 0;
16090 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16091 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16092 }
16093 }
16094
16095 return CLI_SUCCESS;
16096 }
16097 #endif
16098
16099 #if defined(HAVE_SS7)
16100 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16101 {
16102 int linkset, cic;
16103 int blocked = -1, i;
16104 switch (cmd) {
16105 case CLI_INIT:
16106 e->command = "ss7 block cic";
16107 e->usage =
16108 "Usage: ss7 block cic <linkset> <CIC>\n"
16109 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16110 return NULL;
16111 case CLI_GENERATE:
16112 return NULL;
16113 }
16114 if (a->argc == 5)
16115 linkset = atoi(a->argv[3]);
16116 else
16117 return CLI_SHOWUSAGE;
16118
16119 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16120 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16121 return CLI_SUCCESS;
16122 }
16123
16124 if (!linksets[linkset-1].ss7.ss7) {
16125 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16126 return CLI_SUCCESS;
16127 }
16128
16129 cic = atoi(a->argv[4]);
16130
16131 if (cic < 1) {
16132 ast_cli(a->fd, "Invalid CIC specified!\n");
16133 return CLI_SUCCESS;
16134 }
16135
16136 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16137 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16138 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16139 if (!blocked) {
16140 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16141 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16142 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16143 }
16144 }
16145 }
16146
16147 if (blocked < 0) {
16148 ast_cli(a->fd, "Invalid CIC specified!\n");
16149 return CLI_SUCCESS;
16150 }
16151
16152 if (!blocked)
16153 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16154 else
16155 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16156
16157
16158 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16159
16160 return CLI_SUCCESS;
16161 }
16162 #endif
16163
16164 #if defined(HAVE_SS7)
16165 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16166 {
16167 int linkset;
16168 int i;
16169 switch (cmd) {
16170 case CLI_INIT:
16171 e->command = "ss7 block linkset";
16172 e->usage =
16173 "Usage: ss7 block linkset <linkset number>\n"
16174 " Sends a remote blocking request for all CICs on the given linkset\n";
16175 return NULL;
16176 case CLI_GENERATE:
16177 return NULL;
16178 }
16179 if (a->argc == 4)
16180 linkset = atoi(a->argv[3]);
16181 else
16182 return CLI_SHOWUSAGE;
16183
16184 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16185 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16186 return CLI_SUCCESS;
16187 }
16188
16189 if (!linksets[linkset-1].ss7.ss7) {
16190 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16191 return CLI_SUCCESS;
16192 }
16193
16194 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16195 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16196 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16197 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16198 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16199 }
16200
16201
16202 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16203
16204 return CLI_SUCCESS;
16205 }
16206 #endif
16207
16208 #if defined(HAVE_SS7)
16209 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16210 {
16211 int linkset, cic;
16212 int i, blocked = -1;
16213 switch (cmd) {
16214 case CLI_INIT:
16215 e->command = "ss7 unblock cic";
16216 e->usage =
16217 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16218 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16219 return NULL;
16220 case CLI_GENERATE:
16221 return NULL;
16222 }
16223
16224 if (a->argc == 5)
16225 linkset = atoi(a->argv[3]);
16226 else
16227 return CLI_SHOWUSAGE;
16228
16229 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16230 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16231 return CLI_SUCCESS;
16232 }
16233
16234 if (!linksets[linkset-1].ss7.ss7) {
16235 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16236 return CLI_SUCCESS;
16237 }
16238
16239 cic = atoi(a->argv[4]);
16240
16241 if (cic < 1) {
16242 ast_cli(a->fd, "Invalid CIC specified!\n");
16243 return CLI_SUCCESS;
16244 }
16245
16246 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16247 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16248 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16249 if (blocked) {
16250 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16251 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16252 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16253 }
16254 }
16255 }
16256
16257 if (blocked > 0)
16258 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16259
16260
16261 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16262
16263 return CLI_SUCCESS;
16264 }
16265 #endif
16266
16267 #if defined(HAVE_SS7)
16268 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16269 {
16270 int linkset;
16271 int i;
16272 switch (cmd) {
16273 case CLI_INIT:
16274 e->command = "ss7 unblock linkset";
16275 e->usage =
16276 "Usage: ss7 unblock linkset <linkset number>\n"
16277 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16278 return NULL;
16279 case CLI_GENERATE:
16280 return NULL;
16281 }
16282
16283 if (a->argc == 4)
16284 linkset = atoi(a->argv[3]);
16285 else
16286 return CLI_SHOWUSAGE;
16287
16288 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16289 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16290 return CLI_SUCCESS;
16291 }
16292
16293 if (!linksets[linkset-1].ss7.ss7) {
16294 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16295 return CLI_SUCCESS;
16296 }
16297
16298 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16299 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16300 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16301 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16302 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16303 }
16304
16305
16306 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16307
16308 return CLI_SUCCESS;
16309 }
16310 #endif
16311
16312 #if defined(HAVE_SS7)
16313 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16314 {
16315 int linkset;
16316 struct sig_ss7_linkset *ss7;
16317 switch (cmd) {
16318 case CLI_INIT:
16319 e->command = "ss7 show linkset";
16320 e->usage =
16321 "Usage: ss7 show linkset <span>\n"
16322 " Shows the status of an SS7 linkset.\n";
16323 return NULL;
16324 case CLI_GENERATE:
16325 return NULL;
16326 }
16327
16328 if (a->argc < 4)
16329 return CLI_SHOWUSAGE;
16330 linkset = atoi(a->argv[3]);
16331 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16332 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16333 return CLI_SUCCESS;
16334 }
16335 ss7 = &linksets[linkset - 1].ss7;
16336 if (!ss7->ss7) {
16337 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16338 return CLI_SUCCESS;
16339 }
16340
16341 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16342
16343 return CLI_SUCCESS;
16344 }
16345 #endif
16346
16347 #if defined(HAVE_SS7)
16348 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16349 {
16350 int linkset;
16351
16352 switch (cmd) {
16353 case CLI_INIT:
16354 e->command = "ss7 show channels";
16355 e->usage =
16356 "Usage: ss7 show channels\n"
16357 " Displays SS7 channel information at a glance.\n";
16358 return NULL;
16359 case CLI_GENERATE:
16360 return NULL;
16361 }
16362
16363 if (a->argc != 3)
16364 return CLI_SHOWUSAGE;
16365
16366 sig_ss7_cli_show_channels_header(a->fd);
16367 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16368 if (linksets[linkset].ss7.ss7) {
16369 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16370 }
16371 }
16372 return CLI_SUCCESS;
16373 }
16374 #endif
16375
16376 #if defined(HAVE_SS7)
16377 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16378 {
16379 switch (cmd) {
16380 case CLI_INIT:
16381 e->command = "ss7 show version";
16382 e->usage =
16383 "Usage: ss7 show version\n"
16384 " Show the libss7 version\n";
16385 return NULL;
16386 case CLI_GENERATE:
16387 return NULL;
16388 }
16389
16390 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16391
16392 return CLI_SUCCESS;
16393 }
16394 #endif
16395
16396 #if defined(HAVE_SS7)
16397 static struct ast_cli_entry dahdi_ss7_cli[] = {
16398 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16399 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16400 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16401 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16402 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16403 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16404 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16405 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16406 };
16407 #endif
16408
16409 #if defined(HAVE_PRI)
16410 #if defined(HAVE_PRI_CCSS)
16411
16412
16413
16414
16415
16416
16417
16418
16419
16420
16421
16422
16423
16424
16425
16426
16427
16428 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16429 {
16430 struct dahdi_pvt *pvt;
16431 struct sig_pri_chan *pvt_chan;
16432 int res;
16433
16434 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16435
16436 pvt = chan->tech_pvt;
16437 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16438 pvt_chan = pvt->sig_pvt;
16439 } else {
16440 pvt_chan = NULL;
16441 }
16442 if (!pvt_chan) {
16443 return -1;
16444 }
16445
16446 ast_module_ref(ast_module_info->self);
16447
16448 res = sig_pri_cc_agent_init(agent, pvt_chan);
16449 if (res) {
16450 ast_module_unref(ast_module_info->self);
16451 }
16452 return res;
16453 }
16454 #endif
16455 #endif
16456
16457 #if defined(HAVE_PRI)
16458 #if defined(HAVE_PRI_CCSS)
16459
16460
16461
16462
16463
16464
16465
16466
16467
16468
16469
16470
16471
16472 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16473 {
16474 sig_pri_cc_agent_destructor(agent);
16475
16476 ast_module_unref(ast_module_info->self);
16477 }
16478 #endif
16479 #endif
16480
16481 #if defined(HAVE_PRI)
16482 #if defined(HAVE_PRI_CCSS)
16483 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16484 .type = dahdi_pri_cc_type,
16485 .init = dahdi_pri_cc_agent_init,
16486 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16487 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16488 .respond = sig_pri_cc_agent_req_rsp,
16489 .status_request = sig_pri_cc_agent_status_req,
16490 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16491 .party_b_free = sig_pri_cc_agent_party_b_free,
16492 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16493 .callee_available = sig_pri_cc_agent_callee_available,
16494 .destructor = dahdi_pri_cc_agent_destructor,
16495 };
16496 #endif
16497 #endif
16498
16499 #if defined(HAVE_PRI)
16500 #if defined(HAVE_PRI_CCSS)
16501 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16502 .type = dahdi_pri_cc_type,
16503 .request_cc = sig_pri_cc_monitor_req_cc,
16504 .suspend = sig_pri_cc_monitor_suspend,
16505 .unsuspend = sig_pri_cc_monitor_unsuspend,
16506 .status_response = sig_pri_cc_monitor_status_rsp,
16507 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16508 .destructor = sig_pri_cc_monitor_destructor,
16509 };
16510 #endif
16511 #endif
16512
16513 static int __unload_module(void)
16514 {
16515 struct dahdi_pvt *p;
16516 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16517 int i, j;
16518 #endif
16519
16520 #ifdef HAVE_PRI
16521 for (i = 0; i < NUM_SPANS; i++) {
16522 if (pris[i].pri.master != AST_PTHREADT_NULL)
16523 pthread_cancel(pris[i].pri.master);
16524 }
16525 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16526 ast_unregister_application(dahdi_send_keypad_facility_app);
16527 #ifdef HAVE_PRI_PROG_W_CAUSE
16528 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16529 #endif
16530 #endif
16531 #if defined(HAVE_SS7)
16532 for (i = 0; i < NUM_SPANS; i++) {
16533 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16534 pthread_cancel(linksets[i].ss7.master);
16535 }
16536 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16537 #endif
16538 #if defined(HAVE_OPENR2)
16539 dahdi_r2_destroy_links();
16540 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16541 ast_unregister_application(dahdi_accept_r2_call_app);
16542 #endif
16543
16544 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16545 ast_manager_unregister("DAHDIDialOffhook");
16546 ast_manager_unregister("DAHDIHangup");
16547 ast_manager_unregister("DAHDITransfer");
16548 ast_manager_unregister("DAHDIDNDoff");
16549 ast_manager_unregister("DAHDIDNDon");
16550 ast_manager_unregister("DAHDIShowChannels");
16551 ast_manager_unregister("DAHDIRestart");
16552 ast_data_unregister(NULL);
16553 ast_channel_unregister(&dahdi_tech);
16554
16555
16556 ast_mutex_lock(&iflock);
16557 for (p = iflist; p; p = p->next) {
16558 if (p->owner)
16559 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16560 }
16561 ast_mutex_unlock(&iflock);
16562
16563 ast_mutex_lock(&monlock);
16564 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16565 pthread_cancel(monitor_thread);
16566 pthread_kill(monitor_thread, SIGURG);
16567 pthread_join(monitor_thread, NULL);
16568 }
16569 monitor_thread = AST_PTHREADT_STOP;
16570 ast_mutex_unlock(&monlock);
16571
16572 destroy_all_channels();
16573
16574 #if defined(HAVE_PRI)
16575 for (i = 0; i < NUM_SPANS; i++) {
16576 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16577 pthread_join(pris[i].pri.master, NULL);
16578 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16579 dahdi_close_pri_fd(&(pris[i]), j);
16580 }
16581 sig_pri_stop_pri(&pris[i].pri);
16582 }
16583 #if defined(HAVE_PRI_CCSS)
16584 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16585 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16586 #endif
16587 sig_pri_unload();
16588 #endif
16589
16590 #if defined(HAVE_SS7)
16591 for (i = 0; i < NUM_SPANS; i++) {
16592 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16593 pthread_join(linksets[i].ss7.master, NULL);
16594 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16595 dahdi_close_ss7_fd(&(linksets[i]), j);
16596 }
16597 }
16598 #endif
16599 ast_cond_destroy(&ss_thread_complete);
16600 return 0;
16601 }
16602
16603 static int unload_module(void)
16604 {
16605 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16606 int y;
16607 #endif
16608 #ifdef HAVE_PRI
16609 for (y = 0; y < NUM_SPANS; y++)
16610 ast_mutex_destroy(&pris[y].pri.lock);
16611 #endif
16612 #if defined(HAVE_SS7)
16613 for (y = 0; y < NUM_SPANS; y++)
16614 ast_mutex_destroy(&linksets[y].ss7.lock);
16615 #endif
16616 return __unload_module();
16617 }
16618
16619 static void string_replace(char *str, int char1, int char2)
16620 {
16621 for (; *str; str++) {
16622 if (*str == char1) {
16623 *str = char2;
16624 }
16625 }
16626 }
16627
16628 static char *parse_spanchan(char *chanstr, char **subdir)
16629 {
16630 char *p;
16631
16632 if ((p = strrchr(chanstr, '!')) == NULL) {
16633 *subdir = NULL;
16634 return chanstr;
16635 }
16636 *p++ = '\0';
16637 string_replace(chanstr, '!', '/');
16638 *subdir = chanstr;
16639 return p;
16640 }
16641
16642 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16643 {
16644 char *c, *chan;
16645 char *subdir;
16646 int x, start, finish;
16647 struct dahdi_pvt *tmp;
16648
16649 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16650 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16651 return -1;
16652 }
16653
16654 c = ast_strdupa(value);
16655 c = parse_spanchan(c, &subdir);
16656
16657 while ((chan = strsep(&c, ","))) {
16658 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16659
16660 } else if (sscanf(chan, "%30d", &start)) {
16661
16662 finish = start;
16663 } else if (!strcasecmp(chan, "pseudo")) {
16664 finish = start = CHAN_PSEUDO;
16665 if (found_pseudo)
16666 *found_pseudo = 1;
16667 } else {
16668 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16669 return -1;
16670 }
16671 if (finish < start) {
16672 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16673 x = finish;
16674 finish = start;
16675 start = x;
16676 }
16677
16678 for (x = start; x <= finish; x++) {
16679 char fn[PATH_MAX];
16680 int real_channel = x;
16681
16682 if (!ast_strlen_zero(subdir)) {
16683 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16684 if (real_channel < 0) {
16685 if (conf->ignore_failed_channels) {
16686 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16687 subdir, x, real_channel);
16688 continue;
16689 } else {
16690 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16691 subdir, x, real_channel);
16692 return -1;
16693 }
16694 }
16695 }
16696 tmp = mkintf(real_channel, conf, reload);
16697
16698 if (tmp) {
16699 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16700 } else {
16701 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16702 (reload == 1) ? "reconfigure" : "register", value);
16703 return -1;
16704 }
16705 }
16706 }
16707
16708 return 0;
16709 }
16710
16711
16712
16713 #define MAX_CHANLIST_LEN 80
16714
16715 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16716 {
16717 char *parse = ast_strdupa(data);
16718 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16719 unsigned int param_count;
16720 unsigned int x;
16721
16722 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16723 return;
16724
16725 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16726
16727
16728
16729 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16730
16731 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16732 confp->chan.echocancel.head.tap_length = x;
16733 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16734 confp->chan.echocancel.head.tap_length = 128;
16735
16736
16737
16738 for (x = 1; x < param_count; x++) {
16739 struct {
16740 char *name;
16741 char *value;
16742 } param;
16743
16744 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16745 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16746 continue;
16747 }
16748
16749 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16750 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16751 continue;
16752 }
16753
16754 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16755
16756 if (param.value) {
16757 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16758 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16759 continue;
16760 }
16761 }
16762 confp->chan.echocancel.head.param_count++;
16763 }
16764 }
16765
16766
16767 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16768
16769 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16770
16771 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16772 {
16773 struct dahdi_pvt *tmp;
16774 int y;
16775 int found_pseudo = 0;
16776 struct ast_variable *dahdichan = NULL;
16777
16778 for (; v; v = v->next) {
16779 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16780 continue;
16781
16782
16783 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16784 if (options & PROC_DAHDI_OPT_NOCHAN) {
16785 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16786 continue;
16787 }
16788 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16789 if (confp->ignore_failed_channels) {
16790 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16791 continue;
16792 } else {
16793 return -1;
16794 }
16795 }
16796 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16797 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16798 confp->ignore_failed_channels = ast_true(v->value);
16799 } else if (!strcasecmp(v->name, "buffers")) {
16800 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16801 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16802 confp->chan.buf_no = numbufs;
16803 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16804 }
16805 } else if (!strcasecmp(v->name, "faxbuffers")) {
16806 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16807 confp->chan.usefaxbuffers = 1;
16808 }
16809 } else if (!strcasecmp(v->name, "dahdichan")) {
16810
16811 dahdichan = v;
16812 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16813 usedistinctiveringdetection = ast_true(v->value);
16814 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16815 distinctiveringaftercid = ast_true(v->value);
16816 } else if (!strcasecmp(v->name, "dring1context")) {
16817 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16818 } else if (!strcasecmp(v->name, "dring2context")) {
16819 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16820 } else if (!strcasecmp(v->name, "dring3context")) {
16821 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16822 } else if (!strcasecmp(v->name, "dring1range")) {
16823 confp->chan.drings.ringnum[0].range = atoi(v->value);
16824 } else if (!strcasecmp(v->name, "dring2range")) {
16825 confp->chan.drings.ringnum[1].range = atoi(v->value);
16826 } else if (!strcasecmp(v->name, "dring3range")) {
16827 confp->chan.drings.ringnum[2].range = atoi(v->value);
16828 } else if (!strcasecmp(v->name, "dring1")) {
16829 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]);
16830 } else if (!strcasecmp(v->name, "dring2")) {
16831 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]);
16832 } else if (!strcasecmp(v->name, "dring3")) {
16833 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]);
16834 } else if (!strcasecmp(v->name, "usecallerid")) {
16835 confp->chan.use_callerid = ast_true(v->value);
16836 } else if (!strcasecmp(v->name, "cidsignalling")) {
16837 if (!strcasecmp(v->value, "bell"))
16838 confp->chan.cid_signalling = CID_SIG_BELL;
16839 else if (!strcasecmp(v->value, "v23"))
16840 confp->chan.cid_signalling = CID_SIG_V23;
16841 else if (!strcasecmp(v->value, "dtmf"))
16842 confp->chan.cid_signalling = CID_SIG_DTMF;
16843 else if (!strcasecmp(v->value, "smdi"))
16844 confp->chan.cid_signalling = CID_SIG_SMDI;
16845 else if (!strcasecmp(v->value, "v23_jp"))
16846 confp->chan.cid_signalling = CID_SIG_V23_JP;
16847 else if (ast_true(v->value))
16848 confp->chan.cid_signalling = CID_SIG_BELL;
16849 } else if (!strcasecmp(v->name, "cidstart")) {
16850 if (!strcasecmp(v->value, "ring"))
16851 confp->chan.cid_start = CID_START_RING;
16852 else if (!strcasecmp(v->value, "polarity_in"))
16853 confp->chan.cid_start = CID_START_POLARITY_IN;
16854 else if (!strcasecmp(v->value, "polarity"))
16855 confp->chan.cid_start = CID_START_POLARITY;
16856 else if (!strcasecmp(v->value, "dtmf"))
16857 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16858 else if (ast_true(v->value))
16859 confp->chan.cid_start = CID_START_RING;
16860 } else if (!strcasecmp(v->name, "threewaycalling")) {
16861 confp->chan.threewaycalling = ast_true(v->value);
16862 } else if (!strcasecmp(v->name, "cancallforward")) {
16863 confp->chan.cancallforward = ast_true(v->value);
16864 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16865 if (ast_true(v->value))
16866 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16867 else
16868 confp->chan.dtmfrelax = 0;
16869 } else if (!strcasecmp(v->name, "mailbox")) {
16870 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16871 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16872 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16873 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16874 }
16875 } else if (!strcasecmp(v->name, "adsi")) {
16876 confp->chan.adsi = ast_true(v->value);
16877 } else if (!strcasecmp(v->name, "usesmdi")) {
16878 confp->chan.use_smdi = ast_true(v->value);
16879 } else if (!strcasecmp(v->name, "smdiport")) {
16880 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16881 } else if (!strcasecmp(v->name, "transfer")) {
16882 confp->chan.transfer = ast_true(v->value);
16883 } else if (!strcasecmp(v->name, "canpark")) {
16884 confp->chan.canpark = ast_true(v->value);
16885 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16886 confp->chan.echocanbridged = ast_true(v->value);
16887 } else if (!strcasecmp(v->name, "busydetect")) {
16888 confp->chan.busydetect = ast_true(v->value);
16889 } else if (!strcasecmp(v->name, "busycount")) {
16890 confp->chan.busycount = atoi(v->value);
16891 } else if (!strcasecmp(v->name, "busypattern")) {
16892 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16893 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16894 }
16895 } else if (!strcasecmp(v->name, "callprogress")) {
16896 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16897 if (ast_true(v->value))
16898 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16899 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16900 confp->chan.waitfordialtone = atoi(v->value);
16901 } else if (!strcasecmp(v->name, "faxdetect")) {
16902 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16903 if (!strcasecmp(v->value, "incoming")) {
16904 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16905 } else if (!strcasecmp(v->value, "outgoing")) {
16906 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16907 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16908 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16909 } else if (!strcasecmp(v->name, "echocancel")) {
16910 process_echocancel(confp, v->value, v->lineno);
16911 } else if (!strcasecmp(v->name, "echotraining")) {
16912 if (sscanf(v->value, "%30d", &y) == 1) {
16913 if ((y < 10) || (y > 4000)) {
16914 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16915 } else {
16916 confp->chan.echotraining = y;
16917 }
16918 } else if (ast_true(v->value)) {
16919 confp->chan.echotraining = 400;
16920 } else
16921 confp->chan.echotraining = 0;
16922 } else if (!strcasecmp(v->name, "hidecallerid")) {
16923 confp->chan.hidecallerid = ast_true(v->value);
16924 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16925 confp->chan.hidecalleridname = ast_true(v->value);
16926 } else if (!strcasecmp(v->name, "pulsedial")) {
16927 confp->chan.pulse = ast_true(v->value);
16928 } else if (!strcasecmp(v->name, "callreturn")) {
16929 confp->chan.callreturn = ast_true(v->value);
16930 } else if (!strcasecmp(v->name, "callwaiting")) {
16931 confp->chan.callwaiting = ast_true(v->value);
16932 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16933 confp->chan.callwaitingcallerid = ast_true(v->value);
16934 } else if (!strcasecmp(v->name, "context")) {
16935 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16936 } else if (!strcasecmp(v->name, "language")) {
16937 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16938 } else if (!strcasecmp(v->name, "progzone")) {
16939 ast_copy_string(progzone, v->value, sizeof(progzone));
16940 } else if (!strcasecmp(v->name, "mohinterpret")
16941 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16942 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16943 } else if (!strcasecmp(v->name, "mohsuggest")) {
16944 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16945 } else if (!strcasecmp(v->name, "parkinglot")) {
16946 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16947 } else if (!strcasecmp(v->name, "stripmsd")) {
16948 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16949 confp->chan.stripmsd = atoi(v->value);
16950 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16951 numbufs = atoi(v->value);
16952 } else if (!strcasecmp(v->name, "group")) {
16953 confp->chan.group = ast_get_group(v->value);
16954 } else if (!strcasecmp(v->name, "callgroup")) {
16955 if (!strcasecmp(v->value, "none"))
16956 confp->chan.callgroup = 0;
16957 else
16958 confp->chan.callgroup = ast_get_group(v->value);
16959 } else if (!strcasecmp(v->name, "pickupgroup")) {
16960 if (!strcasecmp(v->value, "none"))
16961 confp->chan.pickupgroup = 0;
16962 else
16963 confp->chan.pickupgroup = ast_get_group(v->value);
16964 } else if (!strcasecmp(v->name, "setvar")) {
16965 char *varname = ast_strdupa(v->value), *varval = NULL;
16966 struct ast_variable *tmpvar;
16967 if (varname && (varval = strchr(varname, '='))) {
16968 *varval++ = '\0';
16969 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16970 tmpvar->next = confp->chan.vars;
16971 confp->chan.vars = tmpvar;
16972 }
16973 }
16974 } else if (!strcasecmp(v->name, "immediate")) {
16975 confp->chan.immediate = ast_true(v->value);
16976 } else if (!strcasecmp(v->name, "transfertobusy")) {
16977 confp->chan.transfertobusy = ast_true(v->value);
16978 } else if (!strcasecmp(v->name, "mwimonitor")) {
16979 confp->chan.mwimonitor_neon = 0;
16980 confp->chan.mwimonitor_fsk = 0;
16981 confp->chan.mwimonitor_rpas = 0;
16982 if (strcasestr(v->value, "fsk")) {
16983 confp->chan.mwimonitor_fsk = 1;
16984 }
16985 if (strcasestr(v->value, "rpas")) {
16986 confp->chan.mwimonitor_rpas = 1;
16987 }
16988 if (strcasestr(v->value, "neon")) {
16989 confp->chan.mwimonitor_neon = 1;
16990 }
16991
16992 if (ast_true(v->value)) {
16993 confp->chan.mwimonitor_fsk = 1;
16994 }
16995 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16996 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16997 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16998 }
16999 } else if (!strcasecmp(v->name, "rxgain")) {
17000 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17001 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17002 }
17003 } else if (!strcasecmp(v->name, "txgain")) {
17004 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17005 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17006 }
17007 } else if (!strcasecmp(v->name, "txdrc")) {
17008 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17009 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17010 }
17011 } else if (!strcasecmp(v->name, "rxdrc")) {
17012 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17013 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17014 }
17015 } else if (!strcasecmp(v->name, "tonezone")) {
17016 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17017 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17018 }
17019 } else if (!strcasecmp(v->name, "callerid")) {
17020 if (!strcasecmp(v->value, "asreceived")) {
17021 confp->chan.cid_num[0] = '\0';
17022 confp->chan.cid_name[0] = '\0';
17023 } else {
17024 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17025 }
17026 } else if (!strcasecmp(v->name, "fullname")) {
17027 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17028 } else if (!strcasecmp(v->name, "cid_number")) {
17029 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17030 } else if (!strcasecmp(v->name, "cid_tag")) {
17031 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17032 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17033 confp->chan.dahditrcallerid = ast_true(v->value);
17034 } else if (!strcasecmp(v->name, "restrictcid")) {
17035 confp->chan.restrictcid = ast_true(v->value);
17036 } else if (!strcasecmp(v->name, "usecallingpres")) {
17037 confp->chan.use_callingpres = ast_true(v->value);
17038 } else if (!strcasecmp(v->name, "accountcode")) {
17039 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17040 } else if (!strcasecmp(v->name, "amaflags")) {
17041 y = ast_cdr_amaflags2int(v->value);
17042 if (y < 0)
17043 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17044 else
17045 confp->chan.amaflags = y;
17046 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17047 confp->chan.polarityonanswerdelay = atoi(v->value);
17048 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17049 confp->chan.answeronpolarityswitch = ast_true(v->value);
17050 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17051 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17052 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17053 confp->chan.sendcalleridafter = atoi(v->value);
17054 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17055 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17056 } else if (ast_cc_is_config_param(v->name)) {
17057 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17058 } else if (!strcasecmp(v->name, "mwisendtype")) {
17059 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17060 if (!strcasecmp(v->value, "rpas")) {
17061 mwisend_rpas = 1;
17062 } else {
17063 mwisend_rpas = 0;
17064 }
17065 #else
17066
17067 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17068 if (strcasestr(v->value, "nofsk")) {
17069 confp->chan.mwisend_fsk = 0;
17070 } else {
17071 confp->chan.mwisend_fsk = 1;
17072 }
17073 if (strcasestr(v->value, "rpas")) {
17074 confp->chan.mwisend_rpas = 1;
17075 } else {
17076 confp->chan.mwisend_rpas = 0;
17077 }
17078 if (strcasestr(v->value, "lrev")) {
17079 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17080 }
17081 if (strcasestr(v->value, "hvdc")) {
17082 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17083 }
17084 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17085 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17086 }
17087 #endif
17088 } else if (reload != 1) {
17089 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17090 int orig_radio = confp->chan.radio;
17091 int orig_outsigmod = confp->chan.outsigmod;
17092 int orig_auto = confp->is_sig_auto;
17093
17094 confp->chan.radio = 0;
17095 confp->chan.outsigmod = -1;
17096 confp->is_sig_auto = 0;
17097 if (!strcasecmp(v->value, "em")) {
17098 confp->chan.sig = SIG_EM;
17099 } else if (!strcasecmp(v->value, "em_e1")) {
17100 confp->chan.sig = SIG_EM_E1;
17101 } else if (!strcasecmp(v->value, "em_w")) {
17102 confp->chan.sig = SIG_EMWINK;
17103 } else if (!strcasecmp(v->value, "fxs_ls")) {
17104 confp->chan.sig = SIG_FXSLS;
17105 } else if (!strcasecmp(v->value, "fxs_gs")) {
17106 confp->chan.sig = SIG_FXSGS;
17107 } else if (!strcasecmp(v->value, "fxs_ks")) {
17108 confp->chan.sig = SIG_FXSKS;
17109 } else if (!strcasecmp(v->value, "fxo_ls")) {
17110 confp->chan.sig = SIG_FXOLS;
17111 } else if (!strcasecmp(v->value, "fxo_gs")) {
17112 confp->chan.sig = SIG_FXOGS;
17113 } else if (!strcasecmp(v->value, "fxo_ks")) {
17114 confp->chan.sig = SIG_FXOKS;
17115 } else if (!strcasecmp(v->value, "fxs_rx")) {
17116 confp->chan.sig = SIG_FXSKS;
17117 confp->chan.radio = 1;
17118 } else if (!strcasecmp(v->value, "fxo_rx")) {
17119 confp->chan.sig = SIG_FXOLS;
17120 confp->chan.radio = 1;
17121 } else if (!strcasecmp(v->value, "fxs_tx")) {
17122 confp->chan.sig = SIG_FXSLS;
17123 confp->chan.radio = 1;
17124 } else if (!strcasecmp(v->value, "fxo_tx")) {
17125 confp->chan.sig = SIG_FXOGS;
17126 confp->chan.radio = 1;
17127 } else if (!strcasecmp(v->value, "em_rx")) {
17128 confp->chan.sig = SIG_EM;
17129 confp->chan.radio = 1;
17130 } else if (!strcasecmp(v->value, "em_tx")) {
17131 confp->chan.sig = SIG_EM;
17132 confp->chan.radio = 1;
17133 } else if (!strcasecmp(v->value, "em_rxtx")) {
17134 confp->chan.sig = SIG_EM;
17135 confp->chan.radio = 2;
17136 } else if (!strcasecmp(v->value, "em_txrx")) {
17137 confp->chan.sig = SIG_EM;
17138 confp->chan.radio = 2;
17139 } else if (!strcasecmp(v->value, "sf")) {
17140 confp->chan.sig = SIG_SF;
17141 } else if (!strcasecmp(v->value, "sf_w")) {
17142 confp->chan.sig = SIG_SFWINK;
17143 } else if (!strcasecmp(v->value, "sf_featd")) {
17144 confp->chan.sig = SIG_FEATD;
17145 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17146 confp->chan.sig = SIG_FEATDMF;
17147 } else if (!strcasecmp(v->value, "sf_featb")) {
17148 confp->chan.sig = SIG_SF_FEATB;
17149 } else if (!strcasecmp(v->value, "sf")) {
17150 confp->chan.sig = SIG_SF;
17151 } else if (!strcasecmp(v->value, "sf_rx")) {
17152 confp->chan.sig = SIG_SF;
17153 confp->chan.radio = 1;
17154 } else if (!strcasecmp(v->value, "sf_tx")) {
17155 confp->chan.sig = SIG_SF;
17156 confp->chan.radio = 1;
17157 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17158 confp->chan.sig = SIG_SF;
17159 confp->chan.radio = 2;
17160 } else if (!strcasecmp(v->value, "sf_txrx")) {
17161 confp->chan.sig = SIG_SF;
17162 confp->chan.radio = 2;
17163 } else if (!strcasecmp(v->value, "featd")) {
17164 confp->chan.sig = SIG_FEATD;
17165 } else if (!strcasecmp(v->value, "featdmf")) {
17166 confp->chan.sig = SIG_FEATDMF;
17167 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17168 confp->chan.sig = SIG_FEATDMF_TA;
17169 } else if (!strcasecmp(v->value, "e911")) {
17170 confp->chan.sig = SIG_E911;
17171 } else if (!strcasecmp(v->value, "fgccama")) {
17172 confp->chan.sig = SIG_FGC_CAMA;
17173 } else if (!strcasecmp(v->value, "fgccamamf")) {
17174 confp->chan.sig = SIG_FGC_CAMAMF;
17175 } else if (!strcasecmp(v->value, "featb")) {
17176 confp->chan.sig = SIG_FEATB;
17177 #ifdef HAVE_PRI
17178 } else if (!strcasecmp(v->value, "pri_net")) {
17179 confp->chan.sig = SIG_PRI;
17180 confp->pri.pri.nodetype = PRI_NETWORK;
17181 } else if (!strcasecmp(v->value, "pri_cpe")) {
17182 confp->chan.sig = SIG_PRI;
17183 confp->pri.pri.nodetype = PRI_CPE;
17184 } else if (!strcasecmp(v->value, "bri_cpe")) {
17185 confp->chan.sig = SIG_BRI;
17186 confp->pri.pri.nodetype = PRI_CPE;
17187 } else if (!strcasecmp(v->value, "bri_net")) {
17188 confp->chan.sig = SIG_BRI;
17189 confp->pri.pri.nodetype = PRI_NETWORK;
17190 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17191 confp->chan.sig = SIG_BRI_PTMP;
17192 confp->pri.pri.nodetype = PRI_CPE;
17193 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17194 #if defined(HAVE_PRI_CALL_HOLD)
17195 confp->chan.sig = SIG_BRI_PTMP;
17196 confp->pri.pri.nodetype = PRI_NETWORK;
17197 #else
17198 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17199 #endif
17200 #endif
17201 #if defined(HAVE_SS7)
17202 } else if (!strcasecmp(v->value, "ss7")) {
17203 confp->chan.sig = SIG_SS7;
17204 #endif
17205 #ifdef HAVE_OPENR2
17206 } else if (!strcasecmp(v->value, "mfcr2")) {
17207 confp->chan.sig = SIG_MFCR2;
17208 #endif
17209 } else if (!strcasecmp(v->value, "auto")) {
17210 confp->is_sig_auto = 1;
17211 } else {
17212 confp->chan.outsigmod = orig_outsigmod;
17213 confp->chan.radio = orig_radio;
17214 confp->is_sig_auto = orig_auto;
17215 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17216 }
17217 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17218 if (!strcasecmp(v->value, "em")) {
17219 confp->chan.outsigmod = SIG_EM;
17220 } else if (!strcasecmp(v->value, "em_e1")) {
17221 confp->chan.outsigmod = SIG_EM_E1;
17222 } else if (!strcasecmp(v->value, "em_w")) {
17223 confp->chan.outsigmod = SIG_EMWINK;
17224 } else if (!strcasecmp(v->value, "sf")) {
17225 confp->chan.outsigmod = SIG_SF;
17226 } else if (!strcasecmp(v->value, "sf_w")) {
17227 confp->chan.outsigmod = SIG_SFWINK;
17228 } else if (!strcasecmp(v->value, "sf_featd")) {
17229 confp->chan.outsigmod = SIG_FEATD;
17230 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17231 confp->chan.outsigmod = SIG_FEATDMF;
17232 } else if (!strcasecmp(v->value, "sf_featb")) {
17233 confp->chan.outsigmod = SIG_SF_FEATB;
17234 } else if (!strcasecmp(v->value, "sf")) {
17235 confp->chan.outsigmod = SIG_SF;
17236 } else if (!strcasecmp(v->value, "featd")) {
17237 confp->chan.outsigmod = SIG_FEATD;
17238 } else if (!strcasecmp(v->value, "featdmf")) {
17239 confp->chan.outsigmod = SIG_FEATDMF;
17240 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17241 confp->chan.outsigmod = SIG_FEATDMF_TA;
17242 } else if (!strcasecmp(v->value, "e911")) {
17243 confp->chan.outsigmod = SIG_E911;
17244 } else if (!strcasecmp(v->value, "fgccama")) {
17245 confp->chan.outsigmod = SIG_FGC_CAMA;
17246 } else if (!strcasecmp(v->value, "fgccamamf")) {
17247 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17248 } else if (!strcasecmp(v->value, "featb")) {
17249 confp->chan.outsigmod = SIG_FEATB;
17250 } else {
17251 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17252 }
17253 #ifdef HAVE_PRI
17254 } else if (!strcasecmp(v->name, "pridialplan")) {
17255 if (!strcasecmp(v->value, "national")) {
17256 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17257 } else if (!strcasecmp(v->value, "unknown")) {
17258 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17259 } else if (!strcasecmp(v->value, "private")) {
17260 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17261 } else if (!strcasecmp(v->value, "international")) {
17262 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17263 } else if (!strcasecmp(v->value, "local")) {
17264 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17265 } else if (!strcasecmp(v->value, "dynamic")) {
17266 confp->pri.pri.dialplan = -1;
17267 } else if (!strcasecmp(v->value, "redundant")) {
17268 confp->pri.pri.dialplan = -2;
17269 } else {
17270 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17271 }
17272 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17273 if (!strcasecmp(v->value, "national")) {
17274 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17275 } else if (!strcasecmp(v->value, "unknown")) {
17276 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17277 } else if (!strcasecmp(v->value, "private")) {
17278 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17279 } else if (!strcasecmp(v->value, "international")) {
17280 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17281 } else if (!strcasecmp(v->value, "local")) {
17282 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17283 } else if (!strcasecmp(v->value, "dynamic")) {
17284 confp->pri.pri.localdialplan = -1;
17285 } else if (!strcasecmp(v->value, "redundant")) {
17286 confp->pri.pri.localdialplan = -2;
17287 } else {
17288 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17289 }
17290 } else if (!strcasecmp(v->name, "switchtype")) {
17291 if (!strcasecmp(v->value, "national"))
17292 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17293 else if (!strcasecmp(v->value, "ni1"))
17294 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17295 else if (!strcasecmp(v->value, "dms100"))
17296 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17297 else if (!strcasecmp(v->value, "4ess"))
17298 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17299 else if (!strcasecmp(v->value, "5ess"))
17300 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17301 else if (!strcasecmp(v->value, "euroisdn"))
17302 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17303 else if (!strcasecmp(v->value, "qsig"))
17304 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17305 else {
17306 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17307 return -1;
17308 }
17309 } else if (!strcasecmp(v->name, "msn")) {
17310 ast_copy_string(confp->pri.pri.msn_list, v->value,
17311 sizeof(confp->pri.pri.msn_list));
17312 } else if (!strcasecmp(v->name, "nsf")) {
17313 if (!strcasecmp(v->value, "sdn"))
17314 confp->pri.pri.nsf = PRI_NSF_SDN;
17315 else if (!strcasecmp(v->value, "megacom"))
17316 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17317 else if (!strcasecmp(v->value, "tollfreemegacom"))
17318 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17319 else if (!strcasecmp(v->value, "accunet"))
17320 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17321 else if (!strcasecmp(v->value, "none"))
17322 confp->pri.pri.nsf = PRI_NSF_NONE;
17323 else {
17324 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17325 confp->pri.pri.nsf = PRI_NSF_NONE;
17326 }
17327 } else if (!strcasecmp(v->name, "priindication")) {
17328 if (!strcasecmp(v->value, "outofband"))
17329 confp->chan.priindication_oob = 1;
17330 else if (!strcasecmp(v->value, "inband"))
17331 confp->chan.priindication_oob = 0;
17332 else
17333 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17334 v->value, v->lineno);
17335 } else if (!strcasecmp(v->name, "priexclusive")) {
17336 confp->chan.priexclusive = ast_true(v->value);
17337 } else if (!strcasecmp(v->name, "internationalprefix")) {
17338 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17339 } else if (!strcasecmp(v->name, "nationalprefix")) {
17340 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17341 } else if (!strcasecmp(v->name, "localprefix")) {
17342 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17343 } else if (!strcasecmp(v->name, "privateprefix")) {
17344 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17345 } else if (!strcasecmp(v->name, "unknownprefix")) {
17346 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17347 } else if (!strcasecmp(v->name, "resetinterval")) {
17348 if (!strcasecmp(v->value, "never"))
17349 confp->pri.pri.resetinterval = -1;
17350 else if (atoi(v->value) >= 60)
17351 confp->pri.pri.resetinterval = atoi(v->value);
17352 else
17353 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17354 v->value, v->lineno);
17355 } else if (!strcasecmp(v->name, "minunused")) {
17356 confp->pri.pri.minunused = atoi(v->value);
17357 } else if (!strcasecmp(v->name, "minidle")) {
17358 confp->pri.pri.minidle = atoi(v->value);
17359 } else if (!strcasecmp(v->name, "idleext")) {
17360 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17361 } else if (!strcasecmp(v->name, "idledial")) {
17362 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17363 } else if (!strcasecmp(v->name, "overlapdial")) {
17364 if (ast_true(v->value)) {
17365 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17366 } else if (!strcasecmp(v->value, "incoming")) {
17367 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17368 } else if (!strcasecmp(v->value, "outgoing")) {
17369 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17370 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17371 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17372 } else {
17373 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17374 }
17375 #ifdef HAVE_PRI_PROG_W_CAUSE
17376 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17377 if (!strcasecmp(v->value, "logical")) {
17378 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17379 } else if (!strcasecmp(v->value, "physical")) {
17380 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17381 } else {
17382 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17383 }
17384 #endif
17385 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17386 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17387 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17388 } else if (!strcasecmp(v->name, "service_message_support")) {
17389
17390 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17391 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17392 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17393 confp->pri.pri.enable_service_message_support = 1;
17394 } else {
17395 confp->pri.pri.enable_service_message_support = 0;
17396 }
17397 #endif
17398 #ifdef HAVE_PRI_INBANDDISCONNECT
17399 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17400 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17401 #endif
17402 } else if (!strcasecmp(v->name, "pritimer")) {
17403 #ifdef PRI_GETSET_TIMERS
17404 char tmp[20];
17405 char *timerc;
17406 char *c;
17407 int timer;
17408 int timeridx;
17409
17410 ast_copy_string(tmp, v->value, sizeof(tmp));
17411 c = tmp;
17412 timerc = strsep(&c, ",");
17413 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17414 timeridx = pri_timer2idx(timerc);
17415 timer = atoi(c);
17416 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17417 ast_log(LOG_WARNING,
17418 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17419 v->lineno);
17420 } else if (!timer) {
17421 ast_log(LOG_WARNING,
17422 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17423 c, timerc, v->lineno);
17424 } else {
17425 confp->pri.pri.pritimers[timeridx] = timer;
17426 }
17427 } else {
17428 ast_log(LOG_WARNING,
17429 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17430 v->value, v->lineno);
17431 }
17432 #endif
17433 } else if (!strcasecmp(v->name, "facilityenable")) {
17434 confp->pri.pri.facilityenable = ast_true(v->value);
17435 #if defined(HAVE_PRI_AOC_EVENTS)
17436 } else if (!strcasecmp(v->name, "aoc_enable")) {
17437 confp->pri.pri.aoc_passthrough_flag = 0;
17438 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17439 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17440 }
17441 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17442 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17443 }
17444 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17445 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17446 }
17447 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17448 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17449 #endif
17450 #if defined(HAVE_PRI_CALL_HOLD)
17451 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17452 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17453 #endif
17454 #if defined(HAVE_PRI_CCSS)
17455 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17456 if (!strcasecmp(v->value, "global")) {
17457 confp->pri.pri.cc_ptmp_recall_mode = 0;
17458 } else if (!strcasecmp(v->value, "specific")) {
17459 confp->pri.pri.cc_ptmp_recall_mode = 1;
17460 } else {
17461 confp->pri.pri.cc_ptmp_recall_mode = 1;
17462 }
17463 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17464 if (!strcasecmp(v->value, "release")) {
17465 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17466 } else if (!strcasecmp(v->value, "retain")) {
17467 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17468 } else if (!strcasecmp(v->value, "do_not_care")) {
17469 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17470 } else {
17471 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17472 }
17473 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17474 if (!strcasecmp(v->value, "release")) {
17475 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17476 } else if (!strcasecmp(v->value, "retain")) {
17477 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17478 } else {
17479 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17480 }
17481 #endif
17482 #if defined(HAVE_PRI_CALL_WAITING)
17483 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17484 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17485 if (confp->pri.pri.max_call_waiting_calls < 0) {
17486
17487 confp->pri.pri.max_call_waiting_calls = 0;
17488 }
17489 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17490 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17491 #endif
17492 #if defined(HAVE_PRI_MWI)
17493 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17494 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17495 sizeof(confp->pri.pri.mwi_mailboxes));
17496 #endif
17497 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17498 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17499 #if defined(HAVE_PRI_L2_PERSISTENCE)
17500 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17501 if (!strcasecmp(v->value, "keep_up")) {
17502 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17503 } else if (!strcasecmp(v->value, "leave_down")) {
17504 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17505 } else {
17506 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17507 }
17508 #endif
17509 #endif
17510 #if defined(HAVE_SS7)
17511 } else if (!strcasecmp(v->name, "ss7type")) {
17512 if (!strcasecmp(v->value, "itu")) {
17513 cur_ss7type = SS7_ITU;
17514 } else if (!strcasecmp(v->value, "ansi")) {
17515 cur_ss7type = SS7_ANSI;
17516 } else
17517 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17518 } else if (!strcasecmp(v->name, "linkset")) {
17519 cur_linkset = atoi(v->value);
17520 } else if (!strcasecmp(v->name, "pointcode")) {
17521 cur_pointcode = parse_pointcode(v->value);
17522 } else if (!strcasecmp(v->name, "adjpointcode")) {
17523 cur_adjpointcode = parse_pointcode(v->value);
17524 } else if (!strcasecmp(v->name, "defaultdpc")) {
17525 cur_defaultdpc = parse_pointcode(v->value);
17526 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17527 cur_cicbeginswith = atoi(v->value);
17528 } else if (!strcasecmp(v->name, "networkindicator")) {
17529 if (!strcasecmp(v->value, "national"))
17530 cur_networkindicator = SS7_NI_NAT;
17531 else if (!strcasecmp(v->value, "national_spare"))
17532 cur_networkindicator = SS7_NI_NAT_SPARE;
17533 else if (!strcasecmp(v->value, "international"))
17534 cur_networkindicator = SS7_NI_INT;
17535 else if (!strcasecmp(v->value, "international_spare"))
17536 cur_networkindicator = SS7_NI_INT_SPARE;
17537 else
17538 cur_networkindicator = -1;
17539 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17540 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17541 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17542 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17543 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17544 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17545 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17546 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17547 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17548 if (!strcasecmp(v->value, "national")) {
17549 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17550 } else if (!strcasecmp(v->value, "international")) {
17551 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17552 } else if (!strcasecmp(v->value, "subscriber")) {
17553 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17554 } else if (!strcasecmp(v->value, "unknown")) {
17555 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17556 } else if (!strcasecmp(v->value, "dynamic")) {
17557 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17558 } else {
17559 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17560 }
17561 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17562 if (!strcasecmp(v->value, "national")) {
17563 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17564 } else if (!strcasecmp(v->value, "international")) {
17565 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17566 } else if (!strcasecmp(v->value, "subscriber")) {
17567 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17568 } else if (!strcasecmp(v->value, "unknown")) {
17569 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17570 } else if (!strcasecmp(v->value, "dynamic")) {
17571 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17572 } else {
17573 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17574 }
17575 } else if (!strcasecmp(v->name, "sigchan")) {
17576 int sigchan, res;
17577 sigchan = atoi(v->value);
17578 res = linkset_addsigchan(sigchan);
17579 if (res < 0)
17580 return -1;
17581
17582 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17583 struct dahdi_ss7 *link;
17584 link = ss7_resolve_linkset(cur_linkset);
17585 if (!link) {
17586 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17587 return -1;
17588 }
17589 if (ast_true(v->value))
17590 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17591 #endif
17592 #ifdef HAVE_OPENR2
17593 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17594 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17595 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);
17596 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17597 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17598 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17599 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17600 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17601 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17602 confp->mfcr2.variant = OR2_VAR_ITU;
17603 }
17604 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17605 confp->mfcr2.mfback_timeout = atoi(v->value);
17606 if (!confp->mfcr2.mfback_timeout) {
17607 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17608 confp->mfcr2.mfback_timeout = -1;
17609 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17610 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17611 }
17612 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17613 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17614 if (confp->mfcr2.metering_pulse_timeout > 500) {
17615 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17616 }
17617 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17618 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17619 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17620 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17621 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17622 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17623 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17624 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17625 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17626 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17627 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17628 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17629 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17630 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17631 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17632 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17633 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17634 #endif
17635 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17636 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17637 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17638 confp->mfcr2.max_ani = atoi(v->value);
17639 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17640 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17641 }
17642 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17643 confp->mfcr2.max_dnis = atoi(v->value);
17644 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17645 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17646 }
17647 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17648 confp->mfcr2.category = openr2_proto_get_category(v->value);
17649 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17650 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17651 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17652 v->value, v->lineno);
17653 }
17654 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17655 openr2_log_level_t tmplevel;
17656 char *clevel;
17657 char *logval = ast_strdupa(v->value);
17658 while (logval) {
17659 clevel = strsep(&logval,",");
17660 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17661 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17662 continue;
17663 }
17664 confp->mfcr2.loglevel |= tmplevel;
17665 }
17666 #endif
17667 } else if (!strcasecmp(v->name, "cadence")) {
17668
17669 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17670 int i;
17671 struct dahdi_ring_cadence new_cadence;
17672 int cid_location = -1;
17673 int firstcadencepos = 0;
17674 char original_args[80];
17675 int cadence_is_ok = 1;
17676
17677 ast_copy_string(original_args, v->value, sizeof(original_args));
17678
17679 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]);
17680
17681
17682 if (element_count % 2 == 1) {
17683 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17684 cadence_is_ok = 0;
17685 }
17686
17687
17688 for (i = 0; i < element_count; i++) {
17689 if (c[i] == 0) {
17690 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17691 cadence_is_ok = 0;
17692 break;
17693 } else if (c[i] < 0) {
17694 if (i % 2 == 1) {
17695
17696 if (cid_location == -1) {
17697 cid_location = i;
17698 c[i] *= -1;
17699 } else {
17700 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17701 cadence_is_ok = 0;
17702 break;
17703 }
17704 } else {
17705 if (firstcadencepos == 0) {
17706 firstcadencepos = i;
17707
17708 } else {
17709 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17710 cadence_is_ok = 0;
17711 break;
17712 }
17713 }
17714 }
17715 }
17716
17717
17718 for (i = 0; i < 16; i++) {
17719 new_cadence.ringcadence[i] = c[i];
17720 }
17721
17722 if (cadence_is_ok) {
17723
17724 if (element_count < 2) {
17725 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17726 } else {
17727 if (cid_location == -1) {
17728
17729 cid_location = 1;
17730 } else {
17731
17732 cid_location = (cid_location + 1) / 2;
17733 }
17734
17735 if (!user_has_defined_cadences++)
17736
17737 num_cadence = 0;
17738 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17739 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17740 else {
17741 cadences[num_cadence] = new_cadence;
17742 cidrings[num_cadence++] = cid_location;
17743 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17744 }
17745 }
17746 }
17747 } else if (!strcasecmp(v->name, "ringtimeout")) {
17748 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17749 } else if (!strcasecmp(v->name, "prewink")) {
17750 confp->timing.prewinktime = atoi(v->value);
17751 } else if (!strcasecmp(v->name, "preflash")) {
17752 confp->timing.preflashtime = atoi(v->value);
17753 } else if (!strcasecmp(v->name, "wink")) {
17754 confp->timing.winktime = atoi(v->value);
17755 } else if (!strcasecmp(v->name, "flash")) {
17756 confp->timing.flashtime = atoi(v->value);
17757 } else if (!strcasecmp(v->name, "start")) {
17758 confp->timing.starttime = atoi(v->value);
17759 } else if (!strcasecmp(v->name, "rxwink")) {
17760 confp->timing.rxwinktime = atoi(v->value);
17761 } else if (!strcasecmp(v->name, "rxflash")) {
17762 confp->timing.rxflashtime = atoi(v->value);
17763 } else if (!strcasecmp(v->name, "debounce")) {
17764 confp->timing.debouncetime = atoi(v->value);
17765 } else if (!strcasecmp(v->name, "toneduration")) {
17766 int toneduration;
17767 int ctlfd;
17768 int res;
17769 struct dahdi_dialparams dps;
17770
17771 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17772 if (ctlfd == -1) {
17773 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17774 return -1;
17775 }
17776
17777 toneduration = atoi(v->value);
17778 if (toneduration > -1) {
17779 memset(&dps, 0, sizeof(dps));
17780
17781 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17782 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17783 if (res < 0) {
17784 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17785 close(ctlfd);
17786 return -1;
17787 }
17788 }
17789 close(ctlfd);
17790 } else if (!strcasecmp(v->name, "defaultcic")) {
17791 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17792 } else if (!strcasecmp(v->name, "defaultozz")) {
17793 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17794 } else if (!strcasecmp(v->name, "mwilevel")) {
17795 mwilevel = atoi(v->value);
17796 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17797 dtmfcid_level = atoi(v->value);
17798 } else if (!strcasecmp(v->name, "reportalarms")) {
17799 if (!strcasecmp(v->value, "all"))
17800 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17801 if (!strcasecmp(v->value, "none"))
17802 report_alarms = 0;
17803 else if (!strcasecmp(v->value, "channels"))
17804 report_alarms = REPORT_CHANNEL_ALARMS;
17805 else if (!strcasecmp(v->value, "spans"))
17806 report_alarms = REPORT_SPAN_ALARMS;
17807 }
17808 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17809 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17810 }
17811
17812
17813 if (confp->chan.vars) {
17814 ast_variables_destroy(confp->chan.vars);
17815 confp->chan.vars = NULL;
17816 }
17817
17818 if (dahdichan) {
17819
17820 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17821 &found_pseudo)) {
17822 if (confp->ignore_failed_channels) {
17823 ast_log(LOG_WARNING,
17824 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17825 dahdichan->value);
17826 } else {
17827 return -1;
17828 }
17829 }
17830 }
17831
17832
17833 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17834 if (!tmp->destroy && tmp->span != y) {
17835 tmp->manages_span_alarms = 1;
17836 y = tmp->span;
17837 } else {
17838 tmp->manages_span_alarms = 0;
17839 }
17840 }
17841
17842
17843
17844 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17845
17846
17847
17848
17849 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17850
17851 if (conf.chan.cc_params) {
17852 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17853 } else {
17854 tmp = NULL;
17855 }
17856 if (tmp) {
17857 ast_verb(3, "Automatically generated pseudo channel\n");
17858 } else {
17859 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17860 }
17861 ast_cc_config_params_destroy(conf.chan.cc_params);
17862 }
17863 return 0;
17864 }
17865
17866
17867
17868
17869
17870
17871
17872
17873
17874
17875
17876 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17877 {
17878 struct ast_cc_config_params *cc_params;
17879
17880 cc_params = dest->chan.cc_params;
17881 *dest = *src;
17882 dest->chan.cc_params = cc_params;
17883 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17884 }
17885
17886
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897
17898 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17899 {
17900 struct ast_config *cfg;
17901 struct ast_config *ucfg;
17902 struct ast_variable *v;
17903 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17904 const char *chans;
17905 const char *cat;
17906 int res;
17907
17908 #ifdef HAVE_PRI
17909 char *c;
17910 int spanno;
17911 int i;
17912 int logicalspan;
17913 int trunkgroup;
17914 int dchannels[SIG_PRI_NUM_DCHANS];
17915 #endif
17916 int have_cfg_now;
17917 static int had_cfg_before = 1;
17918
17919 cfg = ast_config_load(config, config_flags);
17920 have_cfg_now = !!cfg;
17921 if (!cfg) {
17922
17923 if (had_cfg_before) {
17924 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17925 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17926 }
17927 cfg = ast_config_new();
17928 if (!cfg) {
17929 return 0;
17930 }
17931 ucfg = ast_config_load("users.conf", config_flags);
17932 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17933 ast_config_destroy(cfg);
17934 return 0;
17935 }
17936 if (ucfg == CONFIG_STATUS_FILEINVALID) {
17937 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17938 ast_config_destroy(cfg);
17939 return 0;
17940 }
17941 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17942 ucfg = ast_config_load("users.conf", config_flags);
17943 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17944 return 0;
17945 }
17946 if (ucfg == CONFIG_STATUS_FILEINVALID) {
17947 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17948 return 0;
17949 }
17950 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17951 cfg = ast_config_load(config, config_flags);
17952 have_cfg_now = !!cfg;
17953 if (!cfg) {
17954 if (had_cfg_before) {
17955
17956 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
17957 ast_config_destroy(ucfg);
17958 return 0;
17959 }
17960 cfg = ast_config_new();
17961 if (!cfg) {
17962 ast_config_destroy(ucfg);
17963 return 0;
17964 }
17965 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17966 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17967 ast_config_destroy(ucfg);
17968 return 0;
17969 }
17970 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17971 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17972 return 0;
17973 } else {
17974 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17975 ucfg = ast_config_load("users.conf", config_flags);
17976 if (ucfg == CONFIG_STATUS_FILEINVALID) {
17977 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17978 ast_config_destroy(cfg);
17979 return 0;
17980 }
17981 }
17982 had_cfg_before = have_cfg_now;
17983
17984
17985 ast_mutex_lock(&iflock);
17986 #ifdef HAVE_PRI
17987 if (reload != 1) {
17988
17989 v = ast_variable_browse(cfg, "trunkgroups");
17990 while (v) {
17991 if (!strcasecmp(v->name, "trunkgroup")) {
17992 trunkgroup = atoi(v->value);
17993 if (trunkgroup > 0) {
17994 if ((c = strchr(v->value, ','))) {
17995 i = 0;
17996 memset(dchannels, 0, sizeof(dchannels));
17997 while (c && (i < SIG_PRI_NUM_DCHANS)) {
17998 dchannels[i] = atoi(c + 1);
17999 if (dchannels[i] < 0) {
18000 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);
18001 } else
18002 i++;
18003 c = strchr(c + 1, ',');
18004 }
18005 if (i) {
18006 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18007 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);
18008 } else
18009 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");
18010 } else
18011 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18012 } else
18013 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18014 } else
18015 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18016 } else if (!strcasecmp(v->name, "spanmap")) {
18017 spanno = atoi(v->value);
18018 if (spanno > 0) {
18019 if ((c = strchr(v->value, ','))) {
18020 trunkgroup = atoi(c + 1);
18021 if (trunkgroup > 0) {
18022 if ((c = strchr(c + 1, ',')))
18023 logicalspan = atoi(c + 1);
18024 else
18025 logicalspan = 0;
18026 if (logicalspan >= 0) {
18027 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18028 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18029 } else
18030 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18031 } else
18032 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);
18033 } else
18034 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18035 } else
18036 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18037 } else
18038 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18039 } else {
18040 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18041 }
18042 v = v->next;
18043 }
18044 }
18045 #endif
18046
18047
18048 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18049
18050 mwimonitornotify[0] = '\0';
18051
18052 v = ast_variable_browse(cfg, "channels");
18053 if ((res = process_dahdi(base_conf,
18054 "" ,
18055 v, reload, 0))) {
18056 ast_mutex_unlock(&iflock);
18057 ast_config_destroy(cfg);
18058 if (ucfg) {
18059 ast_config_destroy(ucfg);
18060 }
18061 return res;
18062 }
18063
18064
18065 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18066
18067
18068
18069 if (!strcasecmp(cat, "general") ||
18070 !strcasecmp(cat, "trunkgroups") ||
18071 !strcasecmp(cat, "globals") ||
18072 !strcasecmp(cat, "channels")) {
18073 continue;
18074 }
18075
18076 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18077 if (ast_strlen_zero(chans)) {
18078
18079 continue;
18080 }
18081
18082
18083 deep_copy_dahdi_chan_conf(conf, base_conf);
18084
18085 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18086 ast_mutex_unlock(&iflock);
18087 ast_config_destroy(cfg);
18088 if (ucfg) {
18089 ast_config_destroy(ucfg);
18090 }
18091 return res;
18092 }
18093 }
18094
18095 ast_config_destroy(cfg);
18096
18097 if (ucfg) {
18098
18099 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18100 process_dahdi(base_conf,
18101 "" ,
18102 ast_variable_browse(ucfg, "general"), 1, 0);
18103
18104 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18105 if (!strcasecmp(cat, "general")) {
18106 continue;
18107 }
18108
18109 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18110 if (ast_strlen_zero(chans)) {
18111
18112 continue;
18113 }
18114
18115
18116 deep_copy_dahdi_chan_conf(conf, base_conf);
18117
18118 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18119 ast_config_destroy(ucfg);
18120 ast_mutex_unlock(&iflock);
18121 return res;
18122 }
18123 }
18124 ast_config_destroy(ucfg);
18125 }
18126 ast_mutex_unlock(&iflock);
18127
18128 #ifdef HAVE_PRI
18129 if (reload != 1) {
18130 int x;
18131 for (x = 0; x < NUM_SPANS; x++) {
18132 if (pris[x].pri.pvts[0]) {
18133 prepare_pri(pris + x);
18134 if (sig_pri_start_pri(&pris[x].pri)) {
18135 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18136 return -1;
18137 } else
18138 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18139 }
18140 }
18141 }
18142 #endif
18143 #if defined(HAVE_SS7)
18144 if (reload != 1) {
18145 int x;
18146 for (x = 0; x < NUM_SPANS; x++) {
18147 if (linksets[x].ss7.ss7) {
18148 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18149 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18150 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18151 return -1;
18152 } else
18153 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18154 }
18155 }
18156 }
18157 #endif
18158 #ifdef HAVE_OPENR2
18159 if (reload != 1) {
18160 int x;
18161 for (x = 0; x < r2links_count; x++) {
18162 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18163 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18164 return -1;
18165 } else {
18166 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18167 }
18168 }
18169 }
18170 #endif
18171
18172 restart_monitor();
18173 return 0;
18174 }
18175
18176
18177
18178
18179
18180
18181
18182
18183
18184
18185 static int setup_dahdi(int reload)
18186 {
18187 int res;
18188 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18189 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18190 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18191
18192 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18193 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18194 } else {
18195 res = -1;
18196 }
18197 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18198 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18199 ast_cc_config_params_destroy(conf.chan.cc_params);
18200
18201 return res;
18202 }
18203
18204
18205
18206
18207
18208
18209
18210
18211 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18212 struct ast_data *data_root)
18213 {
18214 int ctl, res, span;
18215 struct ast_data *data_span, *data_alarms;
18216 struct dahdi_spaninfo s;
18217
18218 ctl = open("/dev/dahdi/ctl", O_RDWR);
18219 if (ctl < 0) {
18220 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18221 return -1;
18222 }
18223 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18224 s.spanno = span;
18225 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18226 if (res) {
18227 continue;
18228 }
18229
18230 data_span = ast_data_add_node(data_root, "span");
18231 if (!data_span) {
18232 continue;
18233 }
18234 ast_data_add_str(data_span, "description", s.desc);
18235
18236
18237 data_alarms = ast_data_add_node(data_span, "alarms");
18238 if (!data_alarms) {
18239 continue;
18240 }
18241
18242 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18243 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18244 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18245 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18246 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18247 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18248
18249 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18250 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18251 ast_data_add_int(data_span, "crc4", s.crc4count);
18252 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18253 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18254 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18255 "CAS");
18256 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18257 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18258 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18259 "Unknown");
18260 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18261 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18262 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18263 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18264
18265
18266 if (!ast_data_search_match(search, data_span)) {
18267 ast_data_remove_node(data_root, data_span);
18268 }
18269 }
18270 close(ctl);
18271
18272 return 0;
18273 }
18274
18275
18276
18277
18278
18279
18280
18281
18282 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18283 struct ast_data *data_root)
18284 {
18285 struct dahdi_pvt *tmp;
18286 struct ast_data *data_channel;
18287
18288 ast_mutex_lock(&iflock);
18289 for (tmp = iflist; tmp; tmp = tmp->next) {
18290 data_channel = ast_data_add_node(data_root, "channel");
18291 if (!data_channel) {
18292 continue;
18293 }
18294
18295 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18296
18297
18298 if (!ast_data_search_match(search, data_channel)) {
18299 ast_data_remove_node(data_root, data_channel);
18300 }
18301 }
18302 ast_mutex_unlock(&iflock);
18303
18304 return 0;
18305 }
18306
18307
18308
18309
18310
18311
18312
18313
18314 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18315 struct ast_data *data_root)
18316 {
18317 int pseudo_fd = -1;
18318 struct dahdi_versioninfo vi = {
18319 .version = "Unknown",
18320 .echo_canceller = "Unknown"
18321 };
18322
18323 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18324 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18325 return -1;
18326 }
18327
18328 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18329 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18330 }
18331
18332 close(pseudo_fd);
18333
18334 ast_data_add_str(data_root, "value", vi.version);
18335 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18336
18337 return 0;
18338 }
18339
18340 static const struct ast_data_handler dahdi_status_data_provider = {
18341 .version = AST_DATA_HANDLER_VERSION,
18342 .get = dahdi_status_data_provider_get
18343 };
18344
18345 static const struct ast_data_handler dahdi_channels_data_provider = {
18346 .version = AST_DATA_HANDLER_VERSION,
18347 .get = dahdi_channels_data_provider_get
18348 };
18349
18350 static const struct ast_data_handler dahdi_version_data_provider = {
18351 .version = AST_DATA_HANDLER_VERSION,
18352 .get = dahdi_version_data_provider_get
18353 };
18354
18355 static const struct ast_data_entry dahdi_data_providers[] = {
18356 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18357 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18358 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18359 };
18360
18361 static int load_module(void)
18362 {
18363 int res;
18364 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18365 int y;
18366 #endif
18367
18368 #ifdef HAVE_PRI
18369 memset(pris, 0, sizeof(pris));
18370 for (y = 0; y < NUM_SPANS; y++) {
18371 sig_pri_init_pri(&pris[y].pri);
18372 }
18373 pri_set_error(dahdi_pri_error);
18374 pri_set_message(dahdi_pri_message);
18375 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18376 #ifdef HAVE_PRI_PROG_W_CAUSE
18377 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18378 #endif
18379 #if defined(HAVE_PRI_CCSS)
18380 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18381 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18382 __unload_module();
18383 return AST_MODULE_LOAD_FAILURE;
18384 }
18385 #endif
18386 if (sig_pri_load(
18387 #if defined(HAVE_PRI_CCSS)
18388 dahdi_pri_cc_type
18389 #else
18390 NULL
18391 #endif
18392 )) {
18393 __unload_module();
18394 return AST_MODULE_LOAD_FAILURE;
18395 }
18396 #endif
18397 #if defined(HAVE_SS7)
18398 memset(linksets, 0, sizeof(linksets));
18399 for (y = 0; y < NUM_SPANS; y++) {
18400 sig_ss7_init_linkset(&linksets[y].ss7);
18401 }
18402 ss7_set_error(dahdi_ss7_error);
18403 ss7_set_message(dahdi_ss7_message);
18404 #endif
18405 res = setup_dahdi(0);
18406
18407 if (res)
18408 return AST_MODULE_LOAD_DECLINE;
18409 if (ast_channel_register(&dahdi_tech)) {
18410 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18411 __unload_module();
18412 return AST_MODULE_LOAD_FAILURE;
18413 }
18414 #ifdef HAVE_PRI
18415 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18416 #endif
18417 #if defined(HAVE_SS7)
18418 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18419 #endif
18420 #ifdef HAVE_OPENR2
18421 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18422 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18423 #endif
18424
18425 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18426
18427 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18428 memset(round_robin, 0, sizeof(round_robin));
18429 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18430 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18431 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18432 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18433 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18434 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18435 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18436
18437 ast_cond_init(&ss_thread_complete, NULL);
18438
18439 return res;
18440 }
18441
18442 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18443 {
18444 #define END_SILENCE_LEN 400
18445 #define HEADER_MS 50
18446 #define TRAILER_MS 5
18447 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18448 #define ASCII_BYTES_PER_CHAR 80
18449
18450 unsigned char *buf,*mybuf;
18451 struct dahdi_pvt *p = c->tech_pvt;
18452 struct pollfd fds[1];
18453 int size,res,fd,len,x;
18454 int bytes=0;
18455
18456 float cr = 1.0;
18457 float ci = 0.0;
18458 float scont = 0.0;
18459 int idx;
18460
18461 idx = dahdi_get_index(c, p, 0);
18462 if (idx < 0) {
18463 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18464 return -1;
18465 }
18466 if (!text[0]) return(0);
18467 if ((!p->tdd) && (!p->mate)) return(0);
18468 if (p->mate)
18469 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18470 else
18471 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18472 if (!buf)
18473 return -1;
18474 mybuf = buf;
18475 if (p->mate) {
18476 int codec = AST_LAW(p);
18477 for (x = 0; x < HEADER_MS; x++) {
18478 PUT_CLID_MARKMS;
18479 }
18480
18481 for (x = 0; text[x]; x++) {
18482 PUT_CLID(text[x]);
18483 }
18484 for (x = 0; x < TRAILER_MS; x++) {
18485 PUT_CLID_MARKMS;
18486 }
18487 len = bytes;
18488 buf = mybuf;
18489 } else {
18490 len = tdd_generate(p->tdd, buf, text);
18491 if (len < 1) {
18492 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18493 ast_free(mybuf);
18494 return -1;
18495 }
18496 }
18497 memset(buf + len, 0x7f, END_SILENCE_LEN);
18498 len += END_SILENCE_LEN;
18499 fd = p->subs[idx].dfd;
18500 while (len) {
18501 if (ast_check_hangup(c)) {
18502 ast_free(mybuf);
18503 return -1;
18504 }
18505 size = len;
18506 if (size > READ_SIZE)
18507 size = READ_SIZE;
18508 fds[0].fd = fd;
18509 fds[0].events = POLLOUT | POLLPRI;
18510 fds[0].revents = 0;
18511 res = poll(fds, 1, -1);
18512 if (!res) {
18513 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18514 continue;
18515 }
18516
18517 if (fds[0].revents & POLLPRI) {
18518 ast_free(mybuf);
18519 return -1;
18520 }
18521 if (!(fds[0].revents & POLLOUT)) {
18522 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18523 continue;
18524 }
18525 res = write(fd, buf, size);
18526 if (res != size) {
18527 if (res == -1) {
18528 ast_free(mybuf);
18529 return -1;
18530 }
18531 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18532 break;
18533 }
18534 len -= size;
18535 buf += size;
18536 }
18537 ast_free(mybuf);
18538 return(0);
18539 }
18540
18541
18542 static int reload(void)
18543 {
18544 int res = 0;
18545
18546 res = setup_dahdi(1);
18547 if (res) {
18548 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18549 return -1;
18550 }
18551 return 0;
18552 }
18553
18554
18555
18556
18557
18558 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18559 .load = load_module,
18560 .unload = unload_module,
18561 .reload = reload,
18562 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18563 .nonoptreq = "res_smdi",
18564 );