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: 336635 $")
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
03580
03581 static struct analog_callback dahdi_analog_callbacks =
03582 {
03583 .play_tone = my_play_tone,
03584 .get_event = my_get_event,
03585 .wait_event = my_wait_event,
03586 .is_off_hook = my_is_off_hook,
03587 .set_echocanceller = my_set_echocanceller,
03588 .ring = my_ring,
03589 .flash = my_flash,
03590 .off_hook = my_off_hook,
03591 .dial_digits = my_dial_digits,
03592 .train_echocanceller = my_train_echocanceller,
03593 .on_hook = my_on_hook,
03594 .is_dialing = my_is_dialing,
03595 .allocate_sub = my_allocate_sub,
03596 .unallocate_sub = my_unallocate_sub,
03597 .swap_subs = my_swap_subchannels,
03598 .has_voicemail = my_has_voicemail,
03599 .check_for_conference = my_check_for_conference,
03600 .conf_add = my_conf_add,
03601 .conf_del = my_conf_del,
03602 .complete_conference_update = my_complete_conference_update,
03603 .start = my_start,
03604 .all_subchannels_hungup = my_all_subchannels_hungup,
03605 .lock_private = my_lock_private,
03606 .unlock_private = my_unlock_private,
03607 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03608 .handle_dtmf = my_handle_dtmf,
03609 .wink = my_wink,
03610 .new_ast_channel = my_new_analog_ast_channel,
03611 .dsp_set_digitmode = my_dsp_set_digitmode,
03612 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03613 .send_callerid = my_send_callerid,
03614 .callwait = my_callwait,
03615 .stop_callwait = my_stop_callwait,
03616 .get_callerid = my_get_callerid,
03617 .start_cid_detect = my_start_cid_detect,
03618 .stop_cid_detect = my_stop_cid_detect,
03619 .handle_notify_message = my_handle_notify_message,
03620 .increase_ss_count = my_increase_ss_count,
03621 .decrease_ss_count = my_decrease_ss_count,
03622 .distinctive_ring = my_distinctive_ring,
03623 .set_linear_mode = my_set_linear_mode,
03624 .set_inthreeway = my_set_inthreeway,
03625 .get_and_handle_alarms = my_get_and_handle_alarms,
03626 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03627 .get_sub_fd = my_get_sub_fd,
03628 .set_cadence = my_set_cadence,
03629 .set_alarm = my_set_alarm,
03630 .set_dialing = my_set_dialing,
03631 .set_ringtimeout = my_set_ringtimeout,
03632 .set_waitingfordt = my_set_waitingfordt,
03633 .check_waitingfordt = my_check_waitingfordt,
03634 .set_confirmanswer = my_set_confirmanswer,
03635 .check_confirmanswer = my_check_confirmanswer,
03636 .set_callwaiting = my_set_callwaiting,
03637 .cancel_cidspill = my_cancel_cidspill,
03638 .confmute = my_confmute,
03639 .set_pulsedial = my_set_pulsedial,
03640 .set_new_owner = my_set_new_owner,
03641 .get_orig_dialstring = my_get_orig_dialstring,
03642 .set_needringing = my_set_needringing,
03643 .set_polarity = my_set_polarity,
03644 .start_polarityswitch = my_start_polarityswitch,
03645 .answer_polarityswitch = my_answer_polarityswitch,
03646 .hangup_polarityswitch = my_hangup_polarityswitch,
03647 };
03648
03649
03650 static struct dahdi_pvt *round_robin[32];
03651
03652 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03653 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03654 {
03655 int res;
03656 if (p->subs[SUB_REAL].owner == ast)
03657 res = 0;
03658 else if (p->subs[SUB_CALLWAIT].owner == ast)
03659 res = 1;
03660 else if (p->subs[SUB_THREEWAY].owner == ast)
03661 res = 2;
03662 else {
03663 res = -1;
03664 if (!nullok)
03665 ast_log(LOG_WARNING,
03666 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03667 ast ? ast->name : "", p->channel, fname, line);
03668 }
03669 return res;
03670 }
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03688 {
03689 for (;;) {
03690 if (!pvt->subs[sub_idx].owner) {
03691
03692 break;
03693 }
03694 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03695
03696 break;
03697 }
03698
03699 DEADLOCK_AVOIDANCE(&pvt->lock);
03700 }
03701 }
03702
03703 static void wakeup_sub(struct dahdi_pvt *p, int a)
03704 {
03705 dahdi_lock_sub_owner(p, a);
03706 if (p->subs[a].owner) {
03707 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03708 ast_channel_unlock(p->subs[a].owner);
03709 }
03710 }
03711
03712 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03713 {
03714 for (;;) {
03715 if (p->owner) {
03716 if (ast_channel_trylock(p->owner)) {
03717 DEADLOCK_AVOIDANCE(&p->lock);
03718 } else {
03719 ast_queue_frame(p->owner, f);
03720 ast_channel_unlock(p->owner);
03721 break;
03722 }
03723 } else
03724 break;
03725 }
03726 }
03727
03728 static void handle_clear_alarms(struct dahdi_pvt *p)
03729 {
03730 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03731 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03732 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03733 }
03734 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03735 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03736 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03737 }
03738 }
03739
03740 #ifdef HAVE_OPENR2
03741
03742 static int dahdi_r2_answer(struct dahdi_pvt *p)
03743 {
03744 int res = 0;
03745
03746
03747
03748 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03749 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03750 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03751 if (!double_answer) {
03752
03753
03754 res = openr2_chan_answer_call(p->r2chan);
03755 } else if (wants_double_answer) {
03756 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03757 } else {
03758 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03759 }
03760 #else
03761 res = openr2_chan_answer_call(p->r2chan);
03762 #endif
03763 return res;
03764 }
03765
03766
03767
03768
03769 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03770 {
03771 openr2_calling_party_category_t cat;
03772 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03773 struct dahdi_pvt *p = c->tech_pvt;
03774 if (ast_strlen_zero(catstr)) {
03775 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03776 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03777 return p->mfcr2_category;
03778 }
03779 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03780 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03781 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03782 return p->mfcr2_category;
03783 }
03784 ast_debug(1, "Using category %s\n", catstr);
03785 return cat;
03786 }
03787
03788 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03789 {
03790 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03791 ast_mutex_lock(&p->lock);
03792 if (p->mfcr2call) {
03793 ast_mutex_unlock(&p->lock);
03794
03795
03796
03797
03798
03799 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03800 return;
03801 }
03802 p->mfcr2call = 1;
03803
03804 p->cid_name[0] = '\0';
03805 p->cid_num[0] = '\0';
03806 p->cid_subaddr[0] = '\0';
03807 p->rdnis[0] = '\0';
03808 p->exten[0] = '\0';
03809 p->mfcr2_ani_index = '\0';
03810 p->mfcr2_dnis_index = '\0';
03811 p->mfcr2_dnis_matched = 0;
03812 p->mfcr2_answer_pending = 0;
03813 p->mfcr2_call_accepted = 0;
03814 ast_mutex_unlock(&p->lock);
03815 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03816 }
03817
03818 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03819 {
03820 int res;
03821 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03822 ast_mutex_lock(&p->lock);
03823 p->inalarm = alarm ? 1 : 0;
03824 if (p->inalarm) {
03825 res = get_alarms(p);
03826 handle_alarms(p, res);
03827 } else {
03828 handle_clear_alarms(p);
03829 }
03830 ast_mutex_unlock(&p->lock);
03831 }
03832
03833 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03834 {
03835 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03836 }
03837
03838 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03839 {
03840 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03841 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03842 if (p->owner) {
03843 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03844 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03845 }
03846 ast_mutex_lock(&p->lock);
03847 p->mfcr2call = 0;
03848 ast_mutex_unlock(&p->lock);
03849 }
03850
03851 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03852 {
03853 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03854 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03855 p->channel, openr2_proto_get_disconnect_string(cause));
03856
03857 openr2_chan_set_idle(p->r2chan);
03858 ast_mutex_lock(&p->lock);
03859 p->mfcr2call = 0;
03860 ast_mutex_unlock(&p->lock);
03861 }
03862 }
03863
03864 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03865 {
03866 struct dahdi_pvt *p;
03867 struct ast_channel *c;
03868 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03869 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03870 openr2_proto_get_category_string(category));
03871 p = openr2_chan_get_client_data(r2chan);
03872
03873 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03874 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03875 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03876 return;
03877 }
03878 ast_mutex_lock(&p->lock);
03879 p->mfcr2_recvd_category = category;
03880
03881 if (!p->use_callerid) {
03882 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03883 p->cid_num[0] = 0;
03884 p->cid_name[0] = 0;
03885 }
03886
03887 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03888 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03889 p->exten[0] = 's';
03890 p->exten[1] = 0;
03891 }
03892 ast_mutex_unlock(&p->lock);
03893 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03894 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03895 p->channel, p->exten, p->context);
03896 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03897 return;
03898 }
03899 if (!p->mfcr2_accept_on_offer) {
03900
03901 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03902 if (c) {
03903
03904
03905
03906 return;
03907 }
03908 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03909 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03910 } else if (p->mfcr2_charge_calls) {
03911 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03912 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03913 } else {
03914 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03915 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03916 }
03917 }
03918
03919 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03920 {
03921 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03922 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03923 ast_mutex_lock(&p->lock);
03924 p->mfcr2call = 0;
03925 ast_mutex_unlock(&p->lock);
03926 }
03927
03928 static void dahdi_enable_ec(struct dahdi_pvt *p);
03929 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03930 {
03931 struct dahdi_pvt *p = NULL;
03932 struct ast_channel *c = NULL;
03933 p = openr2_chan_get_client_data(r2chan);
03934 dahdi_enable_ec(p);
03935 p->mfcr2_call_accepted = 1;
03936
03937 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03938 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03939
03940
03941
03942
03943 if (!p->mfcr2_accept_on_offer) {
03944 openr2_chan_disable_read(r2chan);
03945 if (p->mfcr2_answer_pending) {
03946 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03947 dahdi_r2_answer(p);
03948 }
03949 return;
03950 }
03951 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03952 if (c) {
03953
03954
03955 openr2_chan_disable_read(r2chan);
03956 return;
03957 }
03958 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03959
03960 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03961 return;
03962 }
03963
03964 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03965 p->subs[SUB_REAL].needringing = 1;
03966 p->dialing = 0;
03967
03968 openr2_chan_disable_read(r2chan);
03969 }
03970
03971 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03972 {
03973 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03974 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03975 p->subs[SUB_REAL].needanswer = 1;
03976 }
03977
03978 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03979 {
03980
03981 }
03982
03983 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03984 {
03985 switch (cause) {
03986 case OR2_CAUSE_BUSY_NUMBER:
03987 return AST_CAUSE_BUSY;
03988 case OR2_CAUSE_NETWORK_CONGESTION:
03989 return AST_CAUSE_CONGESTION;
03990 case OR2_CAUSE_OUT_OF_ORDER:
03991 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03992 case OR2_CAUSE_UNALLOCATED_NUMBER:
03993 return AST_CAUSE_UNREGISTERED;
03994 case OR2_CAUSE_NO_ANSWER:
03995 return AST_CAUSE_NO_ANSWER;
03996 case OR2_CAUSE_NORMAL_CLEARING:
03997 return AST_CAUSE_NORMAL_CLEARING;
03998 case OR2_CAUSE_UNSPECIFIED:
03999 default:
04000 return AST_CAUSE_NOTDEFINED;
04001 }
04002 }
04003
04004 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04005 {
04006 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04007 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04008 ast_mutex_lock(&p->lock);
04009 if (!p->owner) {
04010 ast_mutex_unlock(&p->lock);
04011
04012 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04013 return;
04014 }
04015
04016
04017 if (p->owner->_state == AST_STATE_UP) {
04018 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04019 ast_mutex_unlock(&p->lock);
04020 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04021
04022 switch (cause) {
04023 case OR2_CAUSE_BUSY_NUMBER:
04024 p->subs[SUB_REAL].needbusy = 1;
04025 break;
04026 case OR2_CAUSE_NETWORK_CONGESTION:
04027 case OR2_CAUSE_OUT_OF_ORDER:
04028 case OR2_CAUSE_UNALLOCATED_NUMBER:
04029 case OR2_CAUSE_NO_ANSWER:
04030 case OR2_CAUSE_UNSPECIFIED:
04031 case OR2_CAUSE_NORMAL_CLEARING:
04032 p->subs[SUB_REAL].needcongestion = 1;
04033 break;
04034 default:
04035 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04036 }
04037 ast_mutex_unlock(&p->lock);
04038 } else {
04039 ast_mutex_unlock(&p->lock);
04040
04041
04042 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04043 }
04044 }
04045
04046 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04047 {
04048 switch (level) {
04049 case OR2_LOG_NOTICE:
04050 ast_verbose("%s", logmessage);
04051 break;
04052 case OR2_LOG_WARNING:
04053 ast_log(LOG_WARNING, "%s", logmessage);
04054 break;
04055 case OR2_LOG_ERROR:
04056 ast_log(LOG_ERROR, "%s", logmessage);
04057 break;
04058 case OR2_LOG_STACK_TRACE:
04059 case OR2_LOG_MF_TRACE:
04060 case OR2_LOG_CAS_TRACE:
04061 case OR2_LOG_DEBUG:
04062 case OR2_LOG_EX_DEBUG:
04063 ast_log(LOG_DEBUG, "%s", logmessage);
04064 break;
04065 default:
04066 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04067 ast_log(LOG_DEBUG, "%s", logmessage);
04068 break;
04069 }
04070 }
04071
04072 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04073 {
04074 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04075 ast_mutex_lock(&p->lock);
04076 p->remotelyblocked = 1;
04077 ast_mutex_unlock(&p->lock);
04078 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04079 }
04080
04081 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04082 {
04083 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04084 ast_mutex_lock(&p->lock);
04085 p->remotelyblocked = 0;
04086 ast_mutex_unlock(&p->lock);
04087 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04088 }
04089
04090 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04091 __attribute__((format (printf, 3, 0)));
04092 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04093 {
04094 #define CONTEXT_TAG "Context - "
04095 char logmsg[256];
04096 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04097 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04098 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04099 dahdi_r2_write_log(level, completemsg);
04100 #undef CONTEXT_TAG
04101 }
04102
04103 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04104 __attribute__((format (printf, 3, 0)));
04105 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04106 {
04107 #define CHAN_TAG "Chan "
04108 char logmsg[256];
04109 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04110 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04111 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04112 dahdi_r2_write_log(level, completemsg);
04113 }
04114
04115 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04116 {
04117 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04118
04119 if (p->immediate) {
04120 return 0;
04121 }
04122 p->exten[p->mfcr2_dnis_index] = digit;
04123 p->rdnis[p->mfcr2_dnis_index] = digit;
04124 p->mfcr2_dnis_index++;
04125 p->exten[p->mfcr2_dnis_index] = 0;
04126 p->rdnis[p->mfcr2_dnis_index] = 0;
04127
04128 if ((p->mfcr2_dnis_matched ||
04129 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04130 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04131 return 0;
04132 }
04133
04134 return 1;
04135 }
04136
04137 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04138 {
04139 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04140 p->cid_num[p->mfcr2_ani_index] = digit;
04141 p->cid_name[p->mfcr2_ani_index] = digit;
04142 p->mfcr2_ani_index++;
04143 p->cid_num[p->mfcr2_ani_index] = 0;
04144 p->cid_name[p->mfcr2_ani_index] = 0;
04145 }
04146
04147 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04148 {
04149 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04150 }
04151
04152 static openr2_event_interface_t dahdi_r2_event_iface = {
04153 .on_call_init = dahdi_r2_on_call_init,
04154 .on_call_offered = dahdi_r2_on_call_offered,
04155 .on_call_accepted = dahdi_r2_on_call_accepted,
04156 .on_call_answered = dahdi_r2_on_call_answered,
04157 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04158 .on_call_end = dahdi_r2_on_call_end,
04159 .on_call_read = dahdi_r2_on_call_read,
04160 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04161 .on_os_error = dahdi_r2_on_os_error,
04162 .on_protocol_error = dahdi_r2_on_protocol_error,
04163 .on_line_blocked = dahdi_r2_on_line_blocked,
04164 .on_line_idle = dahdi_r2_on_line_idle,
04165
04166 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04167 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04168 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04169
04170 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04171 };
04172
04173 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04174 {
04175 return AST_ALAW(sample);
04176 }
04177
04178 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04179 {
04180 return AST_LIN2A(sample);
04181 }
04182
04183 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04184 dahdi_r2_alaw_to_linear,
04185 dahdi_r2_linear_to_alaw
04186 };
04187
04188 #endif
04189
04190 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04191 {
04192 int tchan;
04193 int tinthreeway;
04194 struct ast_channel *towner;
04195
04196 ast_debug(1, "Swapping %d and %d\n", a, b);
04197
04198 tchan = p->subs[a].chan;
04199 towner = p->subs[a].owner;
04200 tinthreeway = p->subs[a].inthreeway;
04201
04202 p->subs[a].chan = p->subs[b].chan;
04203 p->subs[a].owner = p->subs[b].owner;
04204 p->subs[a].inthreeway = p->subs[b].inthreeway;
04205
04206 p->subs[b].chan = tchan;
04207 p->subs[b].owner = towner;
04208 p->subs[b].inthreeway = tinthreeway;
04209
04210 if (p->subs[a].owner)
04211 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04212 if (p->subs[b].owner)
04213 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04214 wakeup_sub(p, a);
04215 wakeup_sub(p, b);
04216 }
04217
04218 static int dahdi_open(char *fn)
04219 {
04220 int fd;
04221 int isnum;
04222 int chan = 0;
04223 int bs;
04224 int x;
04225 isnum = 1;
04226 for (x = 0; x < strlen(fn); x++) {
04227 if (!isdigit(fn[x])) {
04228 isnum = 0;
04229 break;
04230 }
04231 }
04232 if (isnum) {
04233 chan = atoi(fn);
04234 if (chan < 1) {
04235 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04236 return -1;
04237 }
04238 fn = "/dev/dahdi/channel";
04239 }
04240 fd = open(fn, O_RDWR | O_NONBLOCK);
04241 if (fd < 0) {
04242 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04243 return -1;
04244 }
04245 if (chan) {
04246 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04247 x = errno;
04248 close(fd);
04249 errno = x;
04250 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04251 return -1;
04252 }
04253 }
04254 bs = READ_SIZE;
04255 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04256 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04257 x = errno;
04258 close(fd);
04259 errno = x;
04260 return -1;
04261 }
04262 return fd;
04263 }
04264
04265 static void dahdi_close(int fd)
04266 {
04267 if (fd > 0)
04268 close(fd);
04269 }
04270
04271 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04272 {
04273 dahdi_close(chan_pvt->subs[sub_num].dfd);
04274 chan_pvt->subs[sub_num].dfd = -1;
04275 }
04276
04277 #if defined(HAVE_PRI)
04278 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04279 {
04280 dahdi_close(pri->pri.fds[fd_num]);
04281 pri->pri.fds[fd_num] = -1;
04282 }
04283 #endif
04284
04285 #if defined(HAVE_SS7)
04286 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04287 {
04288 dahdi_close(ss7->ss7.fds[fd_num]);
04289 ss7->ss7.fds[fd_num] = -1;
04290 }
04291 #endif
04292
04293 static int dahdi_setlinear(int dfd, int linear)
04294 {
04295 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04296 }
04297
04298
04299 static int alloc_sub(struct dahdi_pvt *p, int x)
04300 {
04301 struct dahdi_bufferinfo bi;
04302 int res;
04303 if (p->subs[x].dfd >= 0) {
04304 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04305 return -1;
04306 }
04307
04308 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04309 if (p->subs[x].dfd <= -1) {
04310 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04311 return -1;
04312 }
04313
04314 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04315 if (!res) {
04316 bi.txbufpolicy = p->buf_policy;
04317 bi.rxbufpolicy = p->buf_policy;
04318 bi.numbufs = p->buf_no;
04319 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04320 if (res < 0) {
04321 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04322 }
04323 } else
04324 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04325
04326 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04327 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04328 dahdi_close_sub(p, x);
04329 p->subs[x].dfd = -1;
04330 return -1;
04331 }
04332 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04333 return 0;
04334 }
04335
04336 static int unalloc_sub(struct dahdi_pvt *p, int x)
04337 {
04338 if (!x) {
04339 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04340 return -1;
04341 }
04342 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04343 dahdi_close_sub(p, x);
04344 p->subs[x].linear = 0;
04345 p->subs[x].chan = 0;
04346 p->subs[x].owner = NULL;
04347 p->subs[x].inthreeway = 0;
04348 p->polarity = POLARITY_IDLE;
04349 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04350 return 0;
04351 }
04352
04353 static int digit_to_dtmfindex(char digit)
04354 {
04355 if (isdigit(digit))
04356 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04357 else if (digit >= 'A' && digit <= 'D')
04358 return DAHDI_TONE_DTMF_A + (digit - 'A');
04359 else if (digit >= 'a' && digit <= 'd')
04360 return DAHDI_TONE_DTMF_A + (digit - 'a');
04361 else if (digit == '*')
04362 return DAHDI_TONE_DTMF_s;
04363 else if (digit == '#')
04364 return DAHDI_TONE_DTMF_p;
04365 else
04366 return -1;
04367 }
04368
04369 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04370 {
04371 struct dahdi_pvt *pvt;
04372 int idx;
04373 int dtmf = -1;
04374 int res;
04375
04376 pvt = chan->tech_pvt;
04377
04378 ast_mutex_lock(&pvt->lock);
04379
04380 idx = dahdi_get_index(chan, pvt, 0);
04381
04382 if ((idx != SUB_REAL) || !pvt->owner)
04383 goto out;
04384
04385 #ifdef HAVE_PRI
04386 switch (pvt->sig) {
04387 case SIG_PRI_LIB_HANDLE_CASES:
04388 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04389 if (!res)
04390 goto out;
04391 break;
04392 default:
04393 break;
04394 }
04395 #endif
04396 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04397 goto out;
04398
04399 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04400 struct dahdi_dialoperation zo = {
04401 .op = DAHDI_DIAL_OP_APPEND,
04402 };
04403
04404 zo.dialstr[0] = 'T';
04405 zo.dialstr[1] = digit;
04406 zo.dialstr[2] = '\0';
04407 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04408 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04409 else
04410 pvt->dialing = 1;
04411 } else {
04412 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04413 pvt->dialing = 1;
04414 pvt->begindigit = digit;
04415 }
04416
04417 out:
04418 ast_mutex_unlock(&pvt->lock);
04419
04420 return 0;
04421 }
04422
04423 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04424 {
04425 struct dahdi_pvt *pvt;
04426 int res = 0;
04427 int idx;
04428 int x;
04429
04430 pvt = chan->tech_pvt;
04431
04432 ast_mutex_lock(&pvt->lock);
04433
04434 idx = dahdi_get_index(chan, pvt, 0);
04435
04436 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04437 goto out;
04438
04439 #ifdef HAVE_PRI
04440
04441 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04442 goto out;
04443 }
04444 #endif
04445
04446 if (pvt->begindigit) {
04447 x = -1;
04448 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04449 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04450 pvt->dialing = 0;
04451 pvt->begindigit = 0;
04452 }
04453
04454 out:
04455 ast_mutex_unlock(&pvt->lock);
04456
04457 return res;
04458 }
04459
04460 static const char * const events[] = {
04461 "No event",
04462 "On hook",
04463 "Ring/Answered",
04464 "Wink/Flash",
04465 "Alarm",
04466 "No more alarm",
04467 "HDLC Abort",
04468 "HDLC Overrun",
04469 "HDLC Bad FCS",
04470 "Dial Complete",
04471 "Ringer On",
04472 "Ringer Off",
04473 "Hook Transition Complete",
04474 "Bits Changed",
04475 "Pulse Start",
04476 "Timer Expired",
04477 "Timer Ping",
04478 "Polarity Reversal",
04479 "Ring Begin",
04480 };
04481
04482 static struct {
04483 int alarm;
04484 char *name;
04485 } alarms[] = {
04486 { DAHDI_ALARM_RED, "Red Alarm" },
04487 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04488 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04489 { DAHDI_ALARM_RECOVER, "Recovering" },
04490 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04491 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04492 { DAHDI_ALARM_NONE, "None" },
04493 };
04494
04495 static char *alarm2str(int alm)
04496 {
04497 int x;
04498 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04499 if (alarms[x].alarm & alm)
04500 return alarms[x].name;
04501 }
04502 return alm ? "Unknown Alarm" : "No Alarm";
04503 }
04504
04505 static const char *event2str(int event)
04506 {
04507 static char buf[256];
04508 if ((event < (ARRAY_LEN(events))) && (event > -1))
04509 return events[event];
04510 sprintf(buf, "Event %d", event);
04511 return buf;
04512 }
04513
04514 static char *dahdi_sig2str(int sig)
04515 {
04516 static char buf[256];
04517 switch (sig) {
04518 case SIG_EM:
04519 return "E & M Immediate";
04520 case SIG_EMWINK:
04521 return "E & M Wink";
04522 case SIG_EM_E1:
04523 return "E & M E1";
04524 case SIG_FEATD:
04525 return "Feature Group D (DTMF)";
04526 case SIG_FEATDMF:
04527 return "Feature Group D (MF)";
04528 case SIG_FEATDMF_TA:
04529 return "Feature Groud D (MF) Tandem Access";
04530 case SIG_FEATB:
04531 return "Feature Group B (MF)";
04532 case SIG_E911:
04533 return "E911 (MF)";
04534 case SIG_FGC_CAMA:
04535 return "FGC/CAMA (Dialpulse)";
04536 case SIG_FGC_CAMAMF:
04537 return "FGC/CAMA (MF)";
04538 case SIG_FXSLS:
04539 return "FXS Loopstart";
04540 case SIG_FXSGS:
04541 return "FXS Groundstart";
04542 case SIG_FXSKS:
04543 return "FXS Kewlstart";
04544 case SIG_FXOLS:
04545 return "FXO Loopstart";
04546 case SIG_FXOGS:
04547 return "FXO Groundstart";
04548 case SIG_FXOKS:
04549 return "FXO Kewlstart";
04550 case SIG_PRI:
04551 return "ISDN PRI";
04552 case SIG_BRI:
04553 return "ISDN BRI Point to Point";
04554 case SIG_BRI_PTMP:
04555 return "ISDN BRI Point to MultiPoint";
04556 case SIG_SS7:
04557 return "SS7";
04558 case SIG_MFCR2:
04559 return "MFC/R2";
04560 case SIG_SF:
04561 return "SF (Tone) Immediate";
04562 case SIG_SFWINK:
04563 return "SF (Tone) Wink";
04564 case SIG_SF_FEATD:
04565 return "SF (Tone) with Feature Group D (DTMF)";
04566 case SIG_SF_FEATDMF:
04567 return "SF (Tone) with Feature Group D (MF)";
04568 case SIG_SF_FEATB:
04569 return "SF (Tone) with Feature Group B (MF)";
04570 case 0:
04571 return "Pseudo";
04572 default:
04573 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04574 return buf;
04575 }
04576 }
04577
04578 #define sig2str dahdi_sig2str
04579
04580 static int analog_lib_handles(int signalling, int radio, int oprmode)
04581 {
04582 switch (signalling) {
04583 case SIG_FXOLS:
04584 case SIG_FXOGS:
04585 case SIG_FXOKS:
04586 case SIG_FXSLS:
04587 case SIG_FXSGS:
04588 case SIG_FXSKS:
04589 case SIG_EMWINK:
04590 case SIG_EM:
04591 case SIG_EM_E1:
04592 case SIG_FEATD:
04593 case SIG_FEATDMF:
04594 case SIG_E911:
04595 case SIG_FGC_CAMA:
04596 case SIG_FGC_CAMAMF:
04597 case SIG_FEATB:
04598 case SIG_SFWINK:
04599 case SIG_SF:
04600 case SIG_SF_FEATD:
04601 case SIG_SF_FEATDMF:
04602 case SIG_FEATDMF_TA:
04603 case SIG_SF_FEATB:
04604 break;
04605 default:
04606
04607 return 0;
04608 }
04609
04610 if (radio)
04611 return 0;
04612
04613 if (oprmode)
04614 return 0;
04615
04616 return 1;
04617 }
04618
04619 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04620 {
04621
04622
04623 struct dahdi_confinfo zi;
04624
04625 memset(&zi, 0, sizeof(zi));
04626 zi.chan = 0;
04627
04628 if (slavechannel > 0) {
04629
04630 zi.confmode = DAHDI_CONF_DIGITALMON;
04631 zi.confno = slavechannel;
04632 } else {
04633 if (!idx) {
04634
04635 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04636 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04637 } else
04638 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04639 zi.confno = p->confno;
04640 }
04641 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04642 return 0;
04643 if (c->dfd < 0)
04644 return 0;
04645 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04646 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04647 return -1;
04648 }
04649 if (slavechannel < 1) {
04650 p->confno = zi.confno;
04651 }
04652 c->curconf = zi;
04653 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04654 return 0;
04655 }
04656
04657 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04658 {
04659
04660 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04661 return 1;
04662
04663 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04664 return 1;
04665 return 0;
04666 }
04667
04668 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04669 {
04670 struct dahdi_confinfo zi;
04671 if (
04672 (c->dfd < 0) ||
04673
04674 !isourconf(p, c)
04675
04676 ) return 0;
04677 memset(&zi, 0, sizeof(zi));
04678 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04679 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04680 return -1;
04681 }
04682 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04683 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04684 return 0;
04685 }
04686
04687 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04688 {
04689 int x;
04690 int useslavenative;
04691 struct dahdi_pvt *slave = NULL;
04692
04693 useslavenative = 1;
04694
04695 for (x = 0; x < 3; x++) {
04696
04697
04698 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04699 useslavenative = 0;
04700 }
04701
04702
04703 if (useslavenative) {
04704 for (x = 0; x < MAX_SLAVES; x++) {
04705 if (p->slaves[x]) {
04706 if (slave) {
04707
04708
04709 slave = NULL;
04710 useslavenative = 0;
04711 break;
04712 } else {
04713
04714 slave = p->slaves[x];
04715 }
04716 }
04717 }
04718 }
04719
04720 if (!slave)
04721 useslavenative = 0;
04722 else if (slave->law != p->law) {
04723 useslavenative = 0;
04724 slave = NULL;
04725 }
04726 if (out)
04727 *out = slave;
04728 return useslavenative;
04729 }
04730
04731 static int reset_conf(struct dahdi_pvt *p)
04732 {
04733 p->confno = -1;
04734 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04735 if (p->subs[SUB_REAL].dfd > -1) {
04736 struct dahdi_confinfo zi;
04737
04738 memset(&zi, 0, sizeof(zi));
04739 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04740 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04741 }
04742 return 0;
04743 }
04744
04745 static int update_conf(struct dahdi_pvt *p)
04746 {
04747 int needconf = 0;
04748 int x;
04749 int useslavenative;
04750 struct dahdi_pvt *slave = NULL;
04751
04752 useslavenative = isslavenative(p, &slave);
04753
04754 for (x = 0; x < 3; x++) {
04755
04756 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04757 conf_add(p, &p->subs[x], x, 0);
04758 needconf++;
04759 } else {
04760 conf_del(p, &p->subs[x], x);
04761 }
04762 }
04763
04764
04765 for (x = 0; x < MAX_SLAVES; x++) {
04766 if (p->slaves[x]) {
04767 if (useslavenative)
04768 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04769 else {
04770 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04771 needconf++;
04772 }
04773 }
04774 }
04775
04776 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04777 if (useslavenative)
04778 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04779 else {
04780 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04781 needconf++;
04782 }
04783 }
04784
04785 if (p->master) {
04786 if (isslavenative(p->master, NULL)) {
04787 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04788 } else {
04789 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04790 }
04791 }
04792 if (!needconf) {
04793
04794
04795 p->confno = -1;
04796 }
04797 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04798 return 0;
04799 }
04800
04801 static void dahdi_enable_ec(struct dahdi_pvt *p)
04802 {
04803 int res;
04804 if (!p)
04805 return;
04806 if (p->echocanon) {
04807 ast_debug(1, "Echo cancellation already on\n");
04808 return;
04809 }
04810 if (p->digital) {
04811 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04812 return;
04813 }
04814 if (p->echocancel.head.tap_length) {
04815 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04816 switch (p->sig) {
04817 #if defined(HAVE_PRI)
04818 case SIG_PRI_LIB_HANDLE_CASES:
04819 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04820
04821
04822
04823
04824 return;
04825 }
04826
04827 #endif
04828 #if defined(HAVE_SS7)
04829 case SIG_SS7:
04830 #endif
04831 {
04832 int x = 1;
04833
04834 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04835 if (res)
04836 ast_log(LOG_WARNING,
04837 "Unable to enable audio mode on channel %d (%s)\n",
04838 p->channel, strerror(errno));
04839 }
04840 break;
04841 default:
04842 break;
04843 }
04844 #endif
04845 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04846 if (res) {
04847 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04848 } else {
04849 p->echocanon = 1;
04850 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04851 }
04852 } else
04853 ast_debug(1, "No echo cancellation requested\n");
04854 }
04855
04856 static void dahdi_train_ec(struct dahdi_pvt *p)
04857 {
04858 int x;
04859 int res;
04860
04861 if (p && p->echocanon && p->echotraining) {
04862 x = p->echotraining;
04863 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04864 if (res)
04865 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04866 else
04867 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04868 } else {
04869 ast_debug(1, "No echo training requested\n");
04870 }
04871 }
04872
04873 static void dahdi_disable_ec(struct dahdi_pvt *p)
04874 {
04875 int res;
04876
04877 if (p->echocanon) {
04878 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04879
04880 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04881
04882 if (res)
04883 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04884 else
04885 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04886 }
04887
04888 p->echocanon = 0;
04889 }
04890
04891
04892 static int drc_sample(int sample, float drc)
04893 {
04894 float neg;
04895 float shallow, steep;
04896 float max = SHRT_MAX;
04897
04898 neg = (sample < 0 ? -1 : 1);
04899 steep = drc*sample;
04900 shallow = neg*(max-max/drc)+(float)sample/drc;
04901 if (abs(steep) < abs(shallow)) {
04902 sample = steep;
04903 }
04904 else {
04905 sample = shallow;
04906 }
04907
04908 return sample;
04909 }
04910
04911
04912 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04913 {
04914 int j;
04915 int k;
04916
04917 float linear_gain = pow(10.0, gain / 20.0);
04918
04919 switch (law) {
04920 case DAHDI_LAW_ALAW:
04921 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04922 if (gain || drc) {
04923 k = AST_ALAW(j);
04924 if (drc) {
04925 k = drc_sample(k, drc);
04926 }
04927 k = (float)k*linear_gain;
04928 if (k > 32767) k = 32767;
04929 if (k < -32767) k = -32767;
04930 g->txgain[j] = AST_LIN2A(k);
04931 } else {
04932 g->txgain[j] = j;
04933 }
04934 }
04935 break;
04936 case DAHDI_LAW_MULAW:
04937 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04938 if (gain || drc) {
04939 k = AST_MULAW(j);
04940 if (drc) {
04941 k = drc_sample(k, drc);
04942 }
04943 k = (float)k*linear_gain;
04944 if (k > 32767) k = 32767;
04945 if (k < -32767) k = -32767;
04946 g->txgain[j] = AST_LIN2MU(k);
04947
04948 } else {
04949 g->txgain[j] = j;
04950 }
04951 }
04952 break;
04953 }
04954 }
04955
04956 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04957 {
04958 int j;
04959 int k;
04960 float linear_gain = pow(10.0, gain / 20.0);
04961
04962 switch (law) {
04963 case DAHDI_LAW_ALAW:
04964 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04965 if (gain || drc) {
04966 k = AST_ALAW(j);
04967 if (drc) {
04968 k = drc_sample(k, drc);
04969 }
04970 k = (float)k*linear_gain;
04971 if (k > 32767) k = 32767;
04972 if (k < -32767) k = -32767;
04973 g->rxgain[j] = AST_LIN2A(k);
04974 } else {
04975 g->rxgain[j] = j;
04976 }
04977 }
04978 break;
04979 case DAHDI_LAW_MULAW:
04980 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04981 if (gain || drc) {
04982 k = AST_MULAW(j);
04983 if (drc) {
04984 k = drc_sample(k, drc);
04985 }
04986 k = (float)k*linear_gain;
04987 if (k > 32767) k = 32767;
04988 if (k < -32767) k = -32767;
04989 g->rxgain[j] = AST_LIN2MU(k);
04990 } else {
04991 g->rxgain[j] = j;
04992 }
04993 }
04994 break;
04995 }
04996 }
04997
04998 static int set_actual_txgain(int fd, float gain, float drc, int law)
04999 {
05000 struct dahdi_gains g;
05001 int res;
05002
05003 memset(&g, 0, sizeof(g));
05004 res = ioctl(fd, DAHDI_GETGAINS, &g);
05005 if (res) {
05006 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05007 return res;
05008 }
05009
05010 fill_txgain(&g, gain, drc, law);
05011
05012 return ioctl(fd, DAHDI_SETGAINS, &g);
05013 }
05014
05015 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05016 {
05017 struct dahdi_gains g;
05018 int res;
05019
05020 memset(&g, 0, sizeof(g));
05021 res = ioctl(fd, DAHDI_GETGAINS, &g);
05022 if (res) {
05023 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05024 return res;
05025 }
05026
05027 fill_rxgain(&g, gain, drc, law);
05028
05029 return ioctl(fd, DAHDI_SETGAINS, &g);
05030 }
05031
05032 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05033 {
05034 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05035 }
05036
05037 static int bump_gains(struct dahdi_pvt *p)
05038 {
05039 int res;
05040
05041
05042 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05043 if (res) {
05044 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05045 return -1;
05046 }
05047
05048 return 0;
05049 }
05050
05051 static int restore_gains(struct dahdi_pvt *p)
05052 {
05053 int res;
05054
05055 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05056 if (res) {
05057 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05058 return -1;
05059 }
05060
05061 return 0;
05062 }
05063
05064 static inline int dahdi_set_hook(int fd, int hs)
05065 {
05066 int x, res;
05067
05068 x = hs;
05069 res = ioctl(fd, DAHDI_HOOK, &x);
05070
05071 if (res < 0) {
05072 if (errno == EINPROGRESS)
05073 return 0;
05074 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05075
05076 }
05077
05078 return res;
05079 }
05080
05081 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05082 {
05083 int x, res;
05084
05085 x = muted;
05086 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05087 switch (p->sig) {
05088 #if defined(HAVE_PRI)
05089 case SIG_PRI_LIB_HANDLE_CASES:
05090 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05091
05092 break;
05093 }
05094
05095 #endif
05096 #if defined(HAVE_SS7)
05097 case SIG_SS7:
05098 #endif
05099 {
05100 int y = 1;
05101
05102 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05103 if (res)
05104 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05105 p->channel, strerror(errno));
05106 }
05107 break;
05108 default:
05109 break;
05110 }
05111 #endif
05112 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05113 if (res < 0)
05114 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05115 return res;
05116 }
05117
05118 static int save_conference(struct dahdi_pvt *p)
05119 {
05120 struct dahdi_confinfo c;
05121 int res;
05122 if (p->saveconf.confmode) {
05123 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05124 return -1;
05125 }
05126 p->saveconf.chan = 0;
05127 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05128 if (res) {
05129 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05130 p->saveconf.confmode = 0;
05131 return -1;
05132 }
05133 memset(&c, 0, sizeof(c));
05134 c.confmode = DAHDI_CONF_NORMAL;
05135 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05136 if (res) {
05137 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05138 return -1;
05139 }
05140 ast_debug(1, "Disabled conferencing\n");
05141 return 0;
05142 }
05143
05144 static int restore_conference(struct dahdi_pvt *p)
05145 {
05146 int res;
05147 if (p->saveconf.confmode) {
05148 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05149 p->saveconf.confmode = 0;
05150 if (res) {
05151 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05152 return -1;
05153 }
05154 ast_debug(1, "Restored conferencing\n");
05155 }
05156 return 0;
05157 }
05158
05159 static int send_cwcidspill(struct dahdi_pvt *p)
05160 {
05161 p->callwaitcas = 0;
05162 p->cidcwexpire = 0;
05163 p->cid_suppress_expire = 0;
05164 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05165 return -1;
05166 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05167
05168 p->cidlen += READ_SIZE * 4;
05169 p->cidpos = 0;
05170 send_callerid(p);
05171 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05172 return 0;
05173 }
05174
05175 static int has_voicemail(struct dahdi_pvt *p)
05176 {
05177 int new_msgs;
05178 struct ast_event *event;
05179 char *mailbox, *context;
05180
05181 mailbox = context = ast_strdupa(p->mailbox);
05182 strsep(&context, "@");
05183 if (ast_strlen_zero(context))
05184 context = "default";
05185
05186 event = ast_event_get_cached(AST_EVENT_MWI,
05187 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05188 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05189 AST_EVENT_IE_END);
05190
05191 if (event) {
05192 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05193 ast_event_destroy(event);
05194 } else
05195 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05196
05197 return new_msgs;
05198 }
05199
05200
05201
05202 static int send_callerid(struct dahdi_pvt *p)
05203 {
05204
05205 int res;
05206
05207 if (p->subs[SUB_REAL].linear) {
05208 p->subs[SUB_REAL].linear = 0;
05209 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05210 }
05211 while (p->cidpos < p->cidlen) {
05212 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05213 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05214 if (res < 0) {
05215 if (errno == EAGAIN)
05216 return 0;
05217 else {
05218 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05219 return -1;
05220 }
05221 }
05222 if (!res)
05223 return 0;
05224 p->cidpos += res;
05225 }
05226 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05227 ast_free(p->cidspill);
05228 p->cidspill = NULL;
05229 if (p->callwaitcas) {
05230
05231 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05232 p->cid_suppress_expire = p->cidcwexpire;
05233 } else
05234 restore_conference(p);
05235 return 0;
05236 }
05237
05238 static int dahdi_callwait(struct ast_channel *ast)
05239 {
05240 struct dahdi_pvt *p = ast->tech_pvt;
05241 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05242 if (p->cidspill) {
05243 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05244 ast_free(p->cidspill);
05245 }
05246
05247
05248
05249
05250
05251 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05252 return -1;
05253 save_conference(p);
05254
05255 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05256 if (!p->callwaitrings && p->callwaitingcallerid) {
05257 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05258 p->callwaitcas = 1;
05259 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05260 } else {
05261 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05262 p->callwaitcas = 0;
05263 p->cidlen = 2400 + READ_SIZE * 4;
05264 }
05265 p->cidpos = 0;
05266 send_callerid(p);
05267
05268 return 0;
05269 }
05270
05271 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05272 {
05273 struct dahdi_pvt *p = ast->tech_pvt;
05274 int x, res, mysig;
05275 char dest[256];
05276
05277 ast_mutex_lock(&p->lock);
05278 ast_copy_string(dest, rdest, sizeof(dest));
05279 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05280 if ((ast->_state == AST_STATE_BUSY)) {
05281 p->subs[SUB_REAL].needbusy = 1;
05282 ast_mutex_unlock(&p->lock);
05283 return 0;
05284 }
05285 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05286 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05287 ast_mutex_unlock(&p->lock);
05288 return -1;
05289 }
05290 p->waitingfordt.tv_sec = 0;
05291 p->dialednone = 0;
05292 if ((p->radio || (p->oprmode < 0)))
05293 {
05294
05295 ast_setstate(ast, AST_STATE_UP);
05296 ast_mutex_unlock(&p->lock);
05297 return 0;
05298 }
05299 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05300 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05301 if (res)
05302 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05303 p->outgoing = 1;
05304
05305 if (IS_DIGITAL(ast->transfercapability)){
05306 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05307 } else {
05308 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05309 }
05310
05311 #ifdef HAVE_PRI
05312 if (dahdi_sig_pri_lib_handles(p->sig)) {
05313 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05314 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05315 ast_mutex_unlock(&p->lock);
05316 return res;
05317 }
05318 #endif
05319
05320 #if defined(HAVE_SS7)
05321 if (p->sig == SIG_SS7) {
05322 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05323 ast_mutex_unlock(&p->lock);
05324 return res;
05325 }
05326 #endif
05327
05328
05329 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05330 p->callwaitrings = 0;
05331 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05332 ast_mutex_unlock(&p->lock);
05333 return res;
05334 }
05335
05336 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05337 switch (mysig) {
05338 case 0:
05339
05340 ast_setstate(ast, AST_STATE_UP);
05341 break;
05342 case SIG_MFCR2:
05343 break;
05344 default:
05345 ast_debug(1, "not yet implemented\n");
05346 ast_mutex_unlock(&p->lock);
05347 return -1;
05348 }
05349
05350 #ifdef HAVE_OPENR2
05351 if (p->mfcr2) {
05352 openr2_calling_party_category_t chancat;
05353 int callres = 0;
05354 char *c, *l;
05355
05356
05357 p->dialdest[0] = '\0';
05358
05359 c = strchr(dest, '/');
05360 if (c) {
05361 c++;
05362 } else {
05363 c = "";
05364 }
05365 if (!p->hidecallerid) {
05366 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05367 } else {
05368 l = NULL;
05369 }
05370 if (strlen(c) < p->stripmsd) {
05371 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05372 ast_mutex_unlock(&p->lock);
05373 return -1;
05374 }
05375 p->dialing = 1;
05376 chancat = dahdi_r2_get_channel_category(ast);
05377 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05378 if (-1 == callres) {
05379 ast_mutex_unlock(&p->lock);
05380 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05381 return -1;
05382 }
05383 p->mfcr2_call_accepted = 0;
05384 p->mfcr2_progress = 0;
05385 ast_setstate(ast, AST_STATE_DIALING);
05386 }
05387 #endif
05388 ast_mutex_unlock(&p->lock);
05389 return 0;
05390 }
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404
05405
05406
05407 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05408 {
05409 struct dahdi_pvt *cur;
05410
05411 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05412
05413
05414 for (cur = iflist; cur; cur = cur->next) {
05415 if (pvt->channel < cur->channel) {
05416
05417 pvt->prev = cur->prev;
05418 pvt->next = cur;
05419 if (cur->prev) {
05420
05421 cur->prev->next = pvt;
05422 } else {
05423
05424 iflist = pvt;
05425 }
05426 cur->prev = pvt;
05427 return;
05428 }
05429 }
05430
05431
05432 pvt->prev = ifend;
05433 pvt->next = NULL;
05434 if (ifend) {
05435 ifend->next = pvt;
05436 }
05437 ifend = pvt;
05438 if (!iflist) {
05439
05440 iflist = pvt;
05441 }
05442 }
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453
05454
05455
05456
05457 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05458 {
05459
05460 if (pvt->prev) {
05461 pvt->prev->next = pvt->next;
05462 } else if (iflist == pvt) {
05463
05464 iflist = pvt->next;
05465 }
05466
05467
05468 if (pvt->next) {
05469 pvt->next->prev = pvt->prev;
05470 } else if (ifend == pvt) {
05471
05472 ifend = pvt->prev;
05473 }
05474
05475
05476 pvt->which_iflist = DAHDI_IFLIST_NONE;
05477 pvt->prev = NULL;
05478 pvt->next = NULL;
05479 }
05480
05481 #if defined(HAVE_PRI)
05482
05483
05484
05485
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497
05498 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05499 {
05500 struct dahdi_pvt *cur;
05501
05502 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05503
05504
05505 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05506 if (pvt->channel < cur->channel) {
05507
05508 pvt->prev = cur->prev;
05509 pvt->next = cur;
05510 if (cur->prev) {
05511
05512 cur->prev->next = pvt;
05513 } else {
05514
05515 pri->no_b_chan_iflist = pvt;
05516 }
05517 cur->prev = pvt;
05518 return;
05519 }
05520 }
05521
05522
05523 pvt->prev = pri->no_b_chan_end;
05524 pvt->next = NULL;
05525 if (pri->no_b_chan_end) {
05526 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05527 }
05528 pri->no_b_chan_end = pvt;
05529 if (!pri->no_b_chan_iflist) {
05530
05531 pri->no_b_chan_iflist = pvt;
05532 }
05533 }
05534 #endif
05535
05536 #if defined(HAVE_PRI)
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05552 {
05553
05554 if (pvt->prev) {
05555 pvt->prev->next = pvt->next;
05556 } else if (pri->no_b_chan_iflist == pvt) {
05557
05558 pri->no_b_chan_iflist = pvt->next;
05559 }
05560
05561
05562 if (pvt->next) {
05563 pvt->next->prev = pvt->prev;
05564 } else if (pri->no_b_chan_end == pvt) {
05565
05566 pri->no_b_chan_end = pvt->prev;
05567 }
05568
05569
05570 pvt->which_iflist = DAHDI_IFLIST_NONE;
05571 pvt->prev = NULL;
05572 pvt->next = NULL;
05573 }
05574 #endif
05575
05576 #if defined(HAVE_PRI)
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05587 {
05588 unsigned idx;
05589 struct sig_pri_span *pri;
05590
05591 pri = pvt->pri;
05592 if (!pri) {
05593
05594 return;
05595 }
05596 ast_mutex_lock(&pri->lock);
05597 for (idx = 0; idx < pri->numchans; ++idx) {
05598 if (pri->pvts[idx] == pvt->sig_pvt) {
05599 pri->pvts[idx] = NULL;
05600 ast_mutex_unlock(&pri->lock);
05601 return;
05602 }
05603 }
05604 ast_mutex_unlock(&pri->lock);
05605 }
05606 #endif
05607
05608 #if defined(HAVE_SS7)
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05619 {
05620 unsigned idx;
05621 struct sig_ss7_linkset *ss7;
05622
05623 ss7 = pvt->ss7;
05624 if (!ss7) {
05625
05626 return;
05627 }
05628 ast_mutex_lock(&ss7->lock);
05629 for (idx = 0; idx < ss7->numchans; ++idx) {
05630 if (ss7->pvts[idx] == pvt->sig_pvt) {
05631 ss7->pvts[idx] = NULL;
05632 ast_mutex_unlock(&ss7->lock);
05633 return;
05634 }
05635 }
05636 ast_mutex_unlock(&ss7->lock);
05637 }
05638 #endif
05639
05640 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05641 {
05642 if (cur->next && cur->next->span == cur->span) {
05643 return cur->next;
05644 } else if (cur->prev && cur->prev->span == cur->span) {
05645 return cur->prev;
05646 }
05647
05648 return NULL;
05649 }
05650
05651 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05652 {
05653 struct dahdi_pvt *p = pvt;
05654
05655 if (p->manages_span_alarms) {
05656 struct dahdi_pvt *next = find_next_iface_in_span(p);
05657 if (next) {
05658 next->manages_span_alarms = 1;
05659 }
05660 }
05661
05662
05663 #if defined(HAVE_PRI)
05664 dahdi_unlink_pri_pvt(p);
05665 #endif
05666 #if defined(HAVE_SS7)
05667 dahdi_unlink_ss7_pvt(p);
05668 #endif
05669 switch (pvt->which_iflist) {
05670 case DAHDI_IFLIST_NONE:
05671 break;
05672 case DAHDI_IFLIST_MAIN:
05673 dahdi_iflist_extract(p);
05674 break;
05675 #if defined(HAVE_PRI)
05676 case DAHDI_IFLIST_NO_B_CHAN:
05677 if (p->pri) {
05678 dahdi_nobch_extract(p->pri, p);
05679 }
05680 break;
05681 #endif
05682 }
05683
05684 if (p->sig_pvt) {
05685 if (analog_lib_handles(p->sig, 0, 0)) {
05686 analog_delete(p->sig_pvt);
05687 }
05688 switch (p->sig) {
05689 #if defined(HAVE_PRI)
05690 case SIG_PRI_LIB_HANDLE_CASES:
05691 sig_pri_chan_delete(p->sig_pvt);
05692 break;
05693 #endif
05694 #if defined(HAVE_SS7)
05695 case SIG_SS7:
05696 sig_ss7_chan_delete(p->sig_pvt);
05697 break;
05698 #endif
05699 default:
05700 break;
05701 }
05702 }
05703 ast_free(p->cidspill);
05704 if (p->use_smdi)
05705 ast_smdi_interface_unref(p->smdi_iface);
05706 if (p->mwi_event_sub)
05707 ast_event_unsubscribe(p->mwi_event_sub);
05708 if (p->vars) {
05709 ast_variables_destroy(p->vars);
05710 }
05711 if (p->cc_params) {
05712 ast_cc_config_params_destroy(p->cc_params);
05713 }
05714 ast_mutex_destroy(&p->lock);
05715 dahdi_close_sub(p, SUB_REAL);
05716 if (p->owner)
05717 p->owner->tech_pvt = NULL;
05718 ast_free(p);
05719 }
05720
05721 static void destroy_channel(struct dahdi_pvt *cur, int now)
05722 {
05723 int i;
05724
05725 if (!now) {
05726
05727 if (cur->owner) {
05728 return;
05729 }
05730 for (i = 0; i < 3; i++) {
05731 if (cur->subs[i].owner) {
05732 return;
05733 }
05734 }
05735 }
05736 destroy_dahdi_pvt(cur);
05737 }
05738
05739 static void destroy_all_channels(void)
05740 {
05741 int chan;
05742 #if defined(HAVE_PRI)
05743 unsigned span;
05744 struct sig_pri_span *pri;
05745 #endif
05746 struct dahdi_pvt *p;
05747
05748 while (num_restart_pending) {
05749 usleep(1);
05750 }
05751
05752 ast_mutex_lock(&iflock);
05753
05754 while (iflist) {
05755 p = iflist;
05756
05757 chan = p->channel;
05758 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05759 {
05760 char db_chan_name[20];
05761 char db_answer[5];
05762 char state;
05763 int why = -1;
05764
05765 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05766 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05767 sscanf(db_answer, "%1c:%30d", &state, &why);
05768 }
05769 if (!why) {
05770
05771 ast_db_del(db_chan_name, SRVST_DBKEY);
05772 }
05773 }
05774 #endif
05775
05776 destroy_dahdi_pvt(p);
05777 ast_verb(3, "Unregistered channel %d\n", chan);
05778 }
05779 ifcount = 0;
05780 ast_mutex_unlock(&iflock);
05781
05782 #if defined(HAVE_PRI)
05783
05784 for (span = 0; span < NUM_SPANS; ++span) {
05785 if (!pris[span].dchannels[0]) {
05786 break;
05787 }
05788 pri = &pris[span].pri;
05789 ast_mutex_lock(&pri->lock);
05790 while (pri->no_b_chan_iflist) {
05791 p = pri->no_b_chan_iflist;
05792
05793
05794 destroy_dahdi_pvt(p);
05795 }
05796 ast_mutex_unlock(&pri->lock);
05797 }
05798 #endif
05799 }
05800
05801 #if defined(HAVE_PRI)
05802 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05803
05804 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05805 {
05806
05807 struct dahdi_pvt *p;
05808
05809 if (ast_strlen_zero(digits)) {
05810 ast_debug(1, "No digit string sent to application!\n");
05811 return -1;
05812 }
05813
05814 p = (struct dahdi_pvt *)chan->tech_pvt;
05815
05816 if (!p) {
05817 ast_debug(1, "Unable to find technology private\n");
05818 return -1;
05819 }
05820
05821 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05822
05823 return 0;
05824 }
05825 #endif
05826
05827 #if defined(HAVE_PRI)
05828 #if defined(HAVE_PRI_PROG_W_CAUSE)
05829 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05830
05831 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05832 {
05833
05834 struct dahdi_pvt *pvt;
05835 char *parse;
05836 int res = -1;
05837 AST_DECLARE_APP_ARGS(args,
05838 AST_APP_ARG(destination);
05839 AST_APP_ARG(original);
05840 AST_APP_ARG(reason);
05841 );
05842
05843 if (ast_strlen_zero(data)) {
05844 ast_log(LOG_DEBUG, "No data sent to application!\n");
05845 return -1;
05846 }
05847 if (chan->tech != &dahdi_tech) {
05848 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05849 return -1;
05850 }
05851 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05852 if (!pvt) {
05853 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05854 return -1;
05855 }
05856 switch (pvt->sig) {
05857 case SIG_PRI_LIB_HANDLE_CASES:
05858 break;
05859 default:
05860 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05861 chan->name);
05862 return -1;
05863 }
05864
05865 parse = ast_strdupa(data);
05866 AST_STANDARD_APP_ARGS(args, parse);
05867
05868 if (ast_strlen_zero(args.destination)) {
05869 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05870 return -1;
05871 }
05872
05873 if (ast_strlen_zero(args.original)) {
05874 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05875 args.original = NULL;
05876 }
05877
05878 if (ast_strlen_zero(args.reason)) {
05879 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05880 args.reason = NULL;
05881 }
05882
05883 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05884 args.original, args.reason);
05885
05886 return res;
05887 }
05888 #endif
05889 #endif
05890
05891 #if defined(HAVE_OPENR2)
05892 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05893
05894 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05895 {
05896
05897 openr2_call_mode_t accept_mode;
05898 int res, timeout, maxloops;
05899 struct ast_frame *f;
05900 struct dahdi_pvt *p;
05901 char *parse;
05902 AST_DECLARE_APP_ARGS(args,
05903 AST_APP_ARG(charge);
05904 );
05905
05906 if (ast_strlen_zero(data)) {
05907 ast_log(LOG_DEBUG, "No data sent to application!\n");
05908 return -1;
05909 }
05910
05911 if (chan->tech != &dahdi_tech) {
05912 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05913 return -1;
05914 }
05915
05916 p = (struct dahdi_pvt *)chan->tech_pvt;
05917 if (!p) {
05918 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05919 return -1;
05920 }
05921
05922 parse = ast_strdupa(data);
05923 AST_STANDARD_APP_ARGS(args, parse);
05924
05925 if (ast_strlen_zero(args.charge)) {
05926 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05927 return -1;
05928 }
05929
05930 ast_mutex_lock(&p->lock);
05931 if (!p->mfcr2 || !p->mfcr2call) {
05932 ast_mutex_unlock(&p->lock);
05933 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05934 return -1;
05935 }
05936
05937 if (p->mfcr2_call_accepted) {
05938 ast_mutex_unlock(&p->lock);
05939 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05940 return 0;
05941 }
05942 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05943 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05944 ast_mutex_unlock(&p->lock);
05945 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05946 return -1;
05947 }
05948 ast_mutex_unlock(&p->lock);
05949
05950 res = 0;
05951 timeout = 100;
05952 maxloops = 50;
05953
05954 while (maxloops > 0) {
05955 maxloops--;
05956 if (ast_check_hangup(chan)) {
05957 break;
05958 }
05959 res = ast_waitfor(chan, timeout);
05960 if (res < 0) {
05961 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05962 res = -1;
05963 break;
05964 }
05965 if (res == 0) {
05966 continue;
05967 }
05968 f = ast_read(chan);
05969 if (!f) {
05970 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05971 res = -1;
05972 break;
05973 }
05974 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05975 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05976 ast_frfree(f);
05977 res = -1;
05978 break;
05979 }
05980 ast_frfree(f);
05981 ast_mutex_lock(&p->lock);
05982 if (p->mfcr2_call_accepted) {
05983 ast_mutex_unlock(&p->lock);
05984 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05985 break;
05986 }
05987 ast_mutex_unlock(&p->lock);
05988 }
05989 if (res == -1) {
05990 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05991 }
05992 return res;
05993 }
05994
05995 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05996 {
05997 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05998 switch (cause) {
05999 case AST_CAUSE_USER_BUSY:
06000 case AST_CAUSE_CALL_REJECTED:
06001 case AST_CAUSE_INTERWORKING:
06002 r2cause = OR2_CAUSE_BUSY_NUMBER;
06003 break;
06004
06005 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06006 case AST_CAUSE_SWITCH_CONGESTION:
06007 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06008 break;
06009
06010 case AST_CAUSE_UNALLOCATED:
06011 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06012 break;
06013
06014 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06015 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06016 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06017 break;
06018
06019 case AST_CAUSE_NO_ANSWER:
06020 case AST_CAUSE_NO_USER_RESPONSE:
06021 r2cause = OR2_CAUSE_NO_ANSWER;
06022 break;
06023
06024 default:
06025 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06026 break;
06027 }
06028 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06029 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06030 return r2cause;
06031 }
06032 #endif
06033
06034 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06035 {
06036 if (p->bufferoverrideinuse) {
06037
06038 struct dahdi_bufferinfo bi = {
06039 .txbufpolicy = p->buf_policy,
06040 .rxbufpolicy = p->buf_policy,
06041 .bufsize = p->bufsize,
06042 .numbufs = p->buf_no
06043 };
06044 int bpres;
06045
06046 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06047 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06048 }
06049 p->bufferoverrideinuse = 0;
06050 return bpres;
06051 }
06052
06053 return -1;
06054 }
06055
06056 static int dahdi_hangup(struct ast_channel *ast)
06057 {
06058 int res = 0;
06059 int idx,x;
06060 int law;
06061
06062 struct dahdi_pvt *p = ast->tech_pvt;
06063 struct dahdi_params par;
06064
06065 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06066 if (!ast->tech_pvt) {
06067 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06068 return 0;
06069 }
06070
06071 ast_mutex_lock(&p->lock);
06072 p->exten[0] = '\0';
06073 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06074 dahdi_confmute(p, 0);
06075 restore_gains(p);
06076 p->ignoredtmf = 0;
06077 p->waitingfordt.tv_sec = 0;
06078
06079 res = analog_hangup(p->sig_pvt, ast);
06080 revert_fax_buffers(p, ast);
06081
06082 goto hangup_out;
06083 } else {
06084 p->cid_num[0] = '\0';
06085 p->cid_name[0] = '\0';
06086 p->cid_subaddr[0] = '\0';
06087 }
06088
06089 #if defined(HAVE_PRI)
06090 if (dahdi_sig_pri_lib_handles(p->sig)) {
06091 x = 1;
06092 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06093
06094 dahdi_confmute(p, 0);
06095 p->muting = 0;
06096 restore_gains(p);
06097 if (p->dsp) {
06098 ast_dsp_free(p->dsp);
06099 p->dsp = NULL;
06100 }
06101 p->ignoredtmf = 0;
06102
06103
06104 p->subs[SUB_REAL].owner = NULL;
06105 p->subs[SUB_REAL].needbusy = 0;
06106 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06107
06108 p->owner = NULL;
06109 p->cid_tag[0] = '\0';
06110 p->ringt = 0;
06111 p->distinctivering = 0;
06112 p->confirmanswer = 0;
06113 p->outgoing = 0;
06114 p->digital = 0;
06115 p->faxhandled = 0;
06116 p->pulsedial = 0;
06117
06118 revert_fax_buffers(p, ast);
06119
06120 p->law = p->law_default;
06121 law = p->law_default;
06122 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06123 if (res < 0) {
06124 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06125 p->channel, strerror(errno));
06126 }
06127
06128 sig_pri_hangup(p->sig_pvt, ast);
06129
06130 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06131 dahdi_disable_ec(p);
06132
06133 x = 0;
06134 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06135 p->didtdd = 0;
06136
06137 p->rdnis[0] = '\0';
06138 update_conf(p);
06139 reset_conf(p);
06140
06141
06142 x = 0;
06143 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06144
06145 if (num_restart_pending == 0) {
06146 restart_monitor();
06147 }
06148 goto hangup_out;
06149 }
06150 #endif
06151
06152 #if defined(HAVE_SS7)
06153 if (p->sig == SIG_SS7) {
06154 x = 1;
06155 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06156
06157 dahdi_confmute(p, 0);
06158 p->muting = 0;
06159 restore_gains(p);
06160 if (p->dsp) {
06161 ast_dsp_free(p->dsp);
06162 p->dsp = NULL;
06163 }
06164 p->ignoredtmf = 0;
06165
06166
06167 p->subs[SUB_REAL].owner = NULL;
06168 p->subs[SUB_REAL].needbusy = 0;
06169 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06170
06171 p->owner = NULL;
06172 p->ringt = 0;
06173 p->distinctivering = 0;
06174 p->confirmanswer = 0;
06175 p->outgoing = 0;
06176 p->digital = 0;
06177 p->faxhandled = 0;
06178 p->pulsedial = 0;
06179
06180 revert_fax_buffers(p, ast);
06181
06182 p->law = p->law_default;
06183 law = p->law_default;
06184 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06185 if (res < 0) {
06186 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06187 p->channel, strerror(errno));
06188 }
06189
06190 sig_ss7_hangup(p->sig_pvt, ast);
06191
06192 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06193 dahdi_disable_ec(p);
06194
06195 x = 0;
06196 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06197 p->didtdd = 0;
06198
06199 update_conf(p);
06200 reset_conf(p);
06201
06202
06203 x = 0;
06204 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06205
06206 if (num_restart_pending == 0) {
06207 restart_monitor();
06208 }
06209 goto hangup_out;
06210 }
06211 #endif
06212
06213 idx = dahdi_get_index(ast, p, 1);
06214
06215 dahdi_confmute(p, 0);
06216 p->muting = 0;
06217 restore_gains(p);
06218 if (p->origcid_num) {
06219 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06220 ast_free(p->origcid_num);
06221 p->origcid_num = NULL;
06222 }
06223 if (p->origcid_name) {
06224 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06225 ast_free(p->origcid_name);
06226 p->origcid_name = NULL;
06227 }
06228 if (p->dsp)
06229 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06230
06231 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06232 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06233 p->ignoredtmf = 0;
06234
06235 if (idx > -1) {
06236
06237 p->subs[idx].owner = NULL;
06238 p->subs[idx].needanswer = 0;
06239 p->subs[idx].needflash = 0;
06240 p->subs[idx].needringing = 0;
06241 p->subs[idx].needbusy = 0;
06242 p->subs[idx].needcongestion = 0;
06243 p->subs[idx].linear = 0;
06244 p->polarity = POLARITY_IDLE;
06245 dahdi_setlinear(p->subs[idx].dfd, 0);
06246 if (idx == SUB_REAL) {
06247 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06248 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06249 if (p->subs[SUB_CALLWAIT].inthreeway) {
06250
06251 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06252
06253 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06254 unalloc_sub(p, SUB_CALLWAIT);
06255 p->owner = NULL;
06256 } else {
06257
06258 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06259 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06260 unalloc_sub(p, SUB_THREEWAY);
06261 if (p->subs[SUB_REAL].inthreeway) {
06262
06263
06264 ast_debug(1, "Call was complete, setting owner to former third call\n");
06265 p->owner = p->subs[SUB_REAL].owner;
06266 } else {
06267
06268 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06269 p->owner = NULL;
06270 }
06271 p->subs[SUB_REAL].inthreeway = 0;
06272 }
06273 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06274
06275 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06276 unalloc_sub(p, SUB_CALLWAIT);
06277 p->owner = p->subs[SUB_REAL].owner;
06278 if (p->owner->_state != AST_STATE_UP)
06279 p->subs[SUB_REAL].needanswer = 1;
06280 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06281 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06282 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06283 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06284 unalloc_sub(p, SUB_THREEWAY);
06285 if (p->subs[SUB_REAL].inthreeway) {
06286
06287
06288 ast_debug(1, "Call was complete, setting owner to former third call\n");
06289 p->owner = p->subs[SUB_REAL].owner;
06290 } else {
06291
06292 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06293 p->owner = NULL;
06294 }
06295 p->subs[SUB_REAL].inthreeway = 0;
06296 }
06297 } else if (idx == SUB_CALLWAIT) {
06298
06299 if (p->subs[SUB_CALLWAIT].inthreeway) {
06300
06301
06302 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06303 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06304 S_OR(p->mohsuggest, NULL),
06305 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06306 }
06307 p->subs[SUB_THREEWAY].inthreeway = 0;
06308
06309 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06310 unalloc_sub(p, SUB_THREEWAY);
06311 } else
06312 unalloc_sub(p, SUB_CALLWAIT);
06313 } else if (idx == SUB_THREEWAY) {
06314 if (p->subs[SUB_CALLWAIT].inthreeway) {
06315
06316
06317 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06318 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06319 S_OR(p->mohsuggest, NULL),
06320 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06321 }
06322 p->subs[SUB_CALLWAIT].inthreeway = 0;
06323 }
06324 p->subs[SUB_REAL].inthreeway = 0;
06325
06326
06327 unalloc_sub(p, SUB_THREEWAY);
06328 } else {
06329
06330 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06331 }
06332 }
06333
06334 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06335 p->owner = NULL;
06336 p->ringt = 0;
06337 p->distinctivering = 0;
06338 p->confirmanswer = 0;
06339 p->outgoing = 0;
06340 p->digital = 0;
06341 p->faxhandled = 0;
06342 p->pulsedial = 0;
06343 if (p->dsp) {
06344 ast_dsp_free(p->dsp);
06345 p->dsp = NULL;
06346 }
06347
06348 revert_fax_buffers(p, ast);
06349
06350 p->law = p->law_default;
06351 law = p->law_default;
06352 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06353 if (res < 0)
06354 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06355
06356 #ifdef HAVE_OPENR2
06357 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06358 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06359
06360 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06361 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06362 } else {
06363 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06364 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06365 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06366 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06367 dahdi_r2_disconnect_call(p, r2cause);
06368 }
06369 } else if (p->mfcr2call) {
06370 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06371
06372
06373
06374
06375 p->mfcr2call = 0;
06376 }
06377 #endif
06378 switch (p->sig) {
06379 case SIG_SS7:
06380 case SIG_MFCR2:
06381 case SIG_PRI_LIB_HANDLE_CASES:
06382 case 0:
06383 break;
06384 default:
06385 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06386 break;
06387 }
06388 if (res < 0) {
06389 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06390 }
06391 switch (p->sig) {
06392 case SIG_FXOGS:
06393 case SIG_FXOLS:
06394 case SIG_FXOKS:
06395 memset(&par, 0, sizeof(par));
06396 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06397 if (!res) {
06398 struct analog_pvt *analog_p = p->sig_pvt;
06399 #if 0
06400 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06401 #endif
06402
06403 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06404 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06405 else
06406 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06407 analog_p->fxsoffhookstate = par.rxisoffhook;
06408 }
06409 break;
06410 case SIG_FXSGS:
06411 case SIG_FXSLS:
06412 case SIG_FXSKS:
06413
06414
06415 if (ast->_state != AST_STATE_RESERVED) {
06416 time(&p->guardtime);
06417 p->guardtime += 2;
06418 }
06419 break;
06420 default:
06421 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06422 break;
06423 }
06424 if (p->sig)
06425 dahdi_disable_ec(p);
06426 x = 0;
06427 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06428 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06429 p->didtdd = 0;
06430 p->callwaitcas = 0;
06431 p->callwaiting = p->permcallwaiting;
06432 p->hidecallerid = p->permhidecallerid;
06433 p->waitingfordt.tv_sec = 0;
06434 p->dialing = 0;
06435 p->rdnis[0] = '\0';
06436 update_conf(p);
06437 reset_conf(p);
06438
06439 switch (p->sig) {
06440 case SIG_PRI_LIB_HANDLE_CASES:
06441 case SIG_SS7:
06442 x = 0;
06443 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06444 break;
06445 default:
06446 break;
06447 }
06448 if (num_restart_pending == 0)
06449 restart_monitor();
06450 }
06451
06452 p->callwaitingrepeat = 0;
06453 p->cidcwexpire = 0;
06454 p->cid_suppress_expire = 0;
06455 p->oprmode = 0;
06456 hangup_out:
06457 ast->tech_pvt = NULL;
06458 ast_free(p->cidspill);
06459 p->cidspill = NULL;
06460
06461 ast_mutex_unlock(&p->lock);
06462 ast_verb(3, "Hungup '%s'\n", ast->name);
06463
06464 ast_mutex_lock(&iflock);
06465 if (p->restartpending) {
06466 num_restart_pending--;
06467 }
06468
06469 if (p->destroy) {
06470 destroy_channel(p, 0);
06471 }
06472 ast_mutex_unlock(&iflock);
06473
06474 ast_module_unref(ast_module_info->self);
06475 return 0;
06476 }
06477
06478 static int dahdi_answer(struct ast_channel *ast)
06479 {
06480 struct dahdi_pvt *p = ast->tech_pvt;
06481 int res = 0;
06482 int idx;
06483 ast_setstate(ast, AST_STATE_UP);
06484 ast_mutex_lock(&p->lock);
06485 idx = dahdi_get_index(ast, p, 0);
06486 if (idx < 0)
06487 idx = SUB_REAL;
06488
06489 if ((p->radio || (p->oprmode < 0))) {
06490 ast_mutex_unlock(&p->lock);
06491 return 0;
06492 }
06493
06494 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06495 res = analog_answer(p->sig_pvt, ast);
06496 ast_mutex_unlock(&p->lock);
06497 return res;
06498 }
06499
06500 switch (p->sig) {
06501 #if defined(HAVE_PRI)
06502 case SIG_PRI_LIB_HANDLE_CASES:
06503 res = sig_pri_answer(p->sig_pvt, ast);
06504 break;
06505 #endif
06506 #if defined(HAVE_SS7)
06507 case SIG_SS7:
06508 res = sig_ss7_answer(p->sig_pvt, ast);
06509 break;
06510 #endif
06511 #ifdef HAVE_OPENR2
06512 case SIG_MFCR2:
06513 if (!p->mfcr2_call_accepted) {
06514
06515
06516 p->mfcr2_answer_pending = 1;
06517 if (p->mfcr2_charge_calls) {
06518 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06519 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06520 } else {
06521 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06522 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06523 }
06524 } else {
06525 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06526 dahdi_r2_answer(p);
06527 }
06528 break;
06529 #endif
06530 case 0:
06531 ast_mutex_unlock(&p->lock);
06532 return 0;
06533 default:
06534 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06535 res = -1;
06536 break;
06537 }
06538 ast_mutex_unlock(&p->lock);
06539 return res;
06540 }
06541
06542 static void disable_dtmf_detect(struct dahdi_pvt *p)
06543 {
06544 int val = 0;
06545
06546 p->ignoredtmf = 1;
06547
06548 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06549
06550 if (!p->hardwaredtmf && p->dsp) {
06551 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06552 ast_dsp_set_features(p->dsp, p->dsp_features);
06553 }
06554 }
06555
06556 static void enable_dtmf_detect(struct dahdi_pvt *p)
06557 {
06558 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06559
06560 if (p->channel == CHAN_PSEUDO)
06561 return;
06562
06563 p->ignoredtmf = 0;
06564
06565 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06566
06567 if (!p->hardwaredtmf && p->dsp) {
06568 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06569 ast_dsp_set_features(p->dsp, p->dsp_features);
06570 }
06571 }
06572
06573 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06574 {
06575 char *cp;
06576 struct dahdi_pvt *p = chan->tech_pvt;
06577
06578
06579 if (!data || (*datalen < 1)) {
06580 errno = EINVAL;
06581 return -1;
06582 }
06583
06584 switch (option) {
06585 case AST_OPTION_DIGIT_DETECT:
06586 cp = (char *) data;
06587 *cp = p->ignoredtmf ? 0 : 1;
06588 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06589 break;
06590 case AST_OPTION_FAX_DETECT:
06591 cp = (char *) data;
06592 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06593 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06594 break;
06595 case AST_OPTION_CC_AGENT_TYPE:
06596 #if defined(HAVE_PRI)
06597 #if defined(HAVE_PRI_CCSS)
06598 if (dahdi_sig_pri_lib_handles(p->sig)) {
06599 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06600 break;
06601 }
06602 #endif
06603 #endif
06604 return -1;
06605 default:
06606 return -1;
06607 }
06608
06609 errno = 0;
06610
06611 return 0;
06612 }
06613
06614 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06615 {
06616 char *cp;
06617 signed char *scp;
06618 int x;
06619 int idx;
06620 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06621 struct oprmode *oprmode;
06622
06623
06624
06625 if (!data || (datalen < 1)) {
06626 errno = EINVAL;
06627 return -1;
06628 }
06629
06630 switch (option) {
06631 case AST_OPTION_TXGAIN:
06632 scp = (signed char *) data;
06633 idx = dahdi_get_index(chan, p, 0);
06634 if (idx < 0) {
06635 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06636 return -1;
06637 }
06638 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06639 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06640 case AST_OPTION_RXGAIN:
06641 scp = (signed char *) data;
06642 idx = dahdi_get_index(chan, p, 0);
06643 if (idx < 0) {
06644 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06645 return -1;
06646 }
06647 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06648 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06649 case AST_OPTION_TONE_VERIFY:
06650 if (!p->dsp)
06651 break;
06652 cp = (char *) data;
06653 switch (*cp) {
06654 case 1:
06655 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06656 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06657 break;
06658 case 2:
06659 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06660 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06661 break;
06662 default:
06663 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06664 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06665 break;
06666 }
06667 break;
06668 case AST_OPTION_TDD:
06669
06670 cp = (char *) data;
06671 p->mate = 0;
06672 if (!*cp) {
06673 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06674 if (p->tdd)
06675 tdd_free(p->tdd);
06676 p->tdd = 0;
06677 break;
06678 }
06679 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06680 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06681 dahdi_disable_ec(p);
06682
06683 if (!p->didtdd) {
06684 unsigned char mybuf[41000];
06685 unsigned char *buf;
06686 int size, res, fd, len;
06687 struct pollfd fds[1];
06688
06689 buf = mybuf;
06690 memset(buf, 0x7f, sizeof(mybuf));
06691 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06692 len = 40000;
06693 idx = dahdi_get_index(chan, p, 0);
06694 if (idx < 0) {
06695 ast_log(LOG_WARNING, "No index in TDD?\n");
06696 return -1;
06697 }
06698 fd = p->subs[idx].dfd;
06699 while (len) {
06700 if (ast_check_hangup(chan))
06701 return -1;
06702 size = len;
06703 if (size > READ_SIZE)
06704 size = READ_SIZE;
06705 fds[0].fd = fd;
06706 fds[0].events = POLLPRI | POLLOUT;
06707 fds[0].revents = 0;
06708 res = poll(fds, 1, -1);
06709 if (!res) {
06710 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06711 continue;
06712 }
06713
06714 if (fds[0].revents & POLLPRI)
06715 return -1;
06716 if (!(fds[0].revents & POLLOUT)) {
06717 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06718 continue;
06719 }
06720 res = write(fd, buf, size);
06721 if (res != size) {
06722 if (res == -1) return -1;
06723 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06724 break;
06725 }
06726 len -= size;
06727 buf += size;
06728 }
06729 p->didtdd = 1;
06730 }
06731 if (*cp == 2) {
06732 if (p->tdd)
06733 tdd_free(p->tdd);
06734 p->tdd = 0;
06735 p->mate = 1;
06736 break;
06737 }
06738 if (!p->tdd) {
06739 p->tdd = tdd_new();
06740 }
06741 break;
06742 case AST_OPTION_RELAXDTMF:
06743 if (!p->dsp)
06744 break;
06745 cp = (char *) data;
06746 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06747 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06748 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06749 break;
06750 case AST_OPTION_AUDIO_MODE:
06751 #if defined(HAVE_PRI)
06752 if (dahdi_sig_pri_lib_handles(p->sig)
06753 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06754
06755 break;
06756 }
06757 #endif
06758
06759 cp = (char *) data;
06760 if (!*cp) {
06761 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06762 x = 0;
06763 dahdi_disable_ec(p);
06764 } else {
06765 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06766 x = 1;
06767 }
06768 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06769 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06770 break;
06771 case AST_OPTION_OPRMODE:
06772 oprmode = (struct oprmode *) data;
06773
06774 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06775 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06776 chan->tech->type, oprmode->peer->tech->type);
06777 errno = EINVAL;
06778 return -1;
06779 }
06780 pp = oprmode->peer->tech_pvt;
06781 p->oprmode = pp->oprmode = 0;
06782
06783 p->oprpeer = pp;
06784 pp->oprpeer = p;
06785
06786 if (oprmode->mode)
06787 {
06788 pp->oprmode = oprmode->mode;
06789 p->oprmode = -oprmode->mode;
06790 }
06791 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06792 oprmode->mode, chan->name,oprmode->peer->name);
06793 break;
06794 case AST_OPTION_ECHOCAN:
06795 cp = (char *) data;
06796 if (*cp) {
06797 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06798 dahdi_enable_ec(p);
06799 } else {
06800 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06801 dahdi_disable_ec(p);
06802 }
06803 break;
06804 case AST_OPTION_DIGIT_DETECT:
06805 cp = (char *) data;
06806 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06807 if (*cp) {
06808 enable_dtmf_detect(p);
06809 } else {
06810 disable_dtmf_detect(p);
06811 }
06812 break;
06813 case AST_OPTION_FAX_DETECT:
06814 cp = (char *) data;
06815 if (p->dsp) {
06816 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06817 if (*cp) {
06818 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06819 } else {
06820 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06821 }
06822 ast_dsp_set_features(p->dsp, p->dsp_features);
06823 }
06824 break;
06825 default:
06826 return -1;
06827 }
06828 errno = 0;
06829
06830 return 0;
06831 }
06832
06833 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06834 {
06835 struct dahdi_pvt *p = chan->tech_pvt;
06836 int res = 0;
06837
06838 if (!strcasecmp(data, "rxgain")) {
06839 ast_mutex_lock(&p->lock);
06840 snprintf(buf, len, "%f", p->rxgain);
06841 ast_mutex_unlock(&p->lock);
06842 } else if (!strcasecmp(data, "txgain")) {
06843 ast_mutex_lock(&p->lock);
06844 snprintf(buf, len, "%f", p->txgain);
06845 ast_mutex_unlock(&p->lock);
06846 } else if (!strcasecmp(data, "dahdi_channel")) {
06847 ast_mutex_lock(&p->lock);
06848 snprintf(buf, len, "%d", p->channel);
06849 ast_mutex_unlock(&p->lock);
06850 } else if (!strcasecmp(data, "dahdi_span")) {
06851 ast_mutex_lock(&p->lock);
06852 snprintf(buf, len, "%d", p->span);
06853 ast_mutex_unlock(&p->lock);
06854 } else if (!strcasecmp(data, "dahdi_type")) {
06855 ast_mutex_lock(&p->lock);
06856 switch (p->sig) {
06857 #if defined(HAVE_OPENR2)
06858 case SIG_MFCR2:
06859 ast_copy_string(buf, "mfc/r2", len);
06860 break;
06861 #endif
06862 #if defined(HAVE_PRI)
06863 case SIG_PRI_LIB_HANDLE_CASES:
06864 ast_copy_string(buf, "pri", len);
06865 break;
06866 #endif
06867 case 0:
06868 ast_copy_string(buf, "pseudo", len);
06869 break;
06870 #if defined(HAVE_SS7)
06871 case SIG_SS7:
06872 ast_copy_string(buf, "ss7", len);
06873 break;
06874 #endif
06875 default:
06876
06877 ast_copy_string(buf, "analog", len);
06878 break;
06879 }
06880 ast_mutex_unlock(&p->lock);
06881 #if defined(HAVE_PRI)
06882 #if defined(HAVE_PRI_REVERSE_CHARGE)
06883 } else if (!strcasecmp(data, "reversecharge")) {
06884 ast_mutex_lock(&p->lock);
06885 switch (p->sig) {
06886 case SIG_PRI_LIB_HANDLE_CASES:
06887 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06888 break;
06889 default:
06890 *buf = '\0';
06891 res = -1;
06892 break;
06893 }
06894 ast_mutex_unlock(&p->lock);
06895 #endif
06896 #if defined(HAVE_PRI_SETUP_KEYPAD)
06897 } else if (!strcasecmp(data, "keypad_digits")) {
06898 ast_mutex_lock(&p->lock);
06899 switch (p->sig) {
06900 case SIG_PRI_LIB_HANDLE_CASES:
06901 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06902 len);
06903 break;
06904 default:
06905 *buf = '\0';
06906 res = -1;
06907 break;
06908 }
06909 ast_mutex_unlock(&p->lock);
06910 #endif
06911 } else if (!strcasecmp(data, "no_media_path")) {
06912 ast_mutex_lock(&p->lock);
06913 switch (p->sig) {
06914 case SIG_PRI_LIB_HANDLE_CASES:
06915
06916
06917
06918
06919 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06920 break;
06921 default:
06922 *buf = '\0';
06923 res = -1;
06924 break;
06925 }
06926 ast_mutex_unlock(&p->lock);
06927 #endif
06928 } else {
06929 *buf = '\0';
06930 res = -1;
06931 }
06932
06933 return res;
06934 }
06935
06936
06937 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06938 {
06939 int res;
06940 char policy_str[21] = "";
06941
06942 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06943 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06944 return 1;
06945 }
06946 if (*num_buffers < 0) {
06947 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06948 return -1;
06949 }
06950 if (!strcasecmp(policy_str, "full")) {
06951 *policy = DAHDI_POLICY_WHEN_FULL;
06952 } else if (!strcasecmp(policy_str, "immediate")) {
06953 *policy = DAHDI_POLICY_IMMEDIATE;
06954 #if defined(HAVE_DAHDI_HALF_FULL)
06955 } else if (!strcasecmp(policy_str, "half")) {
06956 *policy = DAHDI_POLICY_HALF_FULL;
06957 #endif
06958 } else {
06959 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06960 return -1;
06961 }
06962
06963 return 0;
06964 }
06965
06966 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06967 {
06968 struct dahdi_pvt *p = chan->tech_pvt;
06969 int res = 0;
06970
06971 if (!strcasecmp(data, "buffers")) {
06972 int num_bufs, policy;
06973
06974 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06975 struct dahdi_bufferinfo bi = {
06976 .txbufpolicy = policy,
06977 .rxbufpolicy = policy,
06978 .bufsize = p->bufsize,
06979 .numbufs = num_bufs,
06980 };
06981 int bpres;
06982
06983 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06984 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06985 } else {
06986 p->bufferoverrideinuse = 1;
06987 }
06988 } else {
06989 res = -1;
06990 }
06991 } else if (!strcasecmp(data, "echocan_mode")) {
06992 if (!strcasecmp(value, "on")) {
06993 ast_mutex_lock(&p->lock);
06994 dahdi_enable_ec(p);
06995 ast_mutex_unlock(&p->lock);
06996 } else if (!strcasecmp(value, "off")) {
06997 ast_mutex_lock(&p->lock);
06998 dahdi_disable_ec(p);
06999 ast_mutex_unlock(&p->lock);
07000 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07001 } else if (!strcasecmp(value, "fax")) {
07002 int blah = 1;
07003
07004 ast_mutex_lock(&p->lock);
07005 if (!p->echocanon) {
07006 dahdi_enable_ec(p);
07007 }
07008 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07009 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07010 }
07011 ast_mutex_unlock(&p->lock);
07012 } else if (!strcasecmp(value, "voice")) {
07013 int blah = 0;
07014
07015 ast_mutex_lock(&p->lock);
07016 if (!p->echocanon) {
07017 dahdi_enable_ec(p);
07018 }
07019 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07020 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07021 }
07022 ast_mutex_unlock(&p->lock);
07023 #endif
07024 } else {
07025 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07026 res = -1;
07027 }
07028 } else {
07029 res = -1;
07030 }
07031
07032 return res;
07033 }
07034
07035 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07036 {
07037
07038 int x;
07039 int hasslaves;
07040 if (!master)
07041 return;
07042 if (needlock) {
07043 ast_mutex_lock(&master->lock);
07044 if (slave) {
07045 while (ast_mutex_trylock(&slave->lock)) {
07046 DEADLOCK_AVOIDANCE(&master->lock);
07047 }
07048 }
07049 }
07050 hasslaves = 0;
07051 for (x = 0; x < MAX_SLAVES; x++) {
07052 if (master->slaves[x]) {
07053 if (!slave || (master->slaves[x] == slave)) {
07054
07055 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07056 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07057 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07058 master->slaves[x]->master = NULL;
07059 master->slaves[x] = NULL;
07060 } else
07061 hasslaves = 1;
07062 }
07063 if (!hasslaves)
07064 master->inconference = 0;
07065 }
07066 if (!slave) {
07067 if (master->master) {
07068
07069 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07070 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07071 hasslaves = 0;
07072 for (x = 0; x < MAX_SLAVES; x++) {
07073 if (master->master->slaves[x] == master)
07074 master->master->slaves[x] = NULL;
07075 else if (master->master->slaves[x])
07076 hasslaves = 1;
07077 }
07078 if (!hasslaves)
07079 master->master->inconference = 0;
07080 }
07081 master->master = NULL;
07082 }
07083 update_conf(master);
07084 if (needlock) {
07085 if (slave)
07086 ast_mutex_unlock(&slave->lock);
07087 ast_mutex_unlock(&master->lock);
07088 }
07089 }
07090
07091 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07092 int x;
07093 if (!slave || !master) {
07094 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07095 return;
07096 }
07097 for (x = 0; x < MAX_SLAVES; x++) {
07098 if (!master->slaves[x]) {
07099 master->slaves[x] = slave;
07100 break;
07101 }
07102 }
07103 if (x >= MAX_SLAVES) {
07104 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07105 master->slaves[MAX_SLAVES - 1] = slave;
07106 }
07107 if (slave->master)
07108 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07109 slave->master = master;
07110
07111 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07112 }
07113
07114 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)
07115 {
07116 struct ast_channel *who;
07117 struct dahdi_pvt *p0, *p1, *op0, *op1;
07118 struct dahdi_pvt *master = NULL, *slave = NULL;
07119 struct ast_frame *f;
07120 int inconf = 0;
07121 int nothingok = 1;
07122 int ofd0, ofd1;
07123 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07124 int os0 = -1, os1 = -1;
07125 int priority = 0;
07126 struct ast_channel *oc0, *oc1;
07127 enum ast_bridge_result res;
07128 #ifdef PRI_2BCT
07129 int triedtopribridge = 0;
07130 q931_call *q931c0;
07131 q931_call *q931c1;
07132 #endif
07133
07134
07135
07136
07137
07138
07139 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07140 return AST_BRIDGE_FAILED_NOWARN;
07141
07142 ast_channel_lock(c0);
07143 while (ast_channel_trylock(c1)) {
07144 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07145 }
07146
07147 p0 = c0->tech_pvt;
07148 p1 = c1->tech_pvt;
07149
07150 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07151 ast_channel_unlock(c0);
07152 ast_channel_unlock(c1);
07153 return AST_BRIDGE_FAILED_NOWARN;
07154 }
07155
07156 oi0 = dahdi_get_index(c0, p0, 0);
07157 oi1 = dahdi_get_index(c1, p1, 0);
07158 if ((oi0 < 0) || (oi1 < 0)) {
07159 ast_channel_unlock(c0);
07160 ast_channel_unlock(c1);
07161 return AST_BRIDGE_FAILED;
07162 }
07163
07164 op0 = p0 = c0->tech_pvt;
07165 op1 = p1 = c1->tech_pvt;
07166 ofd0 = c0->fds[0];
07167 ofd1 = c1->fds[0];
07168 oc0 = p0->owner;
07169 oc1 = p1->owner;
07170
07171 if (ast_mutex_trylock(&p0->lock)) {
07172
07173 ast_channel_unlock(c0);
07174 ast_channel_unlock(c1);
07175 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07176 return AST_BRIDGE_RETRY;
07177 }
07178 if (ast_mutex_trylock(&p1->lock)) {
07179
07180 ast_mutex_unlock(&p0->lock);
07181 ast_channel_unlock(c0);
07182 ast_channel_unlock(c1);
07183 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07184 return AST_BRIDGE_RETRY;
07185 }
07186
07187 if ((p0->callwaiting && p0->callwaitingcallerid)
07188 || (p1->callwaiting && p1->callwaitingcallerid)) {
07189
07190
07191
07192
07193
07194
07195
07196
07197
07198 ast_mutex_unlock(&p0->lock);
07199 ast_mutex_unlock(&p1->lock);
07200 ast_channel_unlock(c0);
07201 ast_channel_unlock(c1);
07202 return AST_BRIDGE_FAILED_NOWARN;
07203 }
07204
07205 #if defined(HAVE_PRI)
07206 if ((dahdi_sig_pri_lib_handles(p0->sig)
07207 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07208 || (dahdi_sig_pri_lib_handles(p1->sig)
07209 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07210
07211
07212
07213
07214 ast_mutex_unlock(&p0->lock);
07215 ast_mutex_unlock(&p1->lock);
07216 ast_channel_unlock(c0);
07217 ast_channel_unlock(c1);
07218 return AST_BRIDGE_FAILED_NOWARN;
07219 }
07220 #endif
07221
07222 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07223 if (p0->owner && p1->owner) {
07224
07225 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07226 master = p0;
07227 slave = p1;
07228 inconf = 1;
07229 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07230 master = p1;
07231 slave = p0;
07232 inconf = 1;
07233 } else {
07234 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07235 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07236 p0->channel,
07237 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07238 p0->subs[SUB_REAL].inthreeway, p0->channel,
07239 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07240 p1->subs[SUB_REAL].inthreeway);
07241 }
07242 nothingok = 0;
07243 }
07244 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07245 if (p1->subs[SUB_THREEWAY].inthreeway) {
07246 master = p1;
07247 slave = p0;
07248 nothingok = 0;
07249 }
07250 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07251 if (p0->subs[SUB_THREEWAY].inthreeway) {
07252 master = p0;
07253 slave = p1;
07254 nothingok = 0;
07255 }
07256 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07257
07258
07259 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07260 master = p1;
07261 slave = p0;
07262 nothingok = 0;
07263 }
07264 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07265
07266 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07267 master = p0;
07268 slave = p1;
07269 nothingok = 0;
07270 }
07271 }
07272 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07273 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07274 if (master && slave) {
07275
07276
07277
07278 if ((oi1 == SUB_THREEWAY) &&
07279 p1->subs[SUB_THREEWAY].inthreeway &&
07280 p1->subs[SUB_REAL].owner &&
07281 p1->subs[SUB_REAL].inthreeway &&
07282 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07283 ast_debug(1,
07284 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07285 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07286 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07287 os1 = p1->subs[SUB_REAL].owner->_state;
07288 } else {
07289 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07290 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07291 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07292 }
07293 if ((oi0 == SUB_THREEWAY) &&
07294 p0->subs[SUB_THREEWAY].inthreeway &&
07295 p0->subs[SUB_REAL].owner &&
07296 p0->subs[SUB_REAL].inthreeway &&
07297 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07298 ast_debug(1,
07299 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07300 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07301 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07302 os0 = p0->subs[SUB_REAL].owner->_state;
07303 } else {
07304 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07305 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07306 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07307 }
07308 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07309 if (!p0->echocanbridged || !p1->echocanbridged) {
07310
07311 dahdi_disable_ec(p0);
07312 dahdi_disable_ec(p1);
07313 }
07314 }
07315 dahdi_link(slave, master);
07316 master->inconference = inconf;
07317 } else if (!nothingok)
07318 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07319
07320 update_conf(p0);
07321 update_conf(p1);
07322 t0 = p0->subs[SUB_REAL].inthreeway;
07323 t1 = p1->subs[SUB_REAL].inthreeway;
07324
07325 ast_mutex_unlock(&p0->lock);
07326 ast_mutex_unlock(&p1->lock);
07327
07328 ast_channel_unlock(c0);
07329 ast_channel_unlock(c1);
07330
07331
07332 if ((!master || !slave) && !nothingok) {
07333 dahdi_enable_ec(p0);
07334 dahdi_enable_ec(p1);
07335 return AST_BRIDGE_FAILED;
07336 }
07337
07338 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07339
07340 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07341 disable_dtmf_detect(op0);
07342
07343 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07344 disable_dtmf_detect(op1);
07345
07346 for (;;) {
07347 struct ast_channel *c0_priority[2] = {c0, c1};
07348 struct ast_channel *c1_priority[2] = {c1, c0};
07349
07350
07351
07352
07353 ast_channel_lock(c0);
07354 while (ast_channel_trylock(c1)) {
07355 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07356 }
07357
07358 p0 = c0->tech_pvt;
07359 p1 = c1->tech_pvt;
07360
07361 if (op0 == p0)
07362 i0 = dahdi_get_index(c0, p0, 1);
07363 if (op1 == p1)
07364 i1 = dahdi_get_index(c1, p1, 1);
07365
07366 ast_channel_unlock(c0);
07367 ast_channel_unlock(c1);
07368
07369 if (!timeoutms ||
07370 (op0 != p0) ||
07371 (op1 != p1) ||
07372 (ofd0 != c0->fds[0]) ||
07373 (ofd1 != c1->fds[0]) ||
07374 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07375 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07376 (oc0 != p0->owner) ||
07377 (oc1 != p1->owner) ||
07378 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07379 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07380 (oi0 != i0) ||
07381 (oi1 != i1)) {
07382 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07383 op0->channel, oi0, op1->channel, oi1);
07384 res = AST_BRIDGE_RETRY;
07385 goto return_from_bridge;
07386 }
07387
07388 #ifdef PRI_2BCT
07389 if (!triedtopribridge) {
07390 triedtopribridge = 1;
07391 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07392 ast_mutex_lock(&p0->pri->lock);
07393 switch (p0->sig) {
07394 case SIG_PRI_LIB_HANDLE_CASES:
07395 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07396 break;
07397 default:
07398 q931c0 = NULL;
07399 break;
07400 }
07401 switch (p1->sig) {
07402 case SIG_PRI_LIB_HANDLE_CASES:
07403 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07404 break;
07405 default:
07406 q931c1 = NULL;
07407 break;
07408 }
07409 if (q931c0 && q931c1) {
07410 pri_channel_bridge(q931c0, q931c1);
07411 }
07412 ast_mutex_unlock(&p0->pri->lock);
07413 }
07414 }
07415 #endif
07416
07417 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07418 if (!who) {
07419 ast_debug(1, "Ooh, empty read...\n");
07420 continue;
07421 }
07422 f = ast_read(who);
07423 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07424 *fo = f;
07425 *rc = who;
07426 res = AST_BRIDGE_COMPLETE;
07427 goto return_from_bridge;
07428 }
07429 if (f->frametype == AST_FRAME_DTMF) {
07430 if ((who == c0) && p0->pulsedial) {
07431 ast_write(c1, f);
07432 } else if ((who == c1) && p1->pulsedial) {
07433 ast_write(c0, f);
07434 } else {
07435 *fo = f;
07436 *rc = who;
07437 res = AST_BRIDGE_COMPLETE;
07438 goto return_from_bridge;
07439 }
07440 }
07441 ast_frfree(f);
07442
07443
07444 priority = !priority;
07445 }
07446
07447 return_from_bridge:
07448 if (op0 == p0)
07449 dahdi_enable_ec(p0);
07450
07451 if (op1 == p1)
07452 dahdi_enable_ec(p1);
07453
07454 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07455 enable_dtmf_detect(op0);
07456
07457 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07458 enable_dtmf_detect(op1);
07459
07460 dahdi_unlink(slave, master, 1);
07461
07462 return res;
07463 }
07464
07465 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07466 {
07467 struct dahdi_pvt *p = newchan->tech_pvt;
07468 int x;
07469
07470 ast_mutex_lock(&p->lock);
07471
07472 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07473 if (p->owner == oldchan) {
07474 p->owner = newchan;
07475 }
07476 for (x = 0; x < 3; x++) {
07477 if (p->subs[x].owner == oldchan) {
07478 if (!x) {
07479 dahdi_unlink(NULL, p, 0);
07480 }
07481 p->subs[x].owner = newchan;
07482 }
07483 }
07484 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07485 analog_fixup(oldchan, newchan, p->sig_pvt);
07486 #if defined(HAVE_PRI)
07487 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07488 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07489 #endif
07490 #if defined(HAVE_SS7)
07491 } else if (p->sig == SIG_SS7) {
07492 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07493 #endif
07494 }
07495 update_conf(p);
07496
07497 ast_mutex_unlock(&p->lock);
07498
07499 if (newchan->_state == AST_STATE_RINGING) {
07500 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07501 }
07502 return 0;
07503 }
07504
07505 static int dahdi_ring_phone(struct dahdi_pvt *p)
07506 {
07507 int x;
07508 int res;
07509
07510 x = 0;
07511 x = DAHDI_ONHOOK;
07512 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07513 do {
07514 x = DAHDI_RING;
07515 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07516 if (res) {
07517 switch (errno) {
07518 case EBUSY:
07519 case EINTR:
07520
07521 usleep(10000);
07522 continue;
07523 case EINPROGRESS:
07524 res = 0;
07525 break;
07526 default:
07527 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07528 res = 0;
07529 }
07530 }
07531 } while (res);
07532 return res;
07533 }
07534
07535 static void *analog_ss_thread(void *data);
07536
07537 static int attempt_transfer(struct dahdi_pvt *p)
07538 {
07539
07540
07541
07542 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07543
07544
07545 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07546 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07547 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07548 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07549 }
07550 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07551 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07552 }
07553 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07554 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07555 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07556 return -1;
07557 }
07558
07559 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07560 unalloc_sub(p, SUB_THREEWAY);
07561 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07562 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07563 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07564 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07565 }
07566 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07567 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07568 }
07569 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07570 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07571 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07572 return -1;
07573 }
07574
07575 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07576 ast_channel_unlock(p->subs[SUB_REAL].owner);
07577 unalloc_sub(p, SUB_THREEWAY);
07578
07579 return 1;
07580 } else {
07581 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07582 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07583 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07584 return -1;
07585 }
07586 return 0;
07587 }
07588
07589 static int check_for_conference(struct dahdi_pvt *p)
07590 {
07591 struct dahdi_confinfo ci;
07592
07593 if (p->master || (p->confno > -1))
07594 return 0;
07595 memset(&ci, 0, sizeof(ci));
07596 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07597 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07598 return 0;
07599 }
07600
07601
07602
07603 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07604 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07605 return 1;
07606 }
07607 return 0;
07608 }
07609
07610
07611
07612
07613
07614
07615 static int get_alarms(struct dahdi_pvt *p)
07616 {
07617 int res;
07618 struct dahdi_spaninfo zi;
07619 struct dahdi_params params;
07620
07621 memset(&zi, 0, sizeof(zi));
07622 zi.spanno = p->span;
07623
07624 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07625 if (zi.alarms != DAHDI_ALARM_NONE)
07626 return zi.alarms;
07627 } else {
07628 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07629 return 0;
07630 }
07631
07632
07633 memset(¶ms, 0, sizeof(params));
07634 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07635 return params.chan_alarms;
07636
07637 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07638
07639 return DAHDI_ALARM_NONE;
07640 }
07641
07642 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07643 {
07644 struct dahdi_pvt *p = ast->tech_pvt;
07645 struct ast_frame *f = *dest;
07646
07647 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07648 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07649 f->subclass.integer, f->subclass.integer, ast->name);
07650
07651 if (p->confirmanswer) {
07652 if (f->frametype == AST_FRAME_DTMF_END) {
07653 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07654
07655
07656 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07657 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07658
07659 p->confirmanswer = 0;
07660 } else {
07661 p->subs[idx].f.frametype = AST_FRAME_NULL;
07662 p->subs[idx].f.subclass.integer = 0;
07663 }
07664 *dest = &p->subs[idx].f;
07665 } else if (p->callwaitcas) {
07666 if (f->frametype == AST_FRAME_DTMF_END) {
07667 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07668 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07669 ast_free(p->cidspill);
07670 p->cidspill = NULL;
07671 send_cwcidspill(p);
07672 }
07673 p->callwaitcas = 0;
07674 }
07675 p->subs[idx].f.frametype = AST_FRAME_NULL;
07676 p->subs[idx].f.subclass.integer = 0;
07677 *dest = &p->subs[idx].f;
07678 } else if (f->subclass.integer == 'f') {
07679 if (f->frametype == AST_FRAME_DTMF_END) {
07680
07681 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07682
07683 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07684 struct dahdi_bufferinfo bi = {
07685 .txbufpolicy = p->faxbuf_policy,
07686 .bufsize = p->bufsize,
07687 .numbufs = p->faxbuf_no
07688 };
07689 int res;
07690
07691 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07692 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07693 } else {
07694 p->bufferoverrideinuse = 1;
07695 }
07696 }
07697 p->faxhandled = 1;
07698 if (p->dsp) {
07699 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07700 ast_dsp_set_features(p->dsp, p->dsp_features);
07701 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07702 }
07703 if (strcmp(ast->exten, "fax")) {
07704 const char *target_context = S_OR(ast->macrocontext, ast->context);
07705
07706
07707
07708
07709
07710 ast_mutex_unlock(&p->lock);
07711 ast_channel_unlock(ast);
07712 if (ast_exists_extension(ast, target_context, "fax", 1,
07713 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07714 ast_channel_lock(ast);
07715 ast_mutex_lock(&p->lock);
07716 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07717
07718 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07719 if (ast_async_goto(ast, target_context, "fax", 1))
07720 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07721 } else {
07722 ast_channel_lock(ast);
07723 ast_mutex_lock(&p->lock);
07724 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07725 }
07726 } else {
07727 ast_debug(1, "Already in a fax extension, not redirecting\n");
07728 }
07729 } else {
07730 ast_debug(1, "Fax already handled\n");
07731 }
07732 dahdi_confmute(p, 0);
07733 }
07734 p->subs[idx].f.frametype = AST_FRAME_NULL;
07735 p->subs[idx].f.subclass.integer = 0;
07736 *dest = &p->subs[idx].f;
07737 }
07738 }
07739
07740 static void handle_alarms(struct dahdi_pvt *p, int alms)
07741 {
07742 const char *alarm_str = alarm2str(alms);
07743
07744 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07745 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07746 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07747 "Alarm: %s\r\n"
07748 "Channel: %d\r\n",
07749 alarm_str, p->channel);
07750 }
07751
07752 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07753 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07754 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07755 "Alarm: %s\r\n"
07756 "Span: %d\r\n",
07757 alarm_str, p->span);
07758 }
07759 }
07760
07761 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07762 {
07763 int res, x;
07764 int idx, mysig;
07765 char *c;
07766 struct dahdi_pvt *p = ast->tech_pvt;
07767 pthread_t threadid;
07768 struct ast_channel *chan;
07769 struct ast_frame *f;
07770
07771 idx = dahdi_get_index(ast, p, 0);
07772 mysig = p->sig;
07773 if (p->outsigmod > -1)
07774 mysig = p->outsigmod;
07775 p->subs[idx].f.frametype = AST_FRAME_NULL;
07776 p->subs[idx].f.subclass.integer = 0;
07777 p->subs[idx].f.datalen = 0;
07778 p->subs[idx].f.samples = 0;
07779 p->subs[idx].f.mallocd = 0;
07780 p->subs[idx].f.offset = 0;
07781 p->subs[idx].f.src = "dahdi_handle_event";
07782 p->subs[idx].f.data.ptr = NULL;
07783 f = &p->subs[idx].f;
07784
07785 if (idx < 0)
07786 return &p->subs[idx].f;
07787 if (p->fake_event) {
07788 res = p->fake_event;
07789 p->fake_event = 0;
07790 } else
07791 res = dahdi_get_event(p->subs[idx].dfd);
07792
07793 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07794
07795 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07796 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07797 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07798 #if defined(HAVE_PRI)
07799 if (dahdi_sig_pri_lib_handles(p->sig)
07800 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07801 && p->pri
07802 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07803
07804 } else
07805 #endif
07806 {
07807
07808 dahdi_confmute(p, 0);
07809 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07810 p->subs[idx].f.subclass.integer = res & 0xff;
07811 dahdi_handle_dtmf(ast, idx, &f);
07812 }
07813 return f;
07814 }
07815
07816 if (res & DAHDI_EVENT_DTMFDOWN) {
07817 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07818 #if defined(HAVE_PRI)
07819 if (dahdi_sig_pri_lib_handles(p->sig)
07820 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07821 && p->pri
07822 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07823
07824 } else
07825 #endif
07826 {
07827
07828 dahdi_confmute(p, 1);
07829 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07830 p->subs[idx].f.subclass.integer = res & 0xff;
07831 dahdi_handle_dtmf(ast, idx, &f);
07832 }
07833 return &p->subs[idx].f;
07834 }
07835
07836 switch (res) {
07837 case DAHDI_EVENT_EC_DISABLED:
07838 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07839 p->echocanon = 0;
07840 break;
07841 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07842 case DAHDI_EVENT_TX_CED_DETECTED:
07843 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07844 break;
07845 case DAHDI_EVENT_RX_CED_DETECTED:
07846 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07847 break;
07848 case DAHDI_EVENT_EC_NLP_DISABLED:
07849 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07850 break;
07851 case DAHDI_EVENT_EC_NLP_ENABLED:
07852 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07853 break;
07854 #endif
07855 case DAHDI_EVENT_BITSCHANGED:
07856 #ifdef HAVE_OPENR2
07857 if (p->sig != SIG_MFCR2) {
07858 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07859 } else {
07860 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07861 openr2_chan_handle_cas(p->r2chan);
07862 }
07863 #else
07864 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07865 #endif
07866 case DAHDI_EVENT_PULSE_START:
07867
07868 if (!ast->pbx)
07869 tone_zone_play_tone(p->subs[idx].dfd, -1);
07870 break;
07871 case DAHDI_EVENT_DIALCOMPLETE:
07872 #ifdef HAVE_OPENR2
07873 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07874
07875
07876 break;
07877 }
07878 #endif
07879 if (p->inalarm) break;
07880 if ((p->radio || (p->oprmode < 0))) break;
07881 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07882 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07883 return NULL;
07884 }
07885 if (!x) {
07886 dahdi_enable_ec(p);
07887 if (p->echobreak) {
07888 dahdi_train_ec(p);
07889 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07890 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07891 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07892 p->echobreak = 0;
07893 } else {
07894 p->dialing = 0;
07895 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07896
07897 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07898 ast_setstate(ast, AST_STATE_UP);
07899 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07900 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07901 break;
07902 } else {
07903
07904 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07905 }
07906 }
07907 if (ast->_state == AST_STATE_DIALING) {
07908 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07909 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07910 } else if (p->confirmanswer || (!p->dialednone
07911 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07912 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07913 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07914 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07915 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07916 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07917 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07918 || (mysig == SIG_SF_FEATB)))) {
07919 ast_setstate(ast, AST_STATE_RINGING);
07920 } else if (!p->answeronpolarityswitch) {
07921 ast_setstate(ast, AST_STATE_UP);
07922 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07923 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07924
07925 p->polarity = POLARITY_REV;
07926 } else {
07927
07928 p->polarity = POLARITY_IDLE;
07929 }
07930 }
07931 }
07932 }
07933 break;
07934 case DAHDI_EVENT_ALARM:
07935 switch (p->sig) {
07936 #if defined(HAVE_PRI)
07937 case SIG_PRI_LIB_HANDLE_CASES:
07938 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07939 break;
07940 #endif
07941 #if defined(HAVE_SS7)
07942 case SIG_SS7:
07943 sig_ss7_set_alarm(p->sig_pvt, 1);
07944 break;
07945 #endif
07946 default:
07947 p->inalarm = 1;
07948 break;
07949 }
07950 res = get_alarms(p);
07951 handle_alarms(p, res);
07952 #ifdef HAVE_PRI
07953 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07954
07955 } else {
07956 break;
07957 }
07958 #endif
07959 #if defined(HAVE_SS7)
07960 if (p->sig == SIG_SS7)
07961 break;
07962 #endif
07963 #ifdef HAVE_OPENR2
07964 if (p->sig == SIG_MFCR2)
07965 break;
07966 #endif
07967 case DAHDI_EVENT_ONHOOK:
07968 if (p->radio) {
07969 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07970 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07971 break;
07972 }
07973 if (p->oprmode < 0)
07974 {
07975 if (p->oprmode != -1) break;
07976 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07977 {
07978
07979 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07980 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07981 save_conference(p->oprpeer);
07982 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07983 }
07984 break;
07985 }
07986 switch (p->sig) {
07987 case SIG_FXOLS:
07988 case SIG_FXOGS:
07989 case SIG_FXOKS:
07990
07991 if (idx == SUB_REAL) {
07992
07993 if (p->subs[SUB_CALLWAIT].owner) {
07994
07995 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07996 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07997 unalloc_sub(p, SUB_CALLWAIT);
07998 #if 0
07999 p->subs[idx].needanswer = 0;
08000 p->subs[idx].needringing = 0;
08001 #endif
08002 p->callwaitingrepeat = 0;
08003 p->cidcwexpire = 0;
08004 p->cid_suppress_expire = 0;
08005 p->owner = NULL;
08006
08007 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08008 p->dialing = 1;
08009 dahdi_ring_phone(p);
08010 } else if (p->subs[SUB_THREEWAY].owner) {
08011 unsigned int mssinceflash;
08012
08013
08014 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08015
08016 DLA_UNLOCK(&p->lock);
08017 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08018
08019
08020
08021 DLA_LOCK(&p->lock);
08022 if (p->owner != ast) {
08023 ast_log(LOG_WARNING, "This isn't good...\n");
08024 return NULL;
08025 }
08026 }
08027 if (!p->subs[SUB_THREEWAY].owner) {
08028 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08029 return NULL;
08030 }
08031 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08032 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08033 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08034
08035
08036 if (p->subs[SUB_THREEWAY].owner)
08037 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08038 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08039 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08040 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08041 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08042 if (p->transfer) {
08043
08044 p->subs[SUB_REAL].inthreeway = 0;
08045 p->subs[SUB_THREEWAY].inthreeway = 0;
08046
08047 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08048 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08049
08050 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08051 p->owner = NULL;
08052
08053 dahdi_ring_phone(p);
08054 } else {
08055 if ((res = attempt_transfer(p)) < 0) {
08056 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08057 if (p->subs[SUB_THREEWAY].owner)
08058 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08059 } else if (res) {
08060
08061 if (p->subs[SUB_THREEWAY].owner)
08062 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08063 break;
08064 }
08065 }
08066 } else {
08067 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08068 if (p->subs[SUB_THREEWAY].owner)
08069 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08070 }
08071 } else {
08072 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08073
08074 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08075 p->owner = NULL;
08076
08077 dahdi_ring_phone(p);
08078 }
08079 }
08080 } else {
08081 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08082 }
08083
08084 default:
08085 dahdi_disable_ec(p);
08086 return NULL;
08087 }
08088 break;
08089 case DAHDI_EVENT_RINGOFFHOOK:
08090 if (p->inalarm) break;
08091 if (p->oprmode < 0)
08092 {
08093 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08094 {
08095
08096 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08097 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08098 restore_conference(p->oprpeer);
08099 }
08100 break;
08101 }
08102 if (p->radio)
08103 {
08104 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08105 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08106 break;
08107 }
08108
08109
08110 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08111 c = strchr(p->dialdest, '/');
08112 if (c)
08113 c++;
08114 else
08115 c = p->dialdest;
08116 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08117 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08118 if (strlen(p->dop.dialstr) > 4) {
08119 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08120 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08121 p->echorest[sizeof(p->echorest) - 1] = '\0';
08122 p->echobreak = 1;
08123 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08124 } else
08125 p->echobreak = 0;
08126 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08127 int saveerr = errno;
08128
08129 x = DAHDI_ONHOOK;
08130 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08131 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08132 return NULL;
08133 }
08134 p->dialing = 1;
08135 return &p->subs[idx].f;
08136 }
08137 switch (p->sig) {
08138 case SIG_FXOLS:
08139 case SIG_FXOGS:
08140 case SIG_FXOKS:
08141 switch (ast->_state) {
08142 case AST_STATE_RINGING:
08143 dahdi_enable_ec(p);
08144 dahdi_train_ec(p);
08145 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08146 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08147
08148 p->subs[SUB_REAL].needringing = 0;
08149 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08150 ast_debug(1, "channel %d answered\n", p->channel);
08151
08152
08153 ast_free(p->cidspill);
08154 p->cidspill = NULL;
08155 restore_conference(p);
08156
08157 p->dialing = 0;
08158 p->callwaitcas = 0;
08159 if (p->confirmanswer) {
08160
08161 p->subs[idx].f.frametype = AST_FRAME_NULL;
08162 p->subs[idx].f.subclass.integer = 0;
08163 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08164
08165 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08166 if (res < 0) {
08167 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08168 p->dop.dialstr[0] = '\0';
08169 return NULL;
08170 } else {
08171 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08172 p->subs[idx].f.frametype = AST_FRAME_NULL;
08173 p->subs[idx].f.subclass.integer = 0;
08174 p->dialing = 1;
08175 }
08176 p->dop.dialstr[0] = '\0';
08177 ast_setstate(ast, AST_STATE_DIALING);
08178 } else
08179 ast_setstate(ast, AST_STATE_UP);
08180 return &p->subs[idx].f;
08181 case AST_STATE_DOWN:
08182 ast_setstate(ast, AST_STATE_RING);
08183 ast->rings = 1;
08184 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08185 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08186 ast_debug(1, "channel %d picked up\n", p->channel);
08187 return &p->subs[idx].f;
08188 case AST_STATE_UP:
08189
08190 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08191
08192 if (ast_bridged_channel(p->owner))
08193 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08194 p->subs[idx].needunhold = 1;
08195 break;
08196 case AST_STATE_RESERVED:
08197
08198 if (has_voicemail(p))
08199 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08200 else
08201 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08202 break;
08203 default:
08204 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08205 }
08206 break;
08207 case SIG_FXSLS:
08208 case SIG_FXSGS:
08209 case SIG_FXSKS:
08210 if (ast->_state == AST_STATE_RING) {
08211 p->ringt = p->ringt_base;
08212 }
08213
08214
08215
08216 ast_debug(1, "Setting IDLE polarity due "
08217 "to ring. Old polarity was %d\n",
08218 p->polarity);
08219 p->polarity = POLARITY_IDLE;
08220
08221
08222 case SIG_EM:
08223 case SIG_EM_E1:
08224 case SIG_EMWINK:
08225 case SIG_FEATD:
08226 case SIG_FEATDMF:
08227 case SIG_FEATDMF_TA:
08228 case SIG_E911:
08229 case SIG_FGC_CAMA:
08230 case SIG_FGC_CAMAMF:
08231 case SIG_FEATB:
08232 case SIG_SF:
08233 case SIG_SFWINK:
08234 case SIG_SF_FEATD:
08235 case SIG_SF_FEATDMF:
08236 case SIG_SF_FEATB:
08237 if (ast->_state == AST_STATE_PRERING)
08238 ast_setstate(ast, AST_STATE_RING);
08239 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08240 ast_debug(1, "Ring detected\n");
08241 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08242 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08243 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08244 ast_debug(1, "Line answered\n");
08245 if (p->confirmanswer) {
08246 p->subs[idx].f.frametype = AST_FRAME_NULL;
08247 p->subs[idx].f.subclass.integer = 0;
08248 } else {
08249 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08250 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08251 ast_setstate(ast, AST_STATE_UP);
08252 }
08253 } else if (ast->_state != AST_STATE_RING)
08254 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08255 break;
08256 default:
08257 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08258 }
08259 break;
08260 case DAHDI_EVENT_RINGBEGIN:
08261 switch (p->sig) {
08262 case SIG_FXSLS:
08263 case SIG_FXSGS:
08264 case SIG_FXSKS:
08265 if (ast->_state == AST_STATE_RING) {
08266 p->ringt = p->ringt_base;
08267 }
08268 break;
08269 }
08270 break;
08271 case DAHDI_EVENT_RINGERON:
08272 break;
08273 case DAHDI_EVENT_NOALARM:
08274 switch (p->sig) {
08275 #if defined(HAVE_PRI)
08276 case SIG_PRI_LIB_HANDLE_CASES:
08277 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08278 break;
08279 #endif
08280 #if defined(HAVE_SS7)
08281 case SIG_SS7:
08282 sig_ss7_set_alarm(p->sig_pvt, 0);
08283 break;
08284 #endif
08285 default:
08286 p->inalarm = 0;
08287 break;
08288 }
08289 handle_clear_alarms(p);
08290 break;
08291 case DAHDI_EVENT_WINKFLASH:
08292 if (p->inalarm) break;
08293 if (p->radio) break;
08294 if (p->oprmode < 0) break;
08295 if (p->oprmode > 1)
08296 {
08297 struct dahdi_params par;
08298
08299 memset(&par, 0, sizeof(par));
08300 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08301 {
08302 if (!par.rxisoffhook)
08303 {
08304
08305 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08306 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08307 save_conference(p);
08308 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08309 }
08310 }
08311 break;
08312 }
08313
08314 p->flashtime = ast_tvnow();
08315 switch (mysig) {
08316 case SIG_FXOLS:
08317 case SIG_FXOGS:
08318 case SIG_FXOKS:
08319 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08320 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08321
08322
08323 ast_free(p->cidspill);
08324 p->cidspill = NULL;
08325 restore_conference(p);
08326 p->callwaitcas = 0;
08327
08328 if (idx != SUB_REAL) {
08329 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08330 goto winkflashdone;
08331 }
08332
08333 if (p->subs[SUB_CALLWAIT].owner) {
08334
08335 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08336 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08337 p->owner = p->subs[SUB_REAL].owner;
08338 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08339 if (p->owner->_state == AST_STATE_RINGING) {
08340 ast_setstate(p->owner, AST_STATE_UP);
08341 p->subs[SUB_REAL].needanswer = 1;
08342 }
08343 p->callwaitingrepeat = 0;
08344 p->cidcwexpire = 0;
08345 p->cid_suppress_expire = 0;
08346
08347 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08348 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08349 S_OR(p->mohsuggest, NULL),
08350 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08351 }
08352 p->subs[SUB_CALLWAIT].needhold = 1;
08353 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08354 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08355 S_OR(p->mohsuggest, NULL),
08356 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08357 }
08358 p->subs[SUB_REAL].needunhold = 1;
08359 } else if (!p->subs[SUB_THREEWAY].owner) {
08360 if (!p->threewaycalling) {
08361
08362 p->subs[SUB_REAL].needflash = 1;
08363 goto winkflashdone;
08364 } else if (!check_for_conference(p)) {
08365 char cid_num[256];
08366 char cid_name[256];
08367
08368 cid_num[0] = 0;
08369 cid_name[0] = 0;
08370 if (p->dahditrcallerid && p->owner) {
08371 if (p->owner->caller.id.number.valid
08372 && p->owner->caller.id.number.str) {
08373 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08374 sizeof(cid_num));
08375 }
08376 if (p->owner->caller.id.name.valid
08377 && p->owner->caller.id.name.str) {
08378 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08379 sizeof(cid_name));
08380 }
08381 }
08382
08383
08384 if (!((ast->pbx) ||
08385 (ast->_state == AST_STATE_UP) ||
08386 (ast->_state == AST_STATE_RING))) {
08387 ast_debug(1, "Flash when call not up or ringing\n");
08388 goto winkflashdone;
08389 }
08390 if (alloc_sub(p, SUB_THREEWAY)) {
08391 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08392 goto winkflashdone;
08393 }
08394
08395 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08396 if (p->dahditrcallerid) {
08397 if (!p->origcid_num)
08398 p->origcid_num = ast_strdup(p->cid_num);
08399 if (!p->origcid_name)
08400 p->origcid_name = ast_strdup(p->cid_name);
08401 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08402 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08403 }
08404
08405 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08406
08407 dahdi_disable_ec(p);
08408 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08409 if (res)
08410 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08411 p->owner = chan;
08412 if (!chan) {
08413 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08414 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08415 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08416 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08417 dahdi_enable_ec(p);
08418 ast_hangup(chan);
08419 } else {
08420 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08421
08422
08423 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08424 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08425 S_OR(p->mohsuggest, NULL),
08426 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08427 }
08428 p->subs[SUB_THREEWAY].needhold = 1;
08429 }
08430 }
08431 } else {
08432
08433 if (p->subs[SUB_THREEWAY].inthreeway) {
08434
08435 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08436
08437 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08438
08439 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08440 p->owner = p->subs[SUB_REAL].owner;
08441 }
08442
08443 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08444 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08445 p->subs[SUB_REAL].inthreeway = 0;
08446 p->subs[SUB_THREEWAY].inthreeway = 0;
08447 } else {
08448
08449 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08450 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08451 int otherindex = SUB_THREEWAY;
08452
08453 ast_verb(3, "Building conference call with %s and %s\n",
08454 p->subs[SUB_THREEWAY].owner->name,
08455 p->subs[SUB_REAL].owner->name);
08456
08457 p->subs[SUB_THREEWAY].inthreeway = 1;
08458 p->subs[SUB_REAL].inthreeway = 1;
08459 if (ast->_state == AST_STATE_UP) {
08460 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08461 otherindex = SUB_REAL;
08462 }
08463 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08464 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08465 p->subs[otherindex].needunhold = 1;
08466 p->owner = p->subs[SUB_REAL].owner;
08467 } else {
08468 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08469 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08470 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08471 p->owner = p->subs[SUB_REAL].owner;
08472 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08473 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08474 p->subs[SUB_REAL].needunhold = 1;
08475 dahdi_enable_ec(p);
08476 }
08477 }
08478 }
08479 winkflashdone:
08480 update_conf(p);
08481 break;
08482 case SIG_EM:
08483 case SIG_EM_E1:
08484 case SIG_FEATD:
08485 case SIG_SF:
08486 case SIG_SFWINK:
08487 case SIG_SF_FEATD:
08488 case SIG_FXSLS:
08489 case SIG_FXSGS:
08490 if (p->dialing)
08491 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08492 else
08493 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08494 break;
08495 case SIG_FEATDMF_TA:
08496 switch (p->whichwink) {
08497 case 0:
08498 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08499 S_COR(p->owner->caller.ani.number.valid,
08500 p->owner->caller.ani.number.str, ""));
08501 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08502 p->owner->caller.ani2,
08503 S_COR(p->owner->caller.ani.number.valid,
08504 p->owner->caller.ani.number.str, ""));
08505 break;
08506 case 1:
08507 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08508 break;
08509 case 2:
08510 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08511 return NULL;
08512 }
08513 p->whichwink++;
08514
08515 case SIG_FEATDMF:
08516 case SIG_E911:
08517 case SIG_FGC_CAMAMF:
08518 case SIG_FGC_CAMA:
08519 case SIG_FEATB:
08520 case SIG_SF_FEATDMF:
08521 case SIG_SF_FEATB:
08522 case SIG_EMWINK:
08523
08524 if (!ast_strlen_zero(p->dop.dialstr)) {
08525 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08526 if (res < 0) {
08527 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08528 p->dop.dialstr[0] = '\0';
08529 return NULL;
08530 } else
08531 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08532 }
08533 p->dop.dialstr[0] = '\0';
08534 break;
08535 default:
08536 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08537 }
08538 break;
08539 case DAHDI_EVENT_HOOKCOMPLETE:
08540 if (p->inalarm) break;
08541 if ((p->radio || (p->oprmode < 0))) break;
08542 if (p->waitingfordt.tv_sec) break;
08543 switch (mysig) {
08544 case SIG_FXSLS:
08545 case SIG_FXSGS:
08546 case SIG_FXSKS:
08547 case SIG_EM:
08548 case SIG_EM_E1:
08549 case SIG_EMWINK:
08550 case SIG_FEATD:
08551 case SIG_SF:
08552 case SIG_SFWINK:
08553 case SIG_SF_FEATD:
08554 if (!ast_strlen_zero(p->dop.dialstr)) {
08555 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08556 if (res < 0) {
08557 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08558 p->dop.dialstr[0] = '\0';
08559 return NULL;
08560 } else
08561 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08562 }
08563 p->dop.dialstr[0] = '\0';
08564 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08565 break;
08566 case SIG_FEATDMF:
08567 case SIG_FEATDMF_TA:
08568 case SIG_E911:
08569 case SIG_FGC_CAMA:
08570 case SIG_FGC_CAMAMF:
08571 case SIG_FEATB:
08572 case SIG_SF_FEATDMF:
08573 case SIG_SF_FEATB:
08574 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08575 break;
08576 default:
08577 break;
08578 }
08579 break;
08580 case DAHDI_EVENT_POLARITY:
08581
08582
08583
08584
08585
08586
08587 if (p->polarity == POLARITY_IDLE) {
08588 p->polarity = POLARITY_REV;
08589 if (p->answeronpolarityswitch &&
08590 ((ast->_state == AST_STATE_DIALING) ||
08591 (ast->_state == AST_STATE_RINGING))) {
08592 ast_debug(1, "Answering on polarity switch!\n");
08593 ast_setstate(p->owner, AST_STATE_UP);
08594 if (p->hanguponpolarityswitch) {
08595 p->polaritydelaytv = ast_tvnow();
08596 }
08597 } else
08598 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08599 }
08600
08601
08602 if (p->hanguponpolarityswitch &&
08603 (p->polarityonanswerdelay > 0) &&
08604 (p->polarity == POLARITY_REV) &&
08605 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08606
08607 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) );
08608
08609 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08610 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08611 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08612 p->polarity = POLARITY_IDLE;
08613 } else
08614 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);
08615
08616 } else {
08617 p->polarity = POLARITY_IDLE;
08618 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08619 }
08620
08621 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) );
08622 break;
08623 default:
08624 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08625 }
08626 return &p->subs[idx].f;
08627 }
08628
08629 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08630 {
08631 int res;
08632 int idx;
08633 struct ast_frame *f;
08634 int usedindex = -1;
08635 struct dahdi_pvt *p = ast->tech_pvt;
08636
08637 idx = dahdi_get_index(ast, p, 1);
08638
08639 p->subs[idx].f.frametype = AST_FRAME_NULL;
08640 p->subs[idx].f.datalen = 0;
08641 p->subs[idx].f.samples = 0;
08642 p->subs[idx].f.mallocd = 0;
08643 p->subs[idx].f.offset = 0;
08644 p->subs[idx].f.subclass.integer = 0;
08645 p->subs[idx].f.delivery = ast_tv(0,0);
08646 p->subs[idx].f.src = "dahdi_exception";
08647 p->subs[idx].f.data.ptr = NULL;
08648
08649
08650 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08651
08652
08653
08654
08655
08656 if (p->fake_event) {
08657 res = p->fake_event;
08658 p->fake_event = 0;
08659 } else
08660 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08661
08662 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08663 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08664 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08665 p->owner = p->subs[SUB_REAL].owner;
08666 if (p->owner && ast_bridged_channel(p->owner))
08667 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08668 p->subs[SUB_REAL].needunhold = 1;
08669 }
08670 switch (res) {
08671 case DAHDI_EVENT_ONHOOK:
08672 dahdi_disable_ec(p);
08673 if (p->owner) {
08674 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08675 dahdi_ring_phone(p);
08676 p->callwaitingrepeat = 0;
08677 p->cidcwexpire = 0;
08678 p->cid_suppress_expire = 0;
08679 } else
08680 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08681 update_conf(p);
08682 break;
08683 case DAHDI_EVENT_RINGOFFHOOK:
08684 dahdi_enable_ec(p);
08685 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08686 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08687 p->subs[SUB_REAL].needanswer = 1;
08688 p->dialing = 0;
08689 }
08690 break;
08691 case DAHDI_EVENT_HOOKCOMPLETE:
08692 case DAHDI_EVENT_RINGERON:
08693 case DAHDI_EVENT_RINGEROFF:
08694
08695 break;
08696 case DAHDI_EVENT_WINKFLASH:
08697 p->flashtime = ast_tvnow();
08698 if (p->owner) {
08699 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08700 if (p->owner->_state != AST_STATE_UP) {
08701
08702 usedindex = dahdi_get_index(p->owner, p, 0);
08703 if (usedindex > -1) {
08704 p->subs[usedindex].needanswer = 1;
08705 }
08706 ast_setstate(p->owner, AST_STATE_UP);
08707 }
08708 p->callwaitingrepeat = 0;
08709 p->cidcwexpire = 0;
08710 p->cid_suppress_expire = 0;
08711 if (ast_bridged_channel(p->owner))
08712 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08713 p->subs[SUB_REAL].needunhold = 1;
08714 } else
08715 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08716 update_conf(p);
08717 break;
08718 default:
08719 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08720 }
08721 f = &p->subs[idx].f;
08722 return f;
08723 }
08724 if (!(p->radio || (p->oprmode < 0)))
08725 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08726
08727 if (ast != p->owner) {
08728 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08729 f = &p->subs[idx].f;
08730 return f;
08731 }
08732 f = dahdi_handle_event(ast);
08733
08734
08735 if (f == NULL) {
08736 ast_set_hangupsource(ast, ast->name, 0);
08737 }
08738
08739 return f;
08740 }
08741
08742 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08743 {
08744 struct dahdi_pvt *p = ast->tech_pvt;
08745 struct ast_frame *f;
08746 ast_mutex_lock(&p->lock);
08747 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08748 struct analog_pvt *analog_p = p->sig_pvt;
08749 f = analog_exception(analog_p, ast);
08750 } else {
08751 f = __dahdi_exception(ast);
08752 }
08753 ast_mutex_unlock(&p->lock);
08754 return f;
08755 }
08756
08757 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08758 {
08759 struct dahdi_pvt *p;
08760 int res;
08761 int idx;
08762 void *readbuf;
08763 struct ast_frame *f;
08764
08765
08766
08767
08768
08769
08770 p = ast->tech_pvt;
08771 while (ast_mutex_trylock(&p->lock)) {
08772 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08773
08774
08775
08776
08777
08778
08779 p = ast->tech_pvt;
08780 }
08781
08782 idx = dahdi_get_index(ast, p, 0);
08783
08784
08785 if (idx < 0) {
08786 ast_log(LOG_WARNING, "We don't exist?\n");
08787 ast_mutex_unlock(&p->lock);
08788 return NULL;
08789 }
08790
08791 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08792 ast_mutex_unlock(&p->lock);
08793 return NULL;
08794 }
08795
08796 p->subs[idx].f.frametype = AST_FRAME_NULL;
08797 p->subs[idx].f.datalen = 0;
08798 p->subs[idx].f.samples = 0;
08799 p->subs[idx].f.mallocd = 0;
08800 p->subs[idx].f.offset = 0;
08801 p->subs[idx].f.subclass.integer = 0;
08802 p->subs[idx].f.delivery = ast_tv(0,0);
08803 p->subs[idx].f.src = "dahdi_read";
08804 p->subs[idx].f.data.ptr = NULL;
08805
08806
08807 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08808 {
08809 struct dahdi_params ps;
08810
08811 memset(&ps, 0, sizeof(ps));
08812 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08813 ast_mutex_unlock(&p->lock);
08814 return NULL;
08815 }
08816 p->firstradio = 1;
08817 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08818 if (ps.rxisoffhook)
08819 {
08820 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08821 }
08822 else
08823 {
08824 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08825 }
08826 ast_mutex_unlock(&p->lock);
08827 return &p->subs[idx].f;
08828 }
08829 if (p->ringt > 0) {
08830 if (!(--p->ringt)) {
08831 ast_mutex_unlock(&p->lock);
08832 return NULL;
08833 }
08834 }
08835
08836 #ifdef HAVE_OPENR2
08837 if (p->mfcr2) {
08838 openr2_chan_process_event(p->r2chan);
08839 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08840 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08841
08842
08843 if (p->mfcr2_call_accepted &&
08844 !p->mfcr2_progress &&
08845 ast->_state == AST_STATE_RINGING) {
08846 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08847 ast_queue_frame(p->owner, &f);
08848 p->mfcr2_progress = 1;
08849 }
08850 }
08851 }
08852 #endif
08853
08854 if (p->subs[idx].needringing) {
08855
08856 p->subs[idx].needringing = 0;
08857 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08858 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08859 ast_setstate(ast, AST_STATE_RINGING);
08860 ast_mutex_unlock(&p->lock);
08861 return &p->subs[idx].f;
08862 }
08863
08864 if (p->subs[idx].needbusy) {
08865
08866 p->subs[idx].needbusy = 0;
08867 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08868 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08869 ast_mutex_unlock(&p->lock);
08870 return &p->subs[idx].f;
08871 }
08872
08873 if (p->subs[idx].needcongestion) {
08874
08875 p->subs[idx].needcongestion = 0;
08876 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08877 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08878 ast_mutex_unlock(&p->lock);
08879 return &p->subs[idx].f;
08880 }
08881
08882 if (p->subs[idx].needanswer) {
08883
08884 p->subs[idx].needanswer = 0;
08885 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08886 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08887 ast_mutex_unlock(&p->lock);
08888 return &p->subs[idx].f;
08889 }
08890 #ifdef HAVE_OPENR2
08891 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08892
08893
08894
08895
08896 ast_mutex_unlock(&p->lock);
08897 return &ast_null_frame;
08898 }
08899 #endif
08900
08901 if (p->subs[idx].needflash) {
08902
08903 p->subs[idx].needflash = 0;
08904 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08905 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08906 ast_mutex_unlock(&p->lock);
08907 return &p->subs[idx].f;
08908 }
08909
08910 if (p->subs[idx].needhold) {
08911
08912 p->subs[idx].needhold = 0;
08913 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08914 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08915 ast_mutex_unlock(&p->lock);
08916 ast_debug(1, "Sending hold on '%s'\n", ast->name);
08917 return &p->subs[idx].f;
08918 }
08919
08920 if (p->subs[idx].needunhold) {
08921
08922 p->subs[idx].needunhold = 0;
08923 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08924 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08925 ast_mutex_unlock(&p->lock);
08926 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08927 return &p->subs[idx].f;
08928 }
08929
08930
08931
08932
08933
08934 if (p->fake_event && p->owner == ast) {
08935 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08936 struct analog_pvt *analog_p = p->sig_pvt;
08937
08938 f = analog_exception(analog_p, ast);
08939 } else {
08940 f = __dahdi_exception(ast);
08941 }
08942 ast_mutex_unlock(&p->lock);
08943 return f;
08944 }
08945
08946 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08947 if (!p->subs[idx].linear) {
08948 p->subs[idx].linear = 1;
08949 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08950 if (res)
08951 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08952 }
08953 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08954 (ast->rawreadformat == AST_FORMAT_ALAW)) {
08955 if (p->subs[idx].linear) {
08956 p->subs[idx].linear = 0;
08957 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08958 if (res)
08959 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08960 }
08961 } else {
08962 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08963 ast_mutex_unlock(&p->lock);
08964 return NULL;
08965 }
08966 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08967 CHECK_BLOCKING(ast);
08968 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08969 ast_clear_flag(ast, AST_FLAG_BLOCKING);
08970
08971 if (res < 0) {
08972 f = NULL;
08973 if (res == -1) {
08974 if (errno == EAGAIN) {
08975
08976 ast_mutex_unlock(&p->lock);
08977 return &p->subs[idx].f;
08978 } else if (errno == ELAST) {
08979 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08980 struct analog_pvt *analog_p = p->sig_pvt;
08981 f = analog_exception(analog_p, ast);
08982 } else {
08983 f = __dahdi_exception(ast);
08984 }
08985 } else
08986 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08987 }
08988 ast_mutex_unlock(&p->lock);
08989 return f;
08990 }
08991 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08992 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08993 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08994 struct analog_pvt *analog_p = p->sig_pvt;
08995 f = analog_exception(analog_p, ast);
08996 } else {
08997 f = __dahdi_exception(ast);
08998 }
08999 ast_mutex_unlock(&p->lock);
09000 return f;
09001 }
09002 if (p->tdd) {
09003 int c;
09004
09005 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09006 if (c < 0) {
09007 ast_debug(1,"tdd_feed failed\n");
09008 ast_mutex_unlock(&p->lock);
09009 return NULL;
09010 }
09011 if (c) {
09012 p->subs[idx].f.subclass.integer = 0;
09013 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09014 p->subs[idx].f.mallocd = 0;
09015 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09016 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09017 p->subs[idx].f.datalen = 1;
09018 *((char *) p->subs[idx].f.data.ptr) = c;
09019 ast_mutex_unlock(&p->lock);
09020 return &p->subs[idx].f;
09021 }
09022 }
09023 if (idx == SUB_REAL) {
09024
09025 if (p->cidcwexpire) {
09026 if (!--p->cidcwexpire) {
09027
09028 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09029 restore_conference(p);
09030 }
09031 }
09032 if (p->cid_suppress_expire) {
09033 --p->cid_suppress_expire;
09034 }
09035 if (p->callwaitingrepeat) {
09036 if (!--p->callwaitingrepeat) {
09037
09038 ++p->callwaitrings;
09039 dahdi_callwait(ast);
09040 }
09041 }
09042 }
09043 if (p->subs[idx].linear) {
09044 p->subs[idx].f.datalen = READ_SIZE * 2;
09045 } else
09046 p->subs[idx].f.datalen = READ_SIZE;
09047
09048
09049 if ((p->owner == ast) && p->cidspill) {
09050 send_callerid(p);
09051 }
09052
09053 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09054 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09055 p->subs[idx].f.samples = READ_SIZE;
09056 p->subs[idx].f.mallocd = 0;
09057 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09058 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09059 #if 0
09060 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09061 #endif
09062 if (p->dialing || p->radio ||
09063 (idx && (ast->_state != AST_STATE_UP)) ||
09064 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09065 ) {
09066
09067
09068 p->subs[idx].f.frametype = AST_FRAME_NULL;
09069 p->subs[idx].f.subclass.integer = 0;
09070 p->subs[idx].f.samples = 0;
09071 p->subs[idx].f.mallocd = 0;
09072 p->subs[idx].f.offset = 0;
09073 p->subs[idx].f.data.ptr = NULL;
09074 p->subs[idx].f.datalen= 0;
09075 }
09076 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09077
09078 int mute;
09079
09080 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09081
09082
09083 mute = ast_dsp_was_muted(p->dsp);
09084 if (p->muting != mute) {
09085 p->muting = mute;
09086 dahdi_confmute(p, mute);
09087 }
09088
09089 if (f) {
09090 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09091 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09092
09093
09094 f = NULL;
09095 }
09096 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09097 || f->frametype == AST_FRAME_DTMF_END) {
09098 #ifdef HAVE_PRI
09099 if (dahdi_sig_pri_lib_handles(p->sig)
09100 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09101 && p->pri
09102 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09103 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09104
09105 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09106 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09107 f->subclass.integer, f->subclass.integer, ast->name);
09108
09109 f->frametype = AST_FRAME_NULL;
09110 f->subclass.integer = 0;
09111 }
09112 #endif
09113
09114 p->pulsedial = 0;
09115 } else if (p->waitingfordt.tv_sec) {
09116 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09117 p->waitingfordt.tv_sec = 0;
09118 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09119 f=NULL;
09120 } else if (f->frametype == AST_FRAME_VOICE) {
09121 f->frametype = AST_FRAME_NULL;
09122 f->subclass.integer = 0;
09123 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) {
09124 p->waitingfordt.tv_sec = 0;
09125 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09126 ast_dsp_set_features(p->dsp, p->dsp_features);
09127 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09128 if (!ast_strlen_zero(p->dop.dialstr)) {
09129 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09130 if (res < 0) {
09131 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09132 p->dop.dialstr[0] = '\0';
09133 ast_mutex_unlock(&p->lock);
09134 return NULL;
09135 } else {
09136 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09137 p->dialing = 1;
09138 p->dop.dialstr[0] = '\0';
09139 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09140 ast_setstate(ast, AST_STATE_DIALING);
09141 }
09142 }
09143 }
09144 }
09145 }
09146 }
09147 } else
09148 f = &p->subs[idx].f;
09149
09150 if (f) {
09151 switch (f->frametype) {
09152 case AST_FRAME_DTMF_BEGIN:
09153 case AST_FRAME_DTMF_END:
09154 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09155 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09156 } else {
09157 dahdi_handle_dtmf(ast, idx, &f);
09158 }
09159 break;
09160 case AST_FRAME_VOICE:
09161 if (p->cidspill || p->cid_suppress_expire) {
09162
09163 p->subs[idx].f.frametype = AST_FRAME_NULL;
09164 p->subs[idx].f.subclass.integer = 0;
09165 p->subs[idx].f.samples = 0;
09166 p->subs[idx].f.mallocd = 0;
09167 p->subs[idx].f.offset = 0;
09168 p->subs[idx].f.data.ptr = NULL;
09169 p->subs[idx].f.datalen= 0;
09170 }
09171 break;
09172 default:
09173 break;
09174 }
09175 }
09176
09177 ast_mutex_unlock(&p->lock);
09178 return f;
09179 }
09180
09181 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09182 {
09183 int sent=0;
09184 int size;
09185 int res;
09186 int fd;
09187 fd = p->subs[idx].dfd;
09188 while (len) {
09189 size = len;
09190 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09191 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09192 res = write(fd, buf, size);
09193 if (res != size) {
09194 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09195 return sent;
09196 }
09197 len -= size;
09198 buf += size;
09199 }
09200 return sent;
09201 }
09202
09203 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09204 {
09205 struct dahdi_pvt *p = ast->tech_pvt;
09206 int res;
09207 int idx;
09208 idx = dahdi_get_index(ast, p, 0);
09209 if (idx < 0) {
09210 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09211 return -1;
09212 }
09213
09214
09215 if (frame->frametype != AST_FRAME_VOICE) {
09216 if (frame->frametype != AST_FRAME_IMAGE)
09217 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09218 return 0;
09219 }
09220 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09221 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09222 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09223 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09224 return -1;
09225 }
09226 if (p->dialing) {
09227 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09228 return 0;
09229 }
09230 if (!p->owner) {
09231 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09232 return 0;
09233 }
09234 if (p->cidspill) {
09235 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09236 ast->name);
09237 return 0;
09238 }
09239
09240 if (!frame->data.ptr || !frame->datalen)
09241 return 0;
09242
09243 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09244 if (!p->subs[idx].linear) {
09245 p->subs[idx].linear = 1;
09246 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09247 if (res)
09248 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09249 }
09250 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09251 } else {
09252
09253 if (p->subs[idx].linear) {
09254 p->subs[idx].linear = 0;
09255 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09256 if (res)
09257 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09258 }
09259 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09260 }
09261 if (res < 0) {
09262 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09263 return -1;
09264 }
09265 return 0;
09266 }
09267
09268 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09269 {
09270 struct dahdi_pvt *p = chan->tech_pvt;
09271 int res=-1;
09272 int idx;
09273 int func = DAHDI_FLASH;
09274
09275 ast_mutex_lock(&p->lock);
09276 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09277 switch (p->sig) {
09278 #if defined(HAVE_PRI)
09279 case SIG_PRI_LIB_HANDLE_CASES:
09280 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09281 ast_mutex_unlock(&p->lock);
09282 return res;
09283 #endif
09284 #if defined(HAVE_SS7)
09285 case SIG_SS7:
09286 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09287 ast_mutex_unlock(&p->lock);
09288 return res;
09289 #endif
09290 default:
09291 break;
09292 }
09293 #ifdef HAVE_OPENR2
09294 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09295 ast_mutex_unlock(&p->lock);
09296
09297
09298 return 0;
09299 }
09300 #endif
09301 idx = dahdi_get_index(chan, p, 0);
09302 if (idx == SUB_REAL) {
09303 switch (condition) {
09304 case AST_CONTROL_BUSY:
09305 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09306 break;
09307 case AST_CONTROL_RINGING:
09308 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09309
09310 if (chan->_state != AST_STATE_UP) {
09311 if ((chan->_state != AST_STATE_RING) ||
09312 ((p->sig != SIG_FXSKS) &&
09313 (p->sig != SIG_FXSLS) &&
09314 (p->sig != SIG_FXSGS)))
09315 ast_setstate(chan, AST_STATE_RINGING);
09316 }
09317 break;
09318 case AST_CONTROL_PROCEEDING:
09319 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09320
09321 res = 0;
09322 break;
09323 case AST_CONTROL_PROGRESS:
09324 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09325
09326 res = 0;
09327 break;
09328 case AST_CONTROL_CONGESTION:
09329
09330 switch (chan->hangupcause) {
09331 case AST_CAUSE_USER_BUSY:
09332 case AST_CAUSE_NORMAL_CLEARING:
09333 case 0:
09334
09335 chan->hangupcause = AST_CAUSE_CONGESTION;
09336 break;
09337 default:
09338 break;
09339 }
09340 break;
09341 case AST_CONTROL_HOLD:
09342 ast_moh_start(chan, data, p->mohinterpret);
09343 break;
09344 case AST_CONTROL_UNHOLD:
09345 ast_moh_stop(chan);
09346 break;
09347 case AST_CONTROL_RADIO_KEY:
09348 if (p->radio)
09349 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09350 res = 0;
09351 break;
09352 case AST_CONTROL_RADIO_UNKEY:
09353 if (p->radio)
09354 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09355 res = 0;
09356 break;
09357 case AST_CONTROL_FLASH:
09358
09359 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09360
09361 p->dop.dialstr[0] = '\0';
09362 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09363 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09364 chan->name, strerror(errno));
09365 } else
09366 res = 0;
09367 } else
09368 res = 0;
09369 break;
09370 case AST_CONTROL_SRCUPDATE:
09371 res = 0;
09372 break;
09373 case -1:
09374 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09375 break;
09376 }
09377 } else {
09378 res = 0;
09379 }
09380 ast_mutex_unlock(&p->lock);
09381 return res;
09382 }
09383
09384 #if defined(HAVE_PRI)
09385 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09386 #else
09387 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09388 #endif
09389 {
09390 struct ast_str *chan_name;
09391 int x, y;
09392
09393
09394 if (!(chan_name = ast_str_create(32))) {
09395 return NULL;
09396 }
09397 if (i->channel == CHAN_PSEUDO) {
09398 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09399 #if defined(HAVE_PRI)
09400 } else if (i->pri) {
09401 ast_mutex_lock(&i->pri->lock);
09402 y = ++i->pri->new_chan_seq;
09403 if (is_outgoing) {
09404 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09405 address[0] = '\0';
09406 } else if (ast_strlen_zero(i->cid_subaddr)) {
09407
09408 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09409 } else {
09410
09411 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09412 i->cid_subaddr, y);
09413 }
09414 ast_mutex_unlock(&i->pri->lock);
09415 #endif
09416 } else {
09417 y = 1;
09418 do {
09419 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09420 for (x = 0; x < 3; ++x) {
09421 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09422 i->subs[x].owner->name + 6)) {
09423 break;
09424 }
09425 }
09426 ++y;
09427 } while (x < 3);
09428 }
09429 return chan_name;
09430 }
09431
09432 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09433 {
09434 struct ast_channel *tmp;
09435 format_t deflaw;
09436 int x;
09437 int features;
09438 struct ast_str *chan_name;
09439 struct ast_variable *v;
09440 char *dashptr;
09441 char device_name[AST_CHANNEL_NAME];
09442
09443 if (i->subs[idx].owner) {
09444 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09445 return NULL;
09446 }
09447
09448 #if defined(HAVE_PRI)
09449
09450
09451
09452
09453 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09454 #else
09455 chan_name = create_channel_name(i);
09456 #endif
09457 if (!chan_name) {
09458 return NULL;
09459 }
09460
09461 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));
09462 ast_free(chan_name);
09463 if (!tmp)
09464 return NULL;
09465 tmp->tech = &dahdi_tech;
09466 #if defined(HAVE_PRI)
09467 if (i->pri) {
09468 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09469 }
09470 #endif
09471 ast_channel_cc_params_init(tmp, i->cc_params);
09472 if (law) {
09473 i->law = law;
09474 if (law == DAHDI_LAW_ALAW) {
09475 deflaw = AST_FORMAT_ALAW;
09476 } else {
09477 deflaw = AST_FORMAT_ULAW;
09478 }
09479 } else {
09480 switch (i->sig) {
09481 case SIG_PRI_LIB_HANDLE_CASES:
09482
09483 i->law = (i->law_default == DAHDI_LAW_ALAW)
09484 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09485 break;
09486 default:
09487 i->law = i->law_default;
09488 break;
09489 }
09490 if (i->law_default == DAHDI_LAW_ALAW) {
09491 deflaw = AST_FORMAT_ALAW;
09492 } else {
09493 deflaw = AST_FORMAT_ULAW;
09494 }
09495 }
09496 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09497 tmp->nativeformats = deflaw;
09498
09499 tmp->rawreadformat = deflaw;
09500 tmp->readformat = deflaw;
09501 tmp->rawwriteformat = deflaw;
09502 tmp->writeformat = deflaw;
09503 i->subs[idx].linear = 0;
09504 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09505 features = 0;
09506 if (idx == SUB_REAL) {
09507 if (i->busydetect && CANBUSYDETECT(i))
09508 features |= DSP_FEATURE_BUSY_DETECT;
09509 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09510 features |= DSP_FEATURE_CALL_PROGRESS;
09511 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09512 features |= DSP_FEATURE_WAITDIALTONE;
09513 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09514 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09515 features |= DSP_FEATURE_FAX_DETECT;
09516 }
09517 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09518 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09519 i->hardwaredtmf = 0;
09520 features |= DSP_FEATURE_DIGIT_DETECT;
09521 } else if (NEED_MFDETECT(i)) {
09522 i->hardwaredtmf = 1;
09523 features |= DSP_FEATURE_DIGIT_DETECT;
09524 }
09525 }
09526 if (features) {
09527 if (i->dsp) {
09528 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09529 } else {
09530 if (i->channel != CHAN_PSEUDO)
09531 i->dsp = ast_dsp_new();
09532 else
09533 i->dsp = NULL;
09534 if (i->dsp) {
09535 i->dsp_features = features;
09536 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09537
09538 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09539
09540
09541 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09542 features = 0;
09543 }
09544 #endif
09545 ast_dsp_set_features(i->dsp, features);
09546 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09547 if (!ast_strlen_zero(progzone))
09548 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09549 if (i->busydetect && CANBUSYDETECT(i)) {
09550 ast_dsp_set_busy_count(i->dsp, i->busycount);
09551 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09552 }
09553 }
09554 }
09555 }
09556
09557 if (state == AST_STATE_RING)
09558 tmp->rings = 1;
09559 tmp->tech_pvt = i;
09560 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09561
09562 tmp->callgroup = i->callgroup;
09563 tmp->pickupgroup = i->pickupgroup;
09564 }
09565 if (!ast_strlen_zero(i->parkinglot))
09566 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09567 if (!ast_strlen_zero(i->language))
09568 ast_string_field_set(tmp, language, i->language);
09569 if (!i->owner)
09570 i->owner = tmp;
09571 if (!ast_strlen_zero(i->accountcode))
09572 ast_string_field_set(tmp, accountcode, i->accountcode);
09573 if (i->amaflags)
09574 tmp->amaflags = i->amaflags;
09575 i->subs[idx].owner = tmp;
09576 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09577 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09578 ast_string_field_set(tmp, call_forward, i->call_forward);
09579 }
09580
09581 if (!i->adsi)
09582 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09583 if (!ast_strlen_zero(i->exten))
09584 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09585 if (!ast_strlen_zero(i->rdnis)) {
09586 tmp->redirecting.from.number.valid = 1;
09587 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09588 }
09589 if (!ast_strlen_zero(i->dnid)) {
09590 tmp->dialed.number.str = ast_strdup(i->dnid);
09591 }
09592
09593
09594
09595 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09596 if (!ast_strlen_zero(i->cid_ani)) {
09597 tmp->caller.ani.number.valid = 1;
09598 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09599 } else if (!ast_strlen_zero(i->cid_num)) {
09600 tmp->caller.ani.number.valid = 1;
09601 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09602 }
09603 #else
09604 if (!ast_strlen_zero(i->cid_num)) {
09605 tmp->caller.ani.number.valid = 1;
09606 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09607 }
09608 #endif
09609 tmp->caller.id.name.presentation = i->callingpres;
09610 tmp->caller.id.number.presentation = i->callingpres;
09611 tmp->caller.id.number.plan = i->cid_ton;
09612 tmp->caller.ani2 = i->cid_ani2;
09613 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09614
09615 i->fake_event = 0;
09616
09617 dahdi_confmute(i, 0);
09618 i->muting = 0;
09619
09620 ast_jb_configure(tmp, &global_jbconf);
09621
09622
09623 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09624 dashptr = strrchr(device_name, '-');
09625 if (dashptr) {
09626 *dashptr = '\0';
09627 }
09628 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09629
09630 for (v = i->vars ; v ; v = v->next)
09631 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09632
09633 ast_module_ref(ast_module_info->self);
09634
09635 dahdi_ami_channel_event(i, tmp);
09636 if (startpbx) {
09637 #ifdef HAVE_OPENR2
09638 if (i->mfcr2call) {
09639 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09640 }
09641 #endif
09642 if (ast_pbx_start(tmp)) {
09643 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09644 ast_hangup(tmp);
09645 return NULL;
09646 }
09647 }
09648 return tmp;
09649 }
09650
09651
09652 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09653 {
09654 char c;
09655
09656 *str = 0;
09657 for (;;)
09658 {
09659
09660 c = ast_waitfordigit(chan, ms);
09661
09662 if (c < 1)
09663 return c;
09664 *str++ = c;
09665 *str = 0;
09666 if (strchr(term, c))
09667 return 1;
09668 }
09669 }
09670
09671 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09672 {
09673 int j;
09674 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09675 for (;;)
09676 {
09677
09678 j = DAHDI_IOMUX_SIGEVENT;
09679
09680 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09681
09682 if (j & DAHDI_IOMUX_SIGEVENT) break;
09683 }
09684
09685 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09686 return 0;
09687 }
09688
09689
09690
09691
09692
09693
09694
09695
09696
09697
09698 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09699 {
09700 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09701 return analog_dnd(dahdichan->sig_pvt, flag);
09702 }
09703
09704 if (flag == -1) {
09705 return dahdichan->dnd;
09706 }
09707
09708
09709 dahdichan->dnd = flag;
09710 ast_verb(3, "%s DND on channel %d\n",
09711 flag? "Enabled" : "Disabled",
09712 dahdichan->channel);
09713 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09714 "Channel: DAHDI/%d\r\n"
09715 "Status: %s\r\n", dahdichan->channel,
09716 flag? "enabled" : "disabled");
09717
09718 return 0;
09719 }
09720
09721 static int canmatch_featurecode(const char *exten)
09722 {
09723 int extlen = strlen(exten);
09724 const char *pickup_ext;
09725 if (!extlen) {
09726 return 1;
09727 }
09728 pickup_ext = ast_pickup_ext();
09729 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09730 return 1;
09731 }
09732
09733 if (exten[0] == '*' && extlen < 3) {
09734 if (extlen == 1) {
09735 return 1;
09736 }
09737
09738 switch (exten[1]) {
09739 case '6':
09740 case '7':
09741 case '8':
09742 return 1;
09743 }
09744 }
09745 return 0;
09746 }
09747
09748 static void *analog_ss_thread(void *data)
09749 {
09750 struct ast_channel *chan = data;
09751 struct dahdi_pvt *p = chan->tech_pvt;
09752 char exten[AST_MAX_EXTENSION] = "";
09753 char exten2[AST_MAX_EXTENSION] = "";
09754 unsigned char buf[256];
09755 char dtmfcid[300];
09756 char dtmfbuf[300];
09757 struct callerid_state *cs = NULL;
09758 char *name = NULL, *number = NULL;
09759 int distMatches;
09760 int curRingData[3];
09761 int receivedRingT;
09762 int counter1;
09763 int counter;
09764 int samples = 0;
09765 struct ast_smdi_md_message *smdi_msg = NULL;
09766 int flags = 0;
09767 int i;
09768 int timeout;
09769 int getforward = 0;
09770 char *s1, *s2;
09771 int len = 0;
09772 int res;
09773 int idx;
09774
09775 ast_mutex_lock(&ss_thread_lock);
09776 ss_thread_count++;
09777 ast_mutex_unlock(&ss_thread_lock);
09778
09779
09780
09781 if (!p) {
09782 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09783 ast_hangup(chan);
09784 goto quit;
09785 }
09786 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09787 idx = dahdi_get_index(chan, p, 1);
09788 if (idx < 0) {
09789 ast_log(LOG_WARNING, "Huh?\n");
09790 ast_hangup(chan);
09791 goto quit;
09792 }
09793 if (p->dsp)
09794 ast_dsp_digitreset(p->dsp);
09795 switch (p->sig) {
09796 case SIG_FEATD:
09797 case SIG_FEATDMF:
09798 case SIG_FEATDMF_TA:
09799 case SIG_E911:
09800 case SIG_FGC_CAMAMF:
09801 case SIG_FEATB:
09802 case SIG_EMWINK:
09803 case SIG_SF_FEATD:
09804 case SIG_SF_FEATDMF:
09805 case SIG_SF_FEATB:
09806 case SIG_SFWINK:
09807 if (dahdi_wink(p, idx))
09808 goto quit;
09809
09810 case SIG_EM:
09811 case SIG_EM_E1:
09812 case SIG_SF:
09813 case SIG_FGC_CAMA:
09814 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09815 if (p->dsp)
09816 ast_dsp_digitreset(p->dsp);
09817
09818 if (p->dsp) {
09819 if (NEED_MFDETECT(p))
09820 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09821 else
09822 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09823 }
09824 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09825
09826 if (!p->immediate)
09827
09828 res = ast_waitfordigit(chan, 5000);
09829 else
09830 res = 0;
09831 if (res > 0) {
09832
09833 dtmfbuf[0] = res;
09834 switch (p->sig) {
09835 case SIG_FEATD:
09836 case SIG_SF_FEATD:
09837 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09838 if (res > 0)
09839 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09840 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09841 break;
09842 case SIG_FEATDMF_TA:
09843 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09844 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09845 if (dahdi_wink(p, idx)) goto quit;
09846 dtmfbuf[0] = 0;
09847
09848 res = ast_waitfordigit(chan, 5000);
09849 if (res <= 0) break;
09850 dtmfbuf[0] = res;
09851
09852 case SIG_FEATDMF:
09853 case SIG_E911:
09854 case SIG_FGC_CAMAMF:
09855 case SIG_SF_FEATDMF:
09856 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09857
09858 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09859 {
09860 if (dahdi_wink(p, idx)) goto quit;
09861 dtmfbuf[0] = 0;
09862
09863 res = ast_waitfordigit(chan, 5000);
09864 if (res <= 0) break;
09865 dtmfbuf[0] = res;
09866 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09867 }
09868 if (res > 0) {
09869
09870 if (p->sig == SIG_E911)
09871 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09872 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09873 }
09874 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09875 break;
09876 case SIG_FEATB:
09877 case SIG_SF_FEATB:
09878 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09879 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09880 break;
09881 case SIG_EMWINK:
09882
09883
09884
09885
09886 if (res == '*') {
09887 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09888 if (res > 0)
09889 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09890 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09891 break;
09892 }
09893 default:
09894
09895 len = 1;
09896 dtmfbuf[len] = '\0';
09897 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09898 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09899 timeout = matchdigittimeout;
09900 } else {
09901 timeout = gendigittimeout;
09902 }
09903 res = ast_waitfordigit(chan, timeout);
09904 if (res < 0) {
09905 ast_debug(1, "waitfordigit returned < 0...\n");
09906 ast_hangup(chan);
09907 goto quit;
09908 } else if (res) {
09909 dtmfbuf[len++] = res;
09910 dtmfbuf[len] = '\0';
09911 } else {
09912 break;
09913 }
09914 }
09915 break;
09916 }
09917 }
09918 if (res == -1) {
09919 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09920 ast_hangup(chan);
09921 goto quit;
09922 } else if (res < 0) {
09923 ast_debug(1, "Got hung up before digits finished\n");
09924 ast_hangup(chan);
09925 goto quit;
09926 }
09927
09928 if (p->sig == SIG_FGC_CAMA) {
09929 char anibuf[100];
09930
09931 if (ast_safe_sleep(chan,1000) == -1) {
09932 ast_hangup(chan);
09933 goto quit;
09934 }
09935 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09936 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09937 res = my_getsigstr(chan, anibuf, "#", 10000);
09938 if ((res > 0) && (strlen(anibuf) > 2)) {
09939 if (anibuf[strlen(anibuf) - 1] == '#')
09940 anibuf[strlen(anibuf) - 1] = 0;
09941 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09942 }
09943 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09944 }
09945
09946 ast_copy_string(exten, dtmfbuf, sizeof(exten));
09947 if (ast_strlen_zero(exten))
09948 ast_copy_string(exten, "s", sizeof(exten));
09949 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09950
09951 if (exten[0] == '*') {
09952 char *stringp=NULL;
09953 ast_copy_string(exten2, exten, sizeof(exten2));
09954
09955 stringp=exten2 +1;
09956 s1 = strsep(&stringp, "*");
09957 s2 = strsep(&stringp, "*");
09958 if (s2) {
09959 if (!ast_strlen_zero(p->cid_num))
09960 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09961 else
09962 ast_set_callerid(chan, s1, NULL, s1);
09963 ast_copy_string(exten, s2, sizeof(exten));
09964 } else
09965 ast_copy_string(exten, s1, sizeof(exten));
09966 } else if (p->sig == SIG_FEATD)
09967 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09968 }
09969 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09970 if (exten[0] == '*') {
09971 char *stringp=NULL;
09972 ast_copy_string(exten2, exten, sizeof(exten2));
09973
09974 stringp=exten2 +1;
09975 s1 = strsep(&stringp, "#");
09976 s2 = strsep(&stringp, "#");
09977 if (s2) {
09978 if (!ast_strlen_zero(p->cid_num))
09979 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09980 else
09981 if (*(s1 + 2))
09982 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09983 ast_copy_string(exten, s2 + 1, sizeof(exten));
09984 } else
09985 ast_copy_string(exten, s1 + 2, sizeof(exten));
09986 } else
09987 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09988 }
09989 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09990 if (exten[0] == '*') {
09991 char *stringp=NULL;
09992 ast_copy_string(exten2, exten, sizeof(exten2));
09993
09994 stringp=exten2 +1;
09995 s1 = strsep(&stringp, "#");
09996 s2 = strsep(&stringp, "#");
09997 if (s2 && (*(s2 + 1) == '0')) {
09998 if (*(s2 + 2))
09999 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10000 }
10001 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10002 else ast_copy_string(exten, "911", sizeof(exten));
10003 } else
10004 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10005 }
10006 if (p->sig == SIG_FEATB) {
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 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10014 } else
10015 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10016 }
10017 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10018 dahdi_wink(p, idx);
10019
10020
10021
10022 if (ast_safe_sleep(chan, 100)) {
10023 ast_hangup(chan);
10024 goto quit;
10025 }
10026 }
10027 dahdi_enable_ec(p);
10028 if (NEED_MFDETECT(p)) {
10029 if (p->dsp) {
10030 if (!p->hardwaredtmf)
10031 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10032 else {
10033 ast_dsp_free(p->dsp);
10034 p->dsp = NULL;
10035 }
10036 }
10037 }
10038
10039 if (ast_exists_extension(chan, chan->context, exten, 1,
10040 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10041 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10042 if (p->dsp) ast_dsp_digitreset(p->dsp);
10043 res = ast_pbx_run(chan);
10044 if (res) {
10045 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10046 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10047 }
10048 goto quit;
10049 } else {
10050 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10051 sleep(2);
10052 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10053 if (res < 0)
10054 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10055 else
10056 sleep(1);
10057 res = ast_streamfile(chan, "ss-noservice", chan->language);
10058 if (res >= 0)
10059 ast_waitstream(chan, "");
10060 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10061 ast_hangup(chan);
10062 goto quit;
10063 }
10064 break;
10065 case SIG_FXOLS:
10066 case SIG_FXOGS:
10067 case SIG_FXOKS:
10068
10069 timeout = firstdigittimeout;
10070
10071
10072 if (p->subs[SUB_THREEWAY].owner)
10073 timeout = 999999;
10074 while (len < AST_MAX_EXTENSION-1) {
10075
10076
10077 if (p->immediate)
10078 res = 's';
10079 else
10080 res = ast_waitfordigit(chan, timeout);
10081 timeout = 0;
10082 if (res < 0) {
10083 ast_debug(1, "waitfordigit returned < 0...\n");
10084 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10085 ast_hangup(chan);
10086 goto quit;
10087 } else if (res) {
10088 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10089 exten[len++]=res;
10090 exten[len] = '\0';
10091 }
10092 if (!ast_ignore_pattern(chan->context, exten))
10093 tone_zone_play_tone(p->subs[idx].dfd, -1);
10094 else
10095 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10096 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10097 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10098 if (getforward) {
10099
10100 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10101 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10102 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10103 if (res)
10104 break;
10105 usleep(500000);
10106 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10107 sleep(1);
10108 memset(exten, 0, sizeof(exten));
10109 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10110 len = 0;
10111 getforward = 0;
10112 } else {
10113 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10114 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10115 if (!ast_strlen_zero(p->cid_num)) {
10116 if (!p->hidecallerid)
10117 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10118 else
10119 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10120 }
10121 if (!ast_strlen_zero(p->cid_name)) {
10122 if (!p->hidecallerid)
10123 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10124 }
10125 ast_setstate(chan, AST_STATE_RING);
10126 dahdi_enable_ec(p);
10127 res = ast_pbx_run(chan);
10128 if (res) {
10129 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10130 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10131 }
10132 goto quit;
10133 }
10134 } else {
10135
10136
10137 timeout = matchdigittimeout;
10138 }
10139 } else if (res == 0) {
10140 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10141 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10142 dahdi_wait_event(p->subs[idx].dfd);
10143 ast_hangup(chan);
10144 goto quit;
10145 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10146 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10147
10148 p->callwaiting = 0;
10149 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10150 if (res) {
10151 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10152 chan->name, strerror(errno));
10153 }
10154 len = 0;
10155 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10156 memset(exten, 0, sizeof(exten));
10157 timeout = firstdigittimeout;
10158
10159 } else if (!strcmp(exten,ast_pickup_ext())) {
10160
10161
10162
10163
10164 if (idx == SUB_REAL) {
10165
10166 if (p->subs[SUB_THREEWAY].owner) {
10167
10168
10169 alloc_sub(p, SUB_CALLWAIT);
10170 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10171 unalloc_sub(p, SUB_THREEWAY);
10172 }
10173 dahdi_enable_ec(p);
10174 if (ast_pickup_call(chan)) {
10175 ast_debug(1, "No call pickup possible...\n");
10176 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10177 dahdi_wait_event(p->subs[idx].dfd);
10178 }
10179 ast_hangup(chan);
10180 goto quit;
10181 } else {
10182 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10183 ast_hangup(chan);
10184 goto quit;
10185 }
10186
10187 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10188 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10189
10190 p->hidecallerid = 1;
10191 ast_party_number_free(&chan->caller.id.number);
10192 ast_party_number_init(&chan->caller.id.number);
10193 ast_party_name_free(&chan->caller.id.name);
10194 ast_party_name_init(&chan->caller.id.name);
10195 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10196 if (res) {
10197 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10198 chan->name, strerror(errno));
10199 }
10200 len = 0;
10201 memset(exten, 0, sizeof(exten));
10202 timeout = firstdigittimeout;
10203 } else if (p->callreturn && !strcmp(exten, "*69")) {
10204 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10205 break;
10206 } else if (!strcmp(exten, "*78")) {
10207 dahdi_dnd(p, 1);
10208
10209 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10210 getforward = 0;
10211 memset(exten, 0, sizeof(exten));
10212 len = 0;
10213 } else if (!strcmp(exten, "*79")) {
10214 dahdi_dnd(p, 0);
10215
10216 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10217 getforward = 0;
10218 memset(exten, 0, sizeof(exten));
10219 len = 0;
10220 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10221 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10222 getforward = 1;
10223 memset(exten, 0, sizeof(exten));
10224 len = 0;
10225 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10226 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10227 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10228 memset(p->call_forward, 0, sizeof(p->call_forward));
10229 getforward = 0;
10230 memset(exten, 0, sizeof(exten));
10231 len = 0;
10232 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10233 p->subs[SUB_THREEWAY].owner &&
10234 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10235
10236
10237 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10238 ast_verb(3, "Parking call to '%s'\n", chan->name);
10239 break;
10240 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10241 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10242
10243 p->hidecallerid = 0;
10244 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10245 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10246 if (res) {
10247 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10248 chan->name, strerror(errno));
10249 }
10250 len = 0;
10251 memset(exten, 0, sizeof(exten));
10252 timeout = firstdigittimeout;
10253 } else if (!strcmp(exten, "*0")) {
10254 struct ast_channel *nbridge =
10255 p->subs[SUB_THREEWAY].owner;
10256 struct dahdi_pvt *pbridge = NULL;
10257
10258 if (nbridge && ast_bridged_channel(nbridge))
10259 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10260 if (nbridge && pbridge &&
10261 (nbridge->tech == &dahdi_tech) &&
10262 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10263 ISTRUNK(pbridge)) {
10264 int func = DAHDI_FLASH;
10265
10266 p->dop.dialstr[0] = '\0';
10267
10268 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10269 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10270 nbridge->name, strerror(errno));
10271 }
10272 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10273 unalloc_sub(p, SUB_THREEWAY);
10274 p->owner = p->subs[SUB_REAL].owner;
10275 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10276 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10277 ast_hangup(chan);
10278 goto quit;
10279 } else {
10280 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10281 dahdi_wait_event(p->subs[idx].dfd);
10282 tone_zone_play_tone(p->subs[idx].dfd, -1);
10283 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10284 unalloc_sub(p, SUB_THREEWAY);
10285 p->owner = p->subs[SUB_REAL].owner;
10286 ast_hangup(chan);
10287 goto quit;
10288 }
10289 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10290 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10291 && !canmatch_featurecode(exten)) {
10292 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10293 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10294 chan->context);
10295 break;
10296 }
10297 if (!timeout)
10298 timeout = gendigittimeout;
10299 if (len && !ast_ignore_pattern(chan->context, exten))
10300 tone_zone_play_tone(p->subs[idx].dfd, -1);
10301 }
10302 break;
10303 case SIG_FXSLS:
10304 case SIG_FXSGS:
10305 case SIG_FXSKS:
10306
10307 if (p->use_smdi && p->smdi_iface) {
10308 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10309
10310 if (smdi_msg != NULL) {
10311 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10312
10313 if (smdi_msg->type == 'B')
10314 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10315 else if (smdi_msg->type == 'N')
10316 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10317
10318 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10319 } else {
10320 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10321 }
10322 }
10323
10324 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10325 number = smdi_msg->calling_st;
10326
10327
10328
10329
10330 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10331 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10332
10333 if (p->cid_signalling == CID_SIG_DTMF) {
10334 int k = 0;
10335 cs = NULL;
10336 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10337 dahdi_setlinear(p->subs[idx].dfd, 0);
10338
10339
10340
10341
10342
10343
10344 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10345 res = 4000;
10346 for (;;) {
10347 struct ast_frame *f;
10348 res = ast_waitfor(chan, res);
10349 if (res <= 0) {
10350
10351
10352
10353
10354
10355 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10356 "Exiting simple switch\n");
10357 ast_hangup(chan);
10358 goto quit;
10359 }
10360 f = ast_read(chan);
10361 if (!f)
10362 break;
10363 if (f->frametype == AST_FRAME_DTMF) {
10364 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10365 dtmfbuf[k++] = f->subclass.integer;
10366 }
10367 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10368 res = 4000;
10369 }
10370 ast_frfree(f);
10371 if (chan->_state == AST_STATE_RING ||
10372 chan->_state == AST_STATE_RINGING)
10373 break;
10374 }
10375 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10376 dtmfbuf[k] = '\0';
10377 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10378
10379 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10380 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10381 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10382
10383 if (!ast_strlen_zero(dtmfcid))
10384 number = dtmfcid;
10385 else
10386 number = NULL;
10387
10388 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10389 cs = callerid_new(p->cid_signalling);
10390 if (cs) {
10391 samples = 0;
10392 #if 1
10393 bump_gains(p);
10394 #endif
10395
10396 dahdi_setlinear(p->subs[idx].dfd, 0);
10397
10398
10399 for (;;) {
10400 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10401 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10402 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10403 callerid_free(cs);
10404 ast_hangup(chan);
10405 goto quit;
10406 }
10407 if (i & DAHDI_IOMUX_SIGEVENT) {
10408 res = dahdi_get_event(p->subs[idx].dfd);
10409 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10410 if (res == DAHDI_EVENT_NOALARM) {
10411 p->inalarm = 0;
10412 }
10413
10414 if (p->cid_signalling == CID_SIG_V23_JP) {
10415 if (res == DAHDI_EVENT_RINGBEGIN) {
10416 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10417 usleep(1);
10418 }
10419 } else {
10420 res = 0;
10421 break;
10422 }
10423 } else if (i & DAHDI_IOMUX_READ) {
10424 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10425 if (res < 0) {
10426 if (errno != ELAST) {
10427 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10428 callerid_free(cs);
10429 ast_hangup(chan);
10430 goto quit;
10431 }
10432 break;
10433 }
10434 samples += res;
10435
10436 if (p->cid_signalling == CID_SIG_V23_JP) {
10437 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10438 } else {
10439 res = callerid_feed(cs, buf, res, AST_LAW(p));
10440 }
10441 if (res < 0) {
10442
10443
10444
10445
10446 ast_log(LOG_WARNING,
10447 "Failed to decode CallerID on channel '%s'\n",
10448 chan->name);
10449 break;
10450 } else if (res)
10451 break;
10452 else if (samples > (8000 * 10))
10453 break;
10454 }
10455 }
10456 if (res == 1) {
10457 callerid_get(cs, &name, &number, &flags);
10458 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10459 }
10460
10461 if (p->cid_signalling == CID_SIG_V23_JP) {
10462 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10463 usleep(1);
10464 }
10465
10466
10467 res = 4000;
10468 for (;;) {
10469 struct ast_frame *f;
10470 res = ast_waitfor(chan, res);
10471 if (res <= 0) {
10472 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10473 "Exiting simple switch\n");
10474 ast_hangup(chan);
10475 goto quit;
10476 }
10477 if (!(f = ast_read(chan))) {
10478 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10479 ast_hangup(chan);
10480 goto quit;
10481 }
10482 ast_frfree(f);
10483 if (chan->_state == AST_STATE_RING ||
10484 chan->_state == AST_STATE_RINGING)
10485 break;
10486 }
10487
10488
10489
10490 if (p->usedistinctiveringdetection) {
10491 len = 0;
10492 distMatches = 0;
10493
10494 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10495 curRingData[receivedRingT] = 0;
10496 receivedRingT = 0;
10497 counter = 0;
10498 counter1 = 0;
10499
10500 if (strcmp(p->context,p->defcontext) != 0) {
10501 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10502 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10503 }
10504
10505 for (;;) {
10506 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10507 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10508 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10509 callerid_free(cs);
10510 ast_hangup(chan);
10511 goto quit;
10512 }
10513 if (i & DAHDI_IOMUX_SIGEVENT) {
10514 res = dahdi_get_event(p->subs[idx].dfd);
10515 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10516 if (res == DAHDI_EVENT_NOALARM) {
10517 p->inalarm = 0;
10518 }
10519 res = 0;
10520
10521
10522 curRingData[receivedRingT] = p->ringt;
10523
10524 if (p->ringt < p->ringt_base/2)
10525 break;
10526
10527
10528 if (++receivedRingT == ARRAY_LEN(curRingData))
10529 break;
10530 } else if (i & DAHDI_IOMUX_READ) {
10531 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10532 if (res < 0) {
10533 if (errno != ELAST) {
10534 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10535 callerid_free(cs);
10536 ast_hangup(chan);
10537 goto quit;
10538 }
10539 break;
10540 }
10541 if (p->ringt > 0) {
10542 if (!(--p->ringt)) {
10543 res = -1;
10544 break;
10545 }
10546 }
10547 }
10548 }
10549
10550 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10551 for (counter = 0; counter < 3; counter++) {
10552
10553
10554 distMatches = 0;
10555 for (counter1 = 0; counter1 < 3; counter1++) {
10556 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10557 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10558 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10559 curRingData[counter1]);
10560 distMatches++;
10561 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10562 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10563 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10564 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10565 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10566 distMatches++;
10567 }
10568 }
10569
10570 if (distMatches == 3) {
10571
10572 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10573 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10574 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10575 break;
10576 }
10577 }
10578 }
10579
10580 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10581 #if 1
10582 restore_gains(p);
10583 #endif
10584 } else
10585 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10586 } else {
10587 ast_log(LOG_WARNING, "Channel %s in prering "
10588 "state, but I have nothing to do. "
10589 "Terminating simple switch, should be "
10590 "restarted by the actual ring.\n",
10591 chan->name);
10592 ast_hangup(chan);
10593 goto quit;
10594 }
10595 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10596 if (p->cid_signalling == CID_SIG_DTMF) {
10597 int k = 0;
10598 cs = NULL;
10599 dahdi_setlinear(p->subs[idx].dfd, 0);
10600 res = 2000;
10601 for (;;) {
10602 struct ast_frame *f;
10603 res = ast_waitfor(chan, res);
10604 if (res <= 0) {
10605 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10606 "Exiting simple switch\n");
10607 ast_hangup(chan);
10608 return NULL;
10609 }
10610 f = ast_read(chan);
10611 if (f->frametype == AST_FRAME_DTMF) {
10612 dtmfbuf[k++] = f->subclass.integer;
10613 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10614 res = 2000;
10615 }
10616 ast_frfree(f);
10617
10618 if (p->ringt_base == p->ringt)
10619 break;
10620 }
10621 dtmfbuf[k] = '\0';
10622 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10623
10624 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10625 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10626 dtmfcid, flags);
10627
10628 if (!ast_strlen_zero(dtmfcid))
10629 number = dtmfcid;
10630 else
10631 number = NULL;
10632
10633 } else {
10634
10635 cs = callerid_new(p->cid_signalling);
10636 if (cs) {
10637 #if 1
10638 bump_gains(p);
10639 #endif
10640 samples = 0;
10641 len = 0;
10642 distMatches = 0;
10643
10644 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10645 curRingData[receivedRingT] = 0;
10646 receivedRingT = 0;
10647 counter = 0;
10648 counter1 = 0;
10649
10650 if (strcmp(p->context,p->defcontext) != 0) {
10651 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10652 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10653 }
10654
10655
10656 dahdi_setlinear(p->subs[idx].dfd, 0);
10657 for (;;) {
10658 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10659 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10660 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10661 callerid_free(cs);
10662 ast_hangup(chan);
10663 goto quit;
10664 }
10665 if (i & DAHDI_IOMUX_SIGEVENT) {
10666 res = dahdi_get_event(p->subs[idx].dfd);
10667 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10668 if (res == DAHDI_EVENT_NOALARM) {
10669 p->inalarm = 0;
10670 }
10671
10672 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10673 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10674 p->polarity = POLARITY_IDLE;
10675 callerid_free(cs);
10676 ast_hangup(chan);
10677 goto quit;
10678 }
10679 res = 0;
10680
10681
10682 curRingData[receivedRingT] = p->ringt;
10683
10684 if (p->ringt < p->ringt_base/2)
10685 break;
10686
10687
10688 if (++receivedRingT == ARRAY_LEN(curRingData))
10689 break;
10690 } else if (i & DAHDI_IOMUX_READ) {
10691 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10692 if (res < 0) {
10693 if (errno != ELAST) {
10694 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10695 callerid_free(cs);
10696 ast_hangup(chan);
10697 goto quit;
10698 }
10699 break;
10700 }
10701 if (p->ringt > 0) {
10702 if (!(--p->ringt)) {
10703 res = -1;
10704 break;
10705 }
10706 }
10707 samples += res;
10708 res = callerid_feed(cs, buf, res, AST_LAW(p));
10709 if (res < 0) {
10710
10711
10712
10713
10714 ast_log(LOG_WARNING,
10715 "Failed to decode CallerID on channel '%s'\n",
10716 chan->name);
10717 break;
10718 } else if (res)
10719 break;
10720 else if (samples > (8000 * 10))
10721 break;
10722 }
10723 }
10724 if (res == 1) {
10725 callerid_get(cs, &name, &number, &flags);
10726 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10727 }
10728 if (distinctiveringaftercid == 1) {
10729
10730 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10731 curRingData[receivedRingT] = 0;
10732 }
10733 receivedRingT = 0;
10734 ast_verb(3, "Detecting post-CID distinctive ring\n");
10735 for (;;) {
10736 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10737 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10738 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10739 callerid_free(cs);
10740 ast_hangup(chan);
10741 goto quit;
10742 }
10743 if (i & DAHDI_IOMUX_SIGEVENT) {
10744 res = dahdi_get_event(p->subs[idx].dfd);
10745 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10746 if (res == DAHDI_EVENT_NOALARM) {
10747 p->inalarm = 0;
10748 }
10749 res = 0;
10750
10751
10752 curRingData[receivedRingT] = p->ringt;
10753
10754 if (p->ringt < p->ringt_base/2)
10755 break;
10756
10757
10758 if (++receivedRingT == ARRAY_LEN(curRingData))
10759 break;
10760 } else if (i & DAHDI_IOMUX_READ) {
10761 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10762 if (res < 0) {
10763 if (errno != ELAST) {
10764 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10765 callerid_free(cs);
10766 ast_hangup(chan);
10767 goto quit;
10768 }
10769 break;
10770 }
10771 if (p->ringt > 0) {
10772 if (!(--p->ringt)) {
10773 res = -1;
10774 break;
10775 }
10776 }
10777 }
10778 }
10779 }
10780 if (p->usedistinctiveringdetection) {
10781
10782 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10783
10784 for (counter = 0; counter < 3; counter++) {
10785
10786
10787
10788 ast_verb(3, "Checking %d,%d,%d\n",
10789 p->drings.ringnum[counter].ring[0],
10790 p->drings.ringnum[counter].ring[1],
10791 p->drings.ringnum[counter].ring[2]);
10792 distMatches = 0;
10793 for (counter1 = 0; counter1 < 3; counter1++) {
10794 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10795 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10796 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10797 curRingData[counter1]);
10798 distMatches++;
10799 }
10800 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10801 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10802 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10803 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10804 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10805 distMatches++;
10806 }
10807 }
10808 if (distMatches == 3) {
10809
10810 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10811 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10812 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10813 break;
10814 }
10815 }
10816 }
10817
10818 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10819 #if 1
10820 restore_gains(p);
10821 #endif
10822 if (res < 0) {
10823 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10824 }
10825 } else
10826 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10827 }
10828 } else
10829 cs = NULL;
10830
10831 if (number)
10832 ast_shrink_phone_number(number);
10833 ast_set_callerid(chan, number, name, number);
10834
10835 if (smdi_msg)
10836 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10837
10838 if (cs)
10839 callerid_free(cs);
10840
10841 my_handle_notify_message(chan, p, flags, -1);
10842
10843 ast_setstate(chan, AST_STATE_RING);
10844 chan->rings = 1;
10845 p->ringt = p->ringt_base;
10846 res = ast_pbx_run(chan);
10847 if (res) {
10848 ast_hangup(chan);
10849 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10850 }
10851 goto quit;
10852 default:
10853 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10854 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10855 if (res < 0)
10856 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10857 }
10858 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10859 if (res < 0)
10860 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10861 ast_hangup(chan);
10862 quit:
10863 ast_mutex_lock(&ss_thread_lock);
10864 ss_thread_count--;
10865 ast_cond_signal(&ss_thread_complete);
10866 ast_mutex_unlock(&ss_thread_lock);
10867 return NULL;
10868 }
10869
10870 struct mwi_thread_data {
10871 struct dahdi_pvt *pvt;
10872 unsigned char buf[READ_SIZE];
10873 size_t len;
10874 };
10875
10876 static int calc_energy(const unsigned char *buf, int len, format_t law)
10877 {
10878 int x;
10879 int sum = 0;
10880
10881 if (!len)
10882 return 0;
10883
10884 for (x = 0; x < len; x++)
10885 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10886
10887 return sum / len;
10888 }
10889
10890 static void *mwi_thread(void *data)
10891 {
10892 struct mwi_thread_data *mtd = data;
10893 struct callerid_state *cs;
10894 pthread_t threadid;
10895 int samples = 0;
10896 char *name, *number;
10897 int flags;
10898 int i, res;
10899 unsigned int spill_done = 0;
10900 int spill_result = -1;
10901
10902 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10903 mtd->pvt->mwimonitoractive = 0;
10904
10905 return NULL;
10906 }
10907
10908 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10909
10910 bump_gains(mtd->pvt);
10911
10912 for (;;) {
10913 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10914 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10915 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10916 goto quit;
10917 }
10918
10919 if (i & DAHDI_IOMUX_SIGEVENT) {
10920 struct ast_channel *chan;
10921
10922
10923
10924
10925 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10926
10927 switch (res) {
10928 case DAHDI_EVENT_NEONMWI_ACTIVE:
10929 case DAHDI_EVENT_NEONMWI_INACTIVE:
10930 case DAHDI_EVENT_NONE:
10931 case DAHDI_EVENT_BITSCHANGED:
10932 break;
10933 case DAHDI_EVENT_NOALARM:
10934 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10935 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10936
10937 analog_p->inalarm = 0;
10938 }
10939 mtd->pvt->inalarm = 0;
10940 handle_clear_alarms(mtd->pvt);
10941 break;
10942 case DAHDI_EVENT_ALARM:
10943 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10944 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10945
10946 analog_p->inalarm = 1;
10947 }
10948 mtd->pvt->inalarm = 1;
10949 res = get_alarms(mtd->pvt);
10950 handle_alarms(mtd->pvt, res);
10951 break;
10952 default:
10953 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
10954 callerid_free(cs);
10955
10956 restore_gains(mtd->pvt);
10957 mtd->pvt->ringt = mtd->pvt->ringt_base;
10958
10959 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10960 int result;
10961 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10962 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10963 } else {
10964 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10965 }
10966 if (result) {
10967 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10968 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10969 if (res < 0)
10970 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10971 ast_hangup(chan);
10972 goto quit;
10973 }
10974 goto quit_no_clean;
10975
10976 } else {
10977 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10978 }
10979 }
10980 } else if (i & DAHDI_IOMUX_READ) {
10981 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10982 if (errno != ELAST) {
10983 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10984 goto quit;
10985 }
10986 break;
10987 }
10988 samples += res;
10989 if (!spill_done) {
10990 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10991
10992
10993
10994
10995 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10996 break;
10997 } else if (spill_result) {
10998 spill_done = 1;
10999 }
11000 } else {
11001
11002
11003
11004 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11005 break;
11006 }
11007 if (samples > (8000 * 4))
11008 break;
11009 }
11010 }
11011
11012 if (spill_result == 1) {
11013 callerid_get(cs, &name, &number, &flags);
11014 if (flags & CID_MSGWAITING) {
11015 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11016 notify_message(mtd->pvt->mailbox, 1);
11017 } else if (flags & CID_NOMSGWAITING) {
11018 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11019 notify_message(mtd->pvt->mailbox, 0);
11020 } else {
11021 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11022 }
11023 }
11024
11025
11026 quit:
11027 callerid_free(cs);
11028
11029 restore_gains(mtd->pvt);
11030
11031 quit_no_clean:
11032 mtd->pvt->mwimonitoractive = 0;
11033
11034 ast_free(mtd);
11035
11036 return NULL;
11037 }
11038
11039
11040
11041
11042
11043
11044
11045
11046 static int mwi_send_init(struct dahdi_pvt * pvt)
11047 {
11048 int x;
11049
11050 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11051
11052 if (pvt->mwisend_rpas) {
11053 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11054 pvt->mwisendactive = 1;
11055 } else if (pvt->mwisend_fsk) {
11056 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11057 pvt->mwisendactive = 1;
11058 } else {
11059 pvt->mwisendactive = 0;
11060 return 0;
11061 }
11062 #else
11063 if (mwisend_rpas) {
11064 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11065 } else {
11066 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11067 }
11068 pvt->mwisendactive = 1;
11069 #endif
11070
11071 if (pvt->cidspill) {
11072 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11073 ast_free(pvt->cidspill);
11074 pvt->cidspill = NULL;
11075 pvt->cidpos = 0;
11076 pvt->cidlen = 0;
11077 }
11078 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11079 if (!pvt->cidspill) {
11080 pvt->mwisendactive = 0;
11081 return -1;
11082 }
11083 x = DAHDI_FLUSH_BOTH;
11084 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11085 x = 3000;
11086 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11087 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11088 if (pvt->mwisend_fsk) {
11089 #endif
11090 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11091 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11092 pvt->cidpos = 0;
11093 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11094 }
11095 #endif
11096 return 0;
11097 }
11098
11099 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11100 {
11101 struct timeval now;
11102 int res;
11103
11104
11105
11106
11107 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11108 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11109 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11110
11111 switch ( pvt->mwisend_data.mwisend_current) {
11112 case MWI_SEND_SA:
11113
11114 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11115 if (res) {
11116 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11117 goto quit;
11118 }
11119 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11120 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11121 break;
11122 case MWI_SEND_SA_WAIT:
11123 break;
11124 case MWI_SEND_PAUSE:
11125 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11126 if (pvt->mwisend_fsk) {
11127 #endif
11128 gettimeofday(&now, NULL);
11129 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11130 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11131 }
11132 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11133 } else {
11134 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11135 }
11136 #endif
11137 break;
11138 case MWI_SEND_SPILL:
11139
11140 if(0 < num_read) {
11141 if (num_read > pvt->cidlen - pvt->cidpos)
11142 num_read = pvt->cidlen - pvt->cidpos;
11143 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11144 if (res > 0) {
11145 pvt->cidpos += res;
11146 if (pvt->cidpos >= pvt->cidlen) {
11147 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11148 }
11149 } else {
11150 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11151 goto quit;
11152 }
11153 }
11154 break;
11155 case MWI_SEND_CLEANUP:
11156
11157 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11158 break;
11159 default:
11160
11161 goto quit;
11162 }
11163 }
11164
11165 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11166 if (pvt->cidspill) {
11167 ast_free(pvt->cidspill);
11168 pvt->cidspill = NULL;
11169 pvt->cidpos = 0;
11170 pvt->cidlen = 0;
11171 }
11172 pvt->mwisendactive = 0;
11173 }
11174 return 0;
11175 quit:
11176 if (pvt->cidspill) {
11177 ast_free(pvt->cidspill);
11178 pvt->cidspill = NULL;
11179 pvt->cidpos = 0;
11180 pvt->cidlen = 0;
11181 }
11182 pvt->mwisendactive = 0;
11183 return -1;
11184 }
11185
11186 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11187 {
11188 int handled = 0;
11189
11190 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11191 switch (event) {
11192 case DAHDI_EVENT_RINGEROFF:
11193 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11194 handled = 1;
11195
11196 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11197 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11198 ast_free(pvt->cidspill);
11199 pvt->cidspill = NULL;
11200 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11201 pvt->mwisendactive = 0;
11202 } else {
11203 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11204 gettimeofday(&pvt->mwisend_data.pause, NULL);
11205 }
11206 }
11207 break;
11208
11209 case DAHDI_EVENT_RINGOFFHOOK:
11210 if (pvt->cidspill) {
11211 ast_free(pvt->cidspill);
11212 pvt->cidspill = NULL;
11213 pvt->cidpos = 0;
11214 pvt->cidlen = 0;
11215 }
11216 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11217 pvt->mwisendactive = 0;
11218 break;
11219 case DAHDI_EVENT_RINGERON:
11220 case DAHDI_EVENT_HOOKCOMPLETE:
11221 break;
11222 default:
11223 break;
11224 }
11225 }
11226 return handled;
11227 }
11228
11229
11230 static int dahdi_destroy_channel_bynum(int channel)
11231 {
11232 struct dahdi_pvt *cur;
11233
11234 ast_mutex_lock(&iflock);
11235 for (cur = iflist; cur; cur = cur->next) {
11236 if (cur->channel == channel) {
11237 int x = DAHDI_FLASH;
11238
11239
11240 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11241
11242 destroy_channel(cur, 1);
11243 ast_mutex_unlock(&iflock);
11244 ast_module_unref(ast_module_info->self);
11245 return RESULT_SUCCESS;
11246 }
11247 }
11248 ast_mutex_unlock(&iflock);
11249 return RESULT_FAILURE;
11250 }
11251
11252 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11253 {
11254 int res;
11255 pthread_t threadid;
11256 struct ast_channel *chan;
11257
11258
11259
11260 switch (event) {
11261 case DAHDI_EVENT_NONE:
11262 case DAHDI_EVENT_BITSCHANGED:
11263 break;
11264 case DAHDI_EVENT_WINKFLASH:
11265 case DAHDI_EVENT_RINGOFFHOOK:
11266 if (i->inalarm) break;
11267 if (i->radio) break;
11268
11269 switch (i->sig) {
11270 case SIG_FXOLS:
11271 case SIG_FXOGS:
11272 case SIG_FXOKS:
11273 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11274 if (res && (errno == EBUSY))
11275 break;
11276
11277
11278 ast_free(i->cidspill);
11279 i->cidspill = NULL;
11280 restore_conference(i);
11281
11282 if (i->immediate) {
11283 dahdi_enable_ec(i);
11284
11285 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11286 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11287 if (!chan) {
11288 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11289 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11290 if (res < 0)
11291 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11292 }
11293 } else {
11294
11295 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11296 if (chan) {
11297 if (has_voicemail(i))
11298 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11299 else
11300 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11301 if (res < 0)
11302 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11303 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11304 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11305 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11306 if (res < 0)
11307 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11308 ast_hangup(chan);
11309 }
11310 } else
11311 ast_log(LOG_WARNING, "Unable to create channel\n");
11312 }
11313 break;
11314 case SIG_FXSLS:
11315 case SIG_FXSGS:
11316 case SIG_FXSKS:
11317 i->ringt = i->ringt_base;
11318
11319 case SIG_EMWINK:
11320 case SIG_FEATD:
11321 case SIG_FEATDMF:
11322 case SIG_FEATDMF_TA:
11323 case SIG_E911:
11324 case SIG_FGC_CAMA:
11325 case SIG_FGC_CAMAMF:
11326 case SIG_FEATB:
11327 case SIG_EM:
11328 case SIG_EM_E1:
11329 case SIG_SFWINK:
11330 case SIG_SF_FEATD:
11331 case SIG_SF_FEATDMF:
11332 case SIG_SF_FEATB:
11333 case SIG_SF:
11334
11335 if (i->cid_start == CID_START_POLARITY_IN) {
11336 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11337 } else {
11338 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11339 }
11340
11341 if (!chan) {
11342 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11343 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11344 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11345 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11346 if (res < 0) {
11347 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11348 }
11349 ast_hangup(chan);
11350 }
11351 break;
11352 default:
11353 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11354 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11355 if (res < 0)
11356 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11357 return NULL;
11358 }
11359 break;
11360 case DAHDI_EVENT_NOALARM:
11361 switch (i->sig) {
11362 #if defined(HAVE_PRI)
11363 case SIG_PRI_LIB_HANDLE_CASES:
11364 ast_mutex_lock(&i->lock);
11365 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11366 ast_mutex_unlock(&i->lock);
11367 break;
11368 #endif
11369 #if defined(HAVE_SS7)
11370 case SIG_SS7:
11371 sig_ss7_set_alarm(i->sig_pvt, 0);
11372 break;
11373 #endif
11374 default:
11375 i->inalarm = 0;
11376 break;
11377 }
11378 handle_clear_alarms(i);
11379 break;
11380 case DAHDI_EVENT_ALARM:
11381 switch (i->sig) {
11382 #if defined(HAVE_PRI)
11383 case SIG_PRI_LIB_HANDLE_CASES:
11384 ast_mutex_lock(&i->lock);
11385 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11386 ast_mutex_unlock(&i->lock);
11387 break;
11388 #endif
11389 #if defined(HAVE_SS7)
11390 case SIG_SS7:
11391 sig_ss7_set_alarm(i->sig_pvt, 1);
11392 break;
11393 #endif
11394 default:
11395 i->inalarm = 1;
11396 break;
11397 }
11398 res = get_alarms(i);
11399 handle_alarms(i, res);
11400
11401 case DAHDI_EVENT_ONHOOK:
11402 if (i->radio)
11403 break;
11404
11405 switch (i->sig) {
11406 case SIG_FXOLS:
11407 case SIG_FXOGS:
11408 case SIG_FEATD:
11409 case SIG_FEATDMF:
11410 case SIG_FEATDMF_TA:
11411 case SIG_E911:
11412 case SIG_FGC_CAMA:
11413 case SIG_FGC_CAMAMF:
11414 case SIG_FEATB:
11415 case SIG_EM:
11416 case SIG_EM_E1:
11417 case SIG_EMWINK:
11418 case SIG_SF_FEATD:
11419 case SIG_SF_FEATDMF:
11420 case SIG_SF_FEATB:
11421 case SIG_SF:
11422 case SIG_SFWINK:
11423 case SIG_FXSLS:
11424 case SIG_FXSGS:
11425 case SIG_FXSKS:
11426 case SIG_FXOKS:
11427 dahdi_disable_ec(i);
11428
11429 #ifdef ZHONE_HACK
11430 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11431 usleep(1);
11432 #endif
11433 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11434 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11435 break;
11436 case SIG_SS7:
11437 case SIG_PRI_LIB_HANDLE_CASES:
11438 dahdi_disable_ec(i);
11439 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11440 break;
11441 default:
11442 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11443 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11444 return NULL;
11445 }
11446 break;
11447 case DAHDI_EVENT_POLARITY:
11448 switch (i->sig) {
11449 case SIG_FXSLS:
11450 case SIG_FXSKS:
11451 case SIG_FXSGS:
11452
11453
11454
11455
11456 if (i->hanguponpolarityswitch)
11457 i->polarity = POLARITY_REV;
11458 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11459 i->polarity = POLARITY_REV;
11460 ast_verb(2, "Starting post polarity "
11461 "CID detection on channel %d\n",
11462 i->channel);
11463 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11464 if (!chan) {
11465 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11466 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11467 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11468 }
11469 }
11470 break;
11471 default:
11472 ast_log(LOG_WARNING, "handle_init_event detected "
11473 "polarity reversal on non-FXO (SIG_FXS) "
11474 "interface %d\n", i->channel);
11475 }
11476 break;
11477 case DAHDI_EVENT_REMOVED:
11478 ast_log(LOG_NOTICE,
11479 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11480 i->channel);
11481 return i;
11482 case DAHDI_EVENT_NEONMWI_ACTIVE:
11483 if (i->mwimonitor_neon) {
11484 notify_message(i->mailbox, 1);
11485 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11486 }
11487 break;
11488 case DAHDI_EVENT_NEONMWI_INACTIVE:
11489 if (i->mwimonitor_neon) {
11490 notify_message(i->mailbox, 0);
11491 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11492 }
11493 break;
11494 }
11495 return NULL;
11496 }
11497
11498 static void *do_monitor(void *data)
11499 {
11500 int count, res, res2, spoint, pollres=0;
11501 struct dahdi_pvt *i;
11502 struct dahdi_pvt *last = NULL;
11503 struct dahdi_pvt *doomed;
11504 time_t thispass = 0, lastpass = 0;
11505 int found;
11506 char buf[1024];
11507 struct pollfd *pfds=NULL;
11508 int lastalloc = -1;
11509
11510
11511
11512 #if 0
11513 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11514 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11515 return NULL;
11516 }
11517 ast_debug(1, "Monitor starting...\n");
11518 #endif
11519 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11520
11521 for (;;) {
11522
11523 ast_mutex_lock(&iflock);
11524 if (!pfds || (lastalloc != ifcount)) {
11525 if (pfds) {
11526 ast_free(pfds);
11527 pfds = NULL;
11528 }
11529 if (ifcount) {
11530 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11531 ast_mutex_unlock(&iflock);
11532 return NULL;
11533 }
11534 }
11535 lastalloc = ifcount;
11536 }
11537
11538
11539 count = 0;
11540 for (i = iflist; i; i = i->next) {
11541 ast_mutex_lock(&i->lock);
11542 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11543 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11544 struct analog_pvt *p = i->sig_pvt;
11545
11546 if (!p)
11547 ast_log(LOG_ERROR, "No sig_pvt?\n");
11548
11549 if (!p->owner && !p->subs[SUB_REAL].owner) {
11550
11551 pfds[count].fd = i->subs[SUB_REAL].dfd;
11552 pfds[count].events = POLLPRI;
11553 pfds[count].revents = 0;
11554
11555 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11556 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11557 pfds[count].events |= POLLIN;
11558 }
11559 count++;
11560 }
11561 } else {
11562 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11563
11564 pfds[count].fd = i->subs[SUB_REAL].dfd;
11565 pfds[count].events = POLLPRI;
11566 pfds[count].revents = 0;
11567
11568
11569 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11570 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11571 pfds[count].events |= POLLIN;
11572 }
11573 count++;
11574 }
11575 }
11576 }
11577 ast_mutex_unlock(&i->lock);
11578 }
11579
11580 ast_mutex_unlock(&iflock);
11581
11582 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11583 pthread_testcancel();
11584
11585 res = poll(pfds, count, 1000);
11586 pthread_testcancel();
11587 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11588
11589
11590 if (res < 0) {
11591 if ((errno != EAGAIN) && (errno != EINTR))
11592 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11593 continue;
11594 }
11595
11596
11597 ast_mutex_lock(&iflock);
11598 found = 0;
11599 spoint = 0;
11600 lastpass = thispass;
11601 thispass = time(NULL);
11602 doomed = NULL;
11603 for (i = iflist;; i = i->next) {
11604 if (doomed) {
11605 int res;
11606 res = dahdi_destroy_channel_bynum(doomed->channel);
11607 if (res != RESULT_SUCCESS) {
11608 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11609 }
11610 doomed = NULL;
11611 }
11612 if (!i) {
11613 break;
11614 }
11615
11616 if (thispass != lastpass) {
11617 if (!found && ((i == last) || ((i == iflist) && !last))) {
11618 last = i;
11619 if (last) {
11620 struct analog_pvt *analog_p = last->sig_pvt;
11621
11622 if (analog_p
11623 && !last->mwisendactive
11624 && (last->sig & __DAHDI_SIG_FXO)
11625 && !analog_p->fxsoffhookstate
11626 && !last->owner
11627 && !ast_strlen_zero(last->mailbox)
11628 && (thispass - analog_p->onhooktime > 3)) {
11629 res = has_voicemail(last);
11630 if (analog_p->msgstate != res) {
11631
11632 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11633 if (res2) {
11634
11635 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11636 }
11637
11638 if (mwi_send_init(last)) {
11639 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11640 }
11641 analog_p->msgstate = res;
11642 found ++;
11643 }
11644 }
11645 last = last->next;
11646 }
11647 }
11648 }
11649 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11650 if (i->radio && !i->owner)
11651 {
11652 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11653 if (res)
11654 {
11655 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11656
11657 ast_mutex_unlock(&iflock);
11658 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11659 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11660 else
11661 doomed = handle_init_event(i, res);
11662 ast_mutex_lock(&iflock);
11663 }
11664 continue;
11665 }
11666 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11667 if (pollres & POLLIN) {
11668 if (i->owner || i->subs[SUB_REAL].owner) {
11669 #ifdef HAVE_PRI
11670 if (!i->pri)
11671 #endif
11672 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11673 continue;
11674 }
11675 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11676 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11677 continue;
11678 }
11679 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11680 if (res > 0) {
11681 if (i->mwimonitor_fsk) {
11682 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11683 pthread_attr_t attr;
11684 pthread_t threadid;
11685 struct mwi_thread_data *mtd;
11686
11687 pthread_attr_init(&attr);
11688 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11689
11690 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11691 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11692 mtd->pvt = i;
11693 memcpy(mtd->buf, buf, res);
11694 mtd->len = res;
11695 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11696 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11697 ast_free(mtd);
11698 }
11699 i->mwimonitoractive = 1;
11700 }
11701 }
11702
11703 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11704 int energy;
11705 struct timeval now;
11706
11707
11708
11709 if (1 == i->dtmfcid_holdoff_state) {
11710 gettimeofday(&i->dtmfcid_delay, NULL);
11711 i->dtmfcid_holdoff_state = 2;
11712 } else if (2 == i->dtmfcid_holdoff_state) {
11713 gettimeofday(&now, NULL);
11714 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11715 i->dtmfcid_holdoff_state = 0;
11716 }
11717 } else {
11718 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11719 if (!i->mwisendactive && energy > dtmfcid_level) {
11720 pthread_t threadid;
11721 struct ast_channel *chan;
11722 ast_mutex_unlock(&iflock);
11723 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11724
11725 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11726 i->dtmfcid_holdoff_state = 1;
11727 } else {
11728 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11729 if (!chan) {
11730 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11731 } else {
11732 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11733 if (res) {
11734 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11735 } else {
11736 i->dtmfcid_holdoff_state = 1;
11737 }
11738 }
11739 }
11740 ast_mutex_lock(&iflock);
11741 }
11742 }
11743 }
11744 if (i->mwisendactive) {
11745 mwi_send_process_buffer(i, res);
11746 }
11747 } else {
11748 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11749 }
11750 }
11751 if (pollres & POLLPRI) {
11752 if (i->owner || i->subs[SUB_REAL].owner) {
11753 #ifdef HAVE_PRI
11754 if (!i->pri)
11755 #endif
11756 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11757 continue;
11758 }
11759 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11760 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11761
11762 ast_mutex_unlock(&iflock);
11763 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11764 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11765 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11766 else
11767 doomed = handle_init_event(i, res);
11768 }
11769 ast_mutex_lock(&iflock);
11770 }
11771 }
11772 }
11773 ast_mutex_unlock(&iflock);
11774 }
11775
11776 return NULL;
11777
11778 }
11779
11780 static int restart_monitor(void)
11781 {
11782
11783 if (monitor_thread == AST_PTHREADT_STOP)
11784 return 0;
11785 ast_mutex_lock(&monlock);
11786 if (monitor_thread == pthread_self()) {
11787 ast_mutex_unlock(&monlock);
11788 ast_log(LOG_WARNING, "Cannot kill myself\n");
11789 return -1;
11790 }
11791 if (monitor_thread != AST_PTHREADT_NULL) {
11792
11793 pthread_kill(monitor_thread, SIGURG);
11794 } else {
11795
11796 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11797 ast_mutex_unlock(&monlock);
11798 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11799 return -1;
11800 }
11801 }
11802 ast_mutex_unlock(&monlock);
11803 return 0;
11804 }
11805
11806 #if defined(HAVE_PRI)
11807 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11808 {
11809 int x;
11810 int trunkgroup;
11811
11812 trunkgroup = pris[*span].mastertrunkgroup;
11813 if (trunkgroup) {
11814
11815 for (x = 0; x < NUM_SPANS; x++) {
11816 if (pris[x].pri.trunkgroup == trunkgroup) {
11817 *span = x;
11818 return 0;
11819 }
11820 }
11821 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11822 *span = -1;
11823 } else {
11824 if (pris[*span].pri.trunkgroup) {
11825 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);
11826 *span = -1;
11827 } else if (pris[*span].mastertrunkgroup) {
11828 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11829 *span = -1;
11830 } else {
11831 if (si->totalchans == 31) {
11832
11833 pris[*span].dchannels[0] = 16 + offset;
11834 } else if (si->totalchans == 24) {
11835
11836 pris[*span].dchannels[0] = 24 + offset;
11837 } else if (si->totalchans == 3) {
11838
11839 pris[*span].dchannels[0] = 3 + offset;
11840 } else {
11841 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);
11842 *span = -1;
11843 return 0;
11844 }
11845 pris[*span].pri.span = *span + 1;
11846 }
11847 }
11848 return 0;
11849 }
11850 #endif
11851
11852 #if defined(HAVE_PRI)
11853 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11854 {
11855 struct dahdi_spaninfo si;
11856 struct dahdi_params p;
11857 int fd;
11858 int span;
11859 int ospan=0;
11860 int x,y;
11861 for (x = 0; x < NUM_SPANS; x++) {
11862 if (pris[x].pri.trunkgroup == trunkgroup) {
11863 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11864 return -1;
11865 }
11866 }
11867 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11868 if (!channels[y])
11869 break;
11870 memset(&si, 0, sizeof(si));
11871 memset(&p, 0, sizeof(p));
11872 fd = open("/dev/dahdi/channel", O_RDWR);
11873 if (fd < 0) {
11874 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11875 return -1;
11876 }
11877 x = channels[y];
11878 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11879 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11880 close(fd);
11881 return -1;
11882 }
11883 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11884 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11885 return -1;
11886 }
11887 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11888 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11889 close(fd);
11890 return -1;
11891 }
11892 span = p.spanno - 1;
11893 if (pris[span].pri.trunkgroup) {
11894 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11895 close(fd);
11896 return -1;
11897 }
11898 if (pris[span].pri.pvts[0]) {
11899 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11900 close(fd);
11901 return -1;
11902 }
11903 if (!y) {
11904 pris[span].pri.trunkgroup = trunkgroup;
11905 ospan = span;
11906 }
11907 pris[ospan].dchannels[y] = channels[y];
11908 pris[span].pri.span = span + 1;
11909 close(fd);
11910 }
11911 return 0;
11912 }
11913 #endif
11914
11915 #if defined(HAVE_PRI)
11916 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11917 {
11918 if (pris[span].mastertrunkgroup) {
11919 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);
11920 return -1;
11921 }
11922 pris[span].mastertrunkgroup = trunkgroup;
11923 pris[span].prilogicalspan = logicalspan;
11924 return 0;
11925 }
11926 #endif
11927
11928 #if defined(HAVE_SS7)
11929 static unsigned int parse_pointcode(const char *pcstring)
11930 {
11931 unsigned int code1, code2, code3;
11932 int numvals;
11933
11934 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11935 if (numvals == 1)
11936 return code1;
11937 if (numvals == 3)
11938 return (code1 << 16) | (code2 << 8) | code3;
11939
11940 return 0;
11941 }
11942 #endif
11943
11944 #if defined(HAVE_SS7)
11945 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11946 {
11947 if ((linkset < 0) || (linkset >= NUM_SPANS))
11948 return NULL;
11949 else
11950 return &linksets[linkset - 1];
11951 }
11952 #endif
11953
11954 #ifdef HAVE_OPENR2
11955 static void dahdi_r2_destroy_links(void)
11956 {
11957 int i = 0;
11958 if (!r2links) {
11959 return;
11960 }
11961 for (; i < r2links_count; i++) {
11962 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11963 pthread_cancel(r2links[i]->r2master);
11964 pthread_join(r2links[i]->r2master, NULL);
11965 openr2_context_delete(r2links[i]->protocol_context);
11966 }
11967 ast_free(r2links[i]);
11968 }
11969 ast_free(r2links);
11970 r2links = NULL;
11971 r2links_count = 0;
11972 }
11973
11974 #define R2_LINK_CAPACITY 10
11975 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11976 {
11977 struct dahdi_mfcr2 *new_r2link = NULL;
11978 struct dahdi_mfcr2 **new_r2links = NULL;
11979
11980
11981 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11982 new_r2link = ast_calloc(1, sizeof(**r2links));
11983 if (!new_r2link) {
11984 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11985 return NULL;
11986 }
11987 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11988 if (!new_r2links) {
11989 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11990 ast_free(new_r2link);
11991 return NULL;
11992 }
11993 r2links = new_r2links;
11994 new_r2link->r2master = AST_PTHREADT_NULL;
11995 r2links[r2links_count] = new_r2link;
11996 r2links_count++;
11997 ast_log(LOG_DEBUG, "Created new R2 link!\n");
11998 }
11999 return r2links[r2links_count - 1];
12000 }
12001
12002 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12003 {
12004 char tmplogdir[] = "/tmp";
12005 char logdir[OR2_MAX_PATH];
12006 int threshold = 0;
12007 int snres = 0;
12008 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12009 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12010 conf->mfcr2.max_dnis);
12011 if (!r2_link->protocol_context) {
12012 return -1;
12013 }
12014 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12015 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12016 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12017 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12018 #endif
12019 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12020 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12021 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12022 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12023 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12024 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12025 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12026 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12027 }
12028 } else {
12029 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12030 if (snres >= sizeof(logdir)) {
12031 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12032 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12033 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12034 }
12035 } else {
12036 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12037 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12038 }
12039 }
12040 }
12041 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12042 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12043 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12044 }
12045 }
12046 r2_link->monitored_count = 0;
12047 return 0;
12048 }
12049 #endif
12050
12051
12052
12053
12054
12055
12056 static int sigtype_to_signalling(int sigtype)
12057 {
12058 return sigtype;
12059 }
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12074 {
12075 struct stat stbuf;
12076 int num;
12077
12078 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12079 if (stat(path, &stbuf) < 0) {
12080 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12081 return -errno;
12082 }
12083 if (!S_ISCHR(stbuf.st_mode)) {
12084 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12085 return -EINVAL;
12086 }
12087 num = minor(stbuf.st_rdev);
12088 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12089 return num;
12090
12091 }
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12108 {
12109
12110 struct dahdi_pvt *tmp;
12111 char fn[80];
12112 struct dahdi_bufferinfo bi;
12113
12114 int res;
12115 int span = 0;
12116 int here = 0;
12117 int x;
12118 struct analog_pvt *analog_p = NULL;
12119 struct dahdi_params p;
12120 #if defined(HAVE_PRI)
12121 struct dahdi_spaninfo si;
12122 struct sig_pri_chan *pri_chan = NULL;
12123 #endif
12124 #if defined(HAVE_SS7)
12125 struct sig_ss7_chan *ss7_chan = NULL;
12126 #endif
12127
12128
12129 for (tmp = iflist; tmp; tmp = tmp->next) {
12130 if (!tmp->destroy) {
12131 if (tmp->channel == channel) {
12132
12133 here = 1;
12134 break;
12135 }
12136 if (tmp->channel > channel) {
12137
12138 tmp = NULL;
12139 break;
12140 }
12141 }
12142 }
12143
12144 if (!here && reloading != 1) {
12145 tmp = ast_calloc(1, sizeof(*tmp));
12146 if (!tmp) {
12147 return NULL;
12148 }
12149 tmp->cc_params = ast_cc_config_params_init();
12150 if (!tmp->cc_params) {
12151 ast_free(tmp);
12152 return NULL;
12153 }
12154 ast_mutex_init(&tmp->lock);
12155 ifcount++;
12156 for (x = 0; x < 3; x++)
12157 tmp->subs[x].dfd = -1;
12158 tmp->channel = channel;
12159 tmp->priindication_oob = conf->chan.priindication_oob;
12160 }
12161
12162 if (tmp) {
12163 int chan_sig = conf->chan.sig;
12164
12165
12166 if (reloading && tmp->vars) {
12167 ast_variables_destroy(tmp->vars);
12168 tmp->vars = NULL;
12169 }
12170
12171
12172 if (!here) {
12173
12174 if ((channel != CHAN_PSEUDO)) {
12175 int count = 0;
12176
12177 snprintf(fn, sizeof(fn), "%d", channel);
12178
12179 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12180 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12181 usleep(1);
12182 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12183 count++;
12184 }
12185
12186 if (tmp->subs[SUB_REAL].dfd < 0) {
12187 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);
12188 destroy_dahdi_pvt(tmp);
12189 return NULL;
12190 }
12191 memset(&p, 0, sizeof(p));
12192 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12193 if (res < 0) {
12194 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12195 destroy_dahdi_pvt(tmp);
12196 return NULL;
12197 }
12198 if (conf->is_sig_auto)
12199 chan_sig = sigtype_to_signalling(p.sigtype);
12200 if (p.sigtype != (chan_sig & 0x3ffff)) {
12201 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));
12202 destroy_dahdi_pvt(tmp);
12203 return NULL;
12204 }
12205 tmp->law_default = p.curlaw;
12206 tmp->law = p.curlaw;
12207 tmp->span = p.spanno;
12208 span = p.spanno - 1;
12209 } else {
12210 chan_sig = 0;
12211 }
12212 tmp->sig = chan_sig;
12213 tmp->outsigmod = conf->chan.outsigmod;
12214
12215 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12216 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12217 if (!analog_p) {
12218 destroy_dahdi_pvt(tmp);
12219 return NULL;
12220 }
12221 tmp->sig_pvt = analog_p;
12222 }
12223 #if defined(HAVE_SS7)
12224 if (chan_sig == SIG_SS7) {
12225 struct dahdi_ss7 *ss7;
12226 int clear = 0;
12227
12228 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12229 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12230 destroy_dahdi_pvt(tmp);
12231 return NULL;
12232 }
12233
12234 ss7 = ss7_resolve_linkset(cur_linkset);
12235 if (!ss7) {
12236 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12237 destroy_dahdi_pvt(tmp);
12238 return NULL;
12239 }
12240 ss7->ss7.span = cur_linkset;
12241 if (cur_cicbeginswith < 0) {
12242 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12243 destroy_dahdi_pvt(tmp);
12244 return NULL;
12245 }
12246 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12247 if (!ss7_chan) {
12248 destroy_dahdi_pvt(tmp);
12249 return NULL;
12250 }
12251 tmp->sig_pvt = ss7_chan;
12252 tmp->ss7 = &ss7->ss7;
12253
12254 ss7_chan->channel = tmp->channel;
12255 ss7_chan->cic = cur_cicbeginswith++;
12256
12257
12258 ss7_chan->dpc = cur_defaultdpc;
12259
12260 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12261
12262 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12263 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12264 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12265 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12266
12267 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12268 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12269 }
12270 #endif
12271 #ifdef HAVE_OPENR2
12272 if (chan_sig == SIG_MFCR2) {
12273 struct dahdi_mfcr2 *r2_link;
12274 r2_link = dahdi_r2_get_link();
12275 if (!r2_link) {
12276 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12277 destroy_dahdi_pvt(tmp);
12278 return NULL;
12279 }
12280 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12281 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12282 destroy_dahdi_pvt(tmp);
12283 return NULL;
12284 }
12285 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12286 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12287 destroy_dahdi_pvt(tmp);
12288 return NULL;
12289 }
12290 r2_link->pvts[r2_link->numchans++] = tmp;
12291 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12292 tmp->subs[SUB_REAL].dfd,
12293 NULL, NULL);
12294 if (!tmp->r2chan) {
12295 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12296 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12297 destroy_dahdi_pvt(tmp);
12298 return NULL;
12299 }
12300 tmp->mfcr2 = r2_link;
12301 if (conf->mfcr2.call_files) {
12302 openr2_chan_enable_call_files(tmp->r2chan);
12303 }
12304 openr2_chan_set_client_data(tmp->r2chan, tmp);
12305
12306 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12307 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12308 tmp->mfcr2_category = conf->mfcr2.category;
12309 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12310 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12311 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12312 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12313 tmp->mfcr2call = 0;
12314 tmp->mfcr2_dnis_index = 0;
12315 tmp->mfcr2_ani_index = 0;
12316 r2_link->monitored_count++;
12317 }
12318 #endif
12319 #ifdef HAVE_PRI
12320 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12321 int offset;
12322 int matchesdchan;
12323 int x,y;
12324 int myswitchtype = 0;
12325
12326 offset = 0;
12327 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12328 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12329 destroy_dahdi_pvt(tmp);
12330 return NULL;
12331 }
12332 if (span >= NUM_SPANS) {
12333 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12334 destroy_dahdi_pvt(tmp);
12335 return NULL;
12336 } else {
12337 si.spanno = 0;
12338 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12339 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12340 destroy_dahdi_pvt(tmp);
12341 return NULL;
12342 }
12343
12344 tmp->logicalspan = pris[span].prilogicalspan;
12345 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12346 if (span < 0) {
12347 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12348 destroy_dahdi_pvt(tmp);
12349 return NULL;
12350 }
12351 myswitchtype = conf->pri.pri.switchtype;
12352
12353 matchesdchan=0;
12354 for (x = 0; x < NUM_SPANS; x++) {
12355 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12356 if (pris[x].dchannels[y] == tmp->channel) {
12357 matchesdchan = 1;
12358 break;
12359 }
12360 }
12361 }
12362 if (!matchesdchan) {
12363 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12364 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12365 destroy_dahdi_pvt(tmp);
12366 return NULL;
12367 }
12368 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12369 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12370 destroy_dahdi_pvt(tmp);
12371 return NULL;
12372 }
12373 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12374 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));
12375 destroy_dahdi_pvt(tmp);
12376 return NULL;
12377 }
12378 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12379 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12380 destroy_dahdi_pvt(tmp);
12381 return NULL;
12382 }
12383 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12384 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12385 destroy_dahdi_pvt(tmp);
12386 return NULL;
12387 }
12388 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12389 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12390 destroy_dahdi_pvt(tmp);
12391 return NULL;
12392 }
12393 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12394 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12395 destroy_dahdi_pvt(tmp);
12396 return NULL;
12397 }
12398 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12399 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12400 pris[span].pri.trunkgroup);
12401 destroy_dahdi_pvt(tmp);
12402 return NULL;
12403 }
12404
12405 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12406 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12407 if (!pri_chan) {
12408 destroy_dahdi_pvt(tmp);
12409 return NULL;
12410 }
12411 tmp->sig_pvt = pri_chan;
12412 tmp->pri = &pris[span].pri;
12413
12414 tmp->priexclusive = conf->chan.priexclusive;
12415
12416 if (!tmp->pri->cc_params) {
12417 tmp->pri->cc_params = ast_cc_config_params_init();
12418 if (!tmp->pri->cc_params) {
12419 destroy_dahdi_pvt(tmp);
12420 return NULL;
12421 }
12422 }
12423 ast_cc_copy_config_params(tmp->pri->cc_params,
12424 conf->chan.cc_params);
12425
12426 pris[span].pri.sig = chan_sig;
12427 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12428 pris[span].pri.switchtype = myswitchtype;
12429 pris[span].pri.nsf = conf->pri.pri.nsf;
12430 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12431 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12432 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12433 pris[span].pri.minunused = conf->pri.pri.minunused;
12434 pris[span].pri.minidle = conf->pri.pri.minidle;
12435 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12436 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12437 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12438 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12439 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12440 #endif
12441 #ifdef HAVE_PRI_INBANDDISCONNECT
12442 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12443 #endif
12444 #if defined(HAVE_PRI_CALL_HOLD)
12445 pris[span].pri.hold_disconnect_transfer =
12446 conf->pri.pri.hold_disconnect_transfer;
12447 #endif
12448 #if defined(HAVE_PRI_CCSS)
12449 pris[span].pri.cc_ptmp_recall_mode =
12450 conf->pri.pri.cc_ptmp_recall_mode;
12451 pris[span].pri.cc_qsig_signaling_link_req =
12452 conf->pri.pri.cc_qsig_signaling_link_req;
12453 pris[span].pri.cc_qsig_signaling_link_rsp =
12454 conf->pri.pri.cc_qsig_signaling_link_rsp;
12455 #endif
12456 #if defined(HAVE_PRI_CALL_WAITING)
12457 pris[span].pri.max_call_waiting_calls =
12458 conf->pri.pri.max_call_waiting_calls;
12459 pris[span].pri.allow_call_waiting_calls =
12460 conf->pri.pri.allow_call_waiting_calls;
12461 #endif
12462 pris[span].pri.transfer = conf->chan.transfer;
12463 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12464 #if defined(HAVE_PRI_L2_PERSISTENCE)
12465 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12466 #endif
12467 #if defined(HAVE_PRI_AOC_EVENTS)
12468 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12469 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12470 #endif
12471 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12472 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12473 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12474 #if defined(HAVE_PRI_MWI)
12475 ast_copy_string(pris[span].pri.mwi_mailboxes,
12476 conf->pri.pri.mwi_mailboxes,
12477 sizeof(pris[span].pri.mwi_mailboxes));
12478 #endif
12479 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12480 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12481 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12482 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12483 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12484 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12485 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12486 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12487
12488 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12489 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12490 }
12491
12492 #if defined(HAVE_PRI_CALL_WAITING)
12493
12494 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12495 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12496 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12497 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12498 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12499 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12500 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12501 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12502 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12503 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12504 #endif
12505 } else {
12506 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12507 destroy_dahdi_pvt(tmp);
12508 return NULL;
12509 }
12510 }
12511 }
12512 #endif
12513 } else {
12514
12515 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));
12516 chan_sig = tmp->sig;
12517 if (tmp->subs[SUB_REAL].dfd > -1) {
12518 memset(&p, 0, sizeof(p));
12519 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12520 }
12521 }
12522
12523 switch (chan_sig) {
12524 case SIG_FXSKS:
12525 case SIG_FXSLS:
12526 case SIG_EM:
12527 case SIG_EM_E1:
12528 case SIG_EMWINK:
12529 case SIG_FEATD:
12530 case SIG_FEATDMF:
12531 case SIG_FEATDMF_TA:
12532 case SIG_FEATB:
12533 case SIG_E911:
12534 case SIG_SF:
12535 case SIG_SFWINK:
12536 case SIG_FGC_CAMA:
12537 case SIG_FGC_CAMAMF:
12538 case SIG_SF_FEATD:
12539 case SIG_SF_FEATDMF:
12540 case SIG_SF_FEATB:
12541 p.starttime = 250;
12542 break;
12543 }
12544
12545 if (tmp->radio) {
12546
12547 p.channo = channel;
12548 p.rxwinktime = 1;
12549 p.rxflashtime = 1;
12550 p.starttime = 1;
12551 p.debouncetime = 5;
12552 } else {
12553 p.channo = channel;
12554
12555 if (conf->timing.prewinktime >= 0)
12556 p.prewinktime = conf->timing.prewinktime;
12557 if (conf->timing.preflashtime >= 0)
12558 p.preflashtime = conf->timing.preflashtime;
12559 if (conf->timing.winktime >= 0)
12560 p.winktime = conf->timing.winktime;
12561 if (conf->timing.flashtime >= 0)
12562 p.flashtime = conf->timing.flashtime;
12563 if (conf->timing.starttime >= 0)
12564 p.starttime = conf->timing.starttime;
12565 if (conf->timing.rxwinktime >= 0)
12566 p.rxwinktime = conf->timing.rxwinktime;
12567 if (conf->timing.rxflashtime >= 0)
12568 p.rxflashtime = conf->timing.rxflashtime;
12569 if (conf->timing.debouncetime >= 0)
12570 p.debouncetime = conf->timing.debouncetime;
12571 }
12572
12573
12574 if (tmp->subs[SUB_REAL].dfd >= 0)
12575 {
12576 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12577 if (res < 0) {
12578 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12579 destroy_dahdi_pvt(tmp);
12580 return NULL;
12581 }
12582 }
12583 #if 1
12584 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12585 memset(&bi, 0, sizeof(bi));
12586 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12587 if (!res) {
12588 bi.txbufpolicy = conf->chan.buf_policy;
12589 bi.rxbufpolicy = conf->chan.buf_policy;
12590 bi.numbufs = conf->chan.buf_no;
12591 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12592 if (res < 0) {
12593 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12594 }
12595 } else {
12596 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12597 }
12598 tmp->buf_policy = conf->chan.buf_policy;
12599 tmp->buf_no = conf->chan.buf_no;
12600 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12601 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12602 tmp->faxbuf_no = conf->chan.faxbuf_no;
12603
12604
12605
12606
12607 tmp->bufsize = bi.bufsize;
12608 }
12609 #endif
12610 tmp->immediate = conf->chan.immediate;
12611 tmp->transfertobusy = conf->chan.transfertobusy;
12612 if (chan_sig & __DAHDI_SIG_FXS) {
12613 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12614 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12615 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12616 }
12617 tmp->ringt_base = ringt_base;
12618 tmp->firstradio = 0;
12619 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12620 tmp->permcallwaiting = conf->chan.callwaiting;
12621 else
12622 tmp->permcallwaiting = 0;
12623
12624 tmp->destroy = 0;
12625 tmp->drings = conf->chan.drings;
12626
12627
12628 if (tmp->drings.ringnum[0].range == 0)
12629 tmp->drings.ringnum[0].range = 10;
12630 if (tmp->drings.ringnum[1].range == 0)
12631 tmp->drings.ringnum[1].range = 10;
12632 if (tmp->drings.ringnum[2].range == 0)
12633 tmp->drings.ringnum[2].range = 10;
12634
12635 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12636 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12637 tmp->threewaycalling = conf->chan.threewaycalling;
12638 tmp->adsi = conf->chan.adsi;
12639 tmp->use_smdi = conf->chan.use_smdi;
12640 tmp->permhidecallerid = conf->chan.hidecallerid;
12641 tmp->hidecalleridname = conf->chan.hidecalleridname;
12642 tmp->callreturn = conf->chan.callreturn;
12643 tmp->echocancel = conf->chan.echocancel;
12644 tmp->echotraining = conf->chan.echotraining;
12645 tmp->pulse = conf->chan.pulse;
12646 if (tmp->echocancel.head.tap_length) {
12647 tmp->echocanbridged = conf->chan.echocanbridged;
12648 } else {
12649 if (conf->chan.echocanbridged)
12650 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12651 tmp->echocanbridged = 0;
12652 }
12653 tmp->busydetect = conf->chan.busydetect;
12654 tmp->busycount = conf->chan.busycount;
12655 tmp->busy_tonelength = conf->chan.busy_tonelength;
12656 tmp->busy_quietlength = conf->chan.busy_quietlength;
12657 tmp->callprogress = conf->chan.callprogress;
12658 tmp->waitfordialtone = conf->chan.waitfordialtone;
12659 tmp->cancallforward = conf->chan.cancallforward;
12660 tmp->dtmfrelax = conf->chan.dtmfrelax;
12661 tmp->callwaiting = tmp->permcallwaiting;
12662 tmp->hidecallerid = tmp->permhidecallerid;
12663 tmp->channel = channel;
12664 tmp->stripmsd = conf->chan.stripmsd;
12665 tmp->use_callerid = conf->chan.use_callerid;
12666 tmp->cid_signalling = conf->chan.cid_signalling;
12667 tmp->cid_start = conf->chan.cid_start;
12668 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12669 tmp->restrictcid = conf->chan.restrictcid;
12670 tmp->use_callingpres = conf->chan.use_callingpres;
12671 if (tmp->usedistinctiveringdetection) {
12672 if (!tmp->use_callerid) {
12673 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12674 tmp->use_callerid = 1;
12675 }
12676 }
12677
12678 if (tmp->cid_signalling == CID_SIG_SMDI) {
12679 if (!tmp->use_smdi) {
12680 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12681 tmp->use_smdi = 1;
12682 }
12683 }
12684 if (tmp->use_smdi) {
12685 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12686 if (!(tmp->smdi_iface)) {
12687 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12688 tmp->use_smdi = 0;
12689 }
12690 }
12691
12692 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12693 tmp->amaflags = conf->chan.amaflags;
12694 if (!here) {
12695 tmp->confno = -1;
12696 tmp->propconfno = -1;
12697 }
12698 tmp->canpark = conf->chan.canpark;
12699 tmp->transfer = conf->chan.transfer;
12700 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12701 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12702 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12703 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12704 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12705 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12706 tmp->cid_ton = 0;
12707 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12708 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12709 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12710 } else {
12711 tmp->cid_num[0] = '\0';
12712 tmp->cid_name[0] = '\0';
12713 }
12714 #if defined(HAVE_PRI)
12715 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12716 tmp->cid_tag[0] = '\0';
12717 } else
12718 #endif
12719 {
12720 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12721 }
12722 tmp->cid_subaddr[0] = '\0';
12723 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12724 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12725 char *mailbox, *context;
12726 mailbox = context = ast_strdupa(tmp->mailbox);
12727 strsep(&context, "@");
12728 if (ast_strlen_zero(context))
12729 context = "default";
12730 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12731 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12732 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12733 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12734 AST_EVENT_IE_END);
12735 }
12736 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12737 tmp->mwisend_setting = conf->chan.mwisend_setting;
12738 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12739 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12740 #endif
12741
12742 tmp->group = conf->chan.group;
12743 tmp->callgroup = conf->chan.callgroup;
12744 tmp->pickupgroup= conf->chan.pickupgroup;
12745 if (conf->chan.vars) {
12746 struct ast_variable *v, *tmpvar;
12747 for (v = conf->chan.vars ; v ; v = v->next) {
12748 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12749 tmpvar->next = tmp->vars;
12750 tmp->vars = tmpvar;
12751 }
12752 }
12753 }
12754 tmp->cid_rxgain = conf->chan.cid_rxgain;
12755 tmp->rxgain = conf->chan.rxgain;
12756 tmp->txgain = conf->chan.txgain;
12757 tmp->txdrc = conf->chan.txdrc;
12758 tmp->rxdrc = conf->chan.rxdrc;
12759 tmp->tonezone = conf->chan.tonezone;
12760 if (tmp->subs[SUB_REAL].dfd > -1) {
12761 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12762 if (tmp->dsp)
12763 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12764 update_conf(tmp);
12765 if (!here) {
12766 switch (chan_sig) {
12767 case SIG_PRI_LIB_HANDLE_CASES:
12768 case SIG_SS7:
12769 case SIG_MFCR2:
12770 break;
12771 default:
12772
12773 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12774 break;
12775 }
12776 }
12777 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12778 #ifdef HAVE_PRI
12779 memset(&si, 0, sizeof(si));
12780 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12781 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12782 destroy_dahdi_pvt(tmp);
12783 return NULL;
12784 }
12785 #endif
12786 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12787
12788 switch (tmp->sig) {
12789 #ifdef HAVE_PRI
12790 case SIG_PRI_LIB_HANDLE_CASES:
12791 sig_pri_set_alarm(tmp->sig_pvt, !si.alarms);
12792 break;
12793 #endif
12794 #if defined(HAVE_SS7)
12795 case SIG_SS7:
12796 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12797 break;
12798 #endif
12799 default:
12800
12801 analog_p = tmp->sig_pvt;
12802 if (analog_p) {
12803 analog_p->inalarm = 1;
12804 }
12805 tmp->inalarm = 1;
12806 break;
12807 }
12808 handle_alarms(tmp, res);
12809 }
12810 }
12811
12812 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12813 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12814 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12815 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12816 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12817
12818 if (!here) {
12819 tmp->locallyblocked = 0;
12820 tmp->remotelyblocked = 0;
12821 switch (tmp->sig) {
12822 #if defined(HAVE_PRI)
12823 case SIG_PRI_LIB_HANDLE_CASES:
12824 tmp->inservice = 1;
12825 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12826 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12827 if (chan_sig == SIG_PRI) {
12828 char db_chan_name[20];
12829 char db_answer[5];
12830
12831
12832
12833
12834
12835 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12836 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12837 unsigned *why;
12838
12839 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12840 if (tmp->pri->enable_service_message_support) {
12841 char state;
12842
12843 sscanf(db_answer, "%1c:%30u", &state, why);
12844
12845
12846 *why &= (SRVST_NEAREND | SRVST_FAREND);
12847 }
12848 if (!*why) {
12849 ast_db_del(db_chan_name, SRVST_DBKEY);
12850 }
12851 }
12852 }
12853 #endif
12854 break;
12855 #endif
12856 #if defined(HAVE_SS7)
12857 case SIG_SS7:
12858 tmp->inservice = 0;
12859 break;
12860 #endif
12861 default:
12862
12863 tmp->inservice = 1;
12864 break;
12865 }
12866 }
12867
12868 switch (tmp->sig) {
12869 #if defined(HAVE_PRI)
12870 case SIG_PRI_LIB_HANDLE_CASES:
12871 if (pri_chan) {
12872 pri_chan->channel = tmp->channel;
12873 pri_chan->hidecallerid = tmp->hidecallerid;
12874 pri_chan->hidecalleridname = tmp->hidecalleridname;
12875 pri_chan->immediate = tmp->immediate;
12876 pri_chan->inalarm = tmp->inalarm;
12877 pri_chan->priexclusive = tmp->priexclusive;
12878 pri_chan->priindication_oob = tmp->priindication_oob;
12879 pri_chan->use_callerid = tmp->use_callerid;
12880 pri_chan->use_callingpres = tmp->use_callingpres;
12881 ast_copy_string(pri_chan->context, tmp->context,
12882 sizeof(pri_chan->context));
12883 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12884 sizeof(pri_chan->mohinterpret));
12885 pri_chan->stripmsd = tmp->stripmsd;
12886 }
12887 break;
12888 #endif
12889 #if defined(HAVE_SS7)
12890 case SIG_SS7:
12891 if (ss7_chan) {
12892 ss7_chan->inalarm = tmp->inalarm;
12893
12894 ss7_chan->stripmsd = tmp->stripmsd;
12895 ss7_chan->hidecallerid = tmp->hidecallerid;
12896 ss7_chan->use_callerid = tmp->use_callerid;
12897 ss7_chan->use_callingpres = tmp->use_callingpres;
12898 ss7_chan->immediate = tmp->immediate;
12899 ss7_chan->locallyblocked = tmp->locallyblocked;
12900 ss7_chan->remotelyblocked = tmp->remotelyblocked;
12901 ast_copy_string(ss7_chan->context, tmp->context,
12902 sizeof(ss7_chan->context));
12903 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12904 sizeof(ss7_chan->mohinterpret));
12905 }
12906 break;
12907 #endif
12908 default:
12909
12910 analog_p = tmp->sig_pvt;
12911 if (analog_p) {
12912 analog_p->channel = tmp->channel;
12913 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12914 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12915 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12916 analog_p->permcallwaiting = conf->chan.callwaiting;
12917 analog_p->callreturn = conf->chan.callreturn;
12918 analog_p->cancallforward = conf->chan.cancallforward;
12919 analog_p->canpark = conf->chan.canpark;
12920 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12921 analog_p->immediate = conf->chan.immediate;
12922 analog_p->permhidecallerid = conf->chan.permhidecallerid;
12923 analog_p->pulse = conf->chan.pulse;
12924 analog_p->threewaycalling = conf->chan.threewaycalling;
12925 analog_p->transfer = conf->chan.transfer;
12926 analog_p->transfertobusy = conf->chan.transfertobusy;
12927 analog_p->use_callerid = tmp->use_callerid;
12928 analog_p->use_smdi = tmp->use_smdi;
12929 analog_p->smdi_iface = tmp->smdi_iface;
12930 analog_p->outsigmod = ANALOG_SIG_NONE;
12931 analog_p->echotraining = conf->chan.echotraining;
12932 analog_p->cid_signalling = conf->chan.cid_signalling;
12933 analog_p->stripmsd = conf->chan.stripmsd;
12934 switch (conf->chan.cid_start) {
12935 case CID_START_POLARITY:
12936 analog_p->cid_start = ANALOG_CID_START_POLARITY;
12937 break;
12938 case CID_START_POLARITY_IN:
12939 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12940 break;
12941 case CID_START_DTMF_NOALERT:
12942 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12943 break;
12944 default:
12945 analog_p->cid_start = ANALOG_CID_START_RING;
12946 break;
12947 }
12948 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12949 analog_p->ringt = conf->chan.ringt;
12950 analog_p->ringt_base = ringt_base;
12951 analog_p->chan_tech = &dahdi_tech;
12952 analog_p->onhooktime = time(NULL);
12953 if (chan_sig & __DAHDI_SIG_FXO) {
12954 memset(&p, 0, sizeof(p));
12955 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12956 if (!res) {
12957 analog_p->fxsoffhookstate = p.rxisoffhook;
12958 }
12959 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12960 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12961 #endif
12962 }
12963 analog_p->msgstate = -1;
12964
12965 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12966 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12967 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12968
12969 analog_config_complete(analog_p);
12970 }
12971 break;
12972 }
12973 #if defined(HAVE_PRI)
12974 if (tmp->channel == CHAN_PSEUDO) {
12975
12976
12977
12978
12979 dahdi_pseudo_parms.buf_no = tmp->buf_no;
12980 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12981 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12982 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12983 }
12984 #endif
12985 }
12986 if (tmp && !here) {
12987
12988 dahdi_iflist_insert(tmp);
12989 }
12990 return tmp;
12991 }
12992
12993 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
12994 {
12995 #if defined(HAVE_PRI)
12996 if (0 < span) {
12997
12998 if (!p->pri || p->pri->span != span) {
12999 return 0;
13000 }
13001 if (!groupmatch && channelmatch == -1) {
13002
13003 *groupmatched = 1;
13004 return 1;
13005 }
13006 }
13007 #endif
13008
13009 if (groupmatch) {
13010 if ((p->group & groupmatch) != groupmatch)
13011
13012 return 0;
13013 *groupmatched = 1;
13014 }
13015
13016 if (channelmatch != -1) {
13017 if (p->channel != channelmatch)
13018
13019 return 0;
13020 *channelmatched = 1;
13021 }
13022
13023 return 1;
13024 }
13025
13026 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13027 {
13028 struct dahdi_pvt *p = *pvt;
13029
13030 if (p->inalarm)
13031 return 0;
13032
13033 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13034 return analog_available(p->sig_pvt);
13035
13036 switch (p->sig) {
13037 #if defined(HAVE_PRI)
13038 case SIG_PRI_LIB_HANDLE_CASES:
13039 {
13040 struct sig_pri_chan *pvt_chan;
13041 int res;
13042
13043 pvt_chan = p->sig_pvt;
13044 res = sig_pri_available(&pvt_chan, is_specific_channel);
13045 *pvt = pvt_chan->chan_pvt;
13046 return res;
13047 }
13048 #endif
13049 #if defined(HAVE_SS7)
13050 case SIG_SS7:
13051 return sig_ss7_available(p->sig_pvt);
13052 #endif
13053 default:
13054 break;
13055 }
13056
13057 if (p->locallyblocked || p->remotelyblocked) {
13058 return 0;
13059 }
13060
13061
13062 if (!p->owner) {
13063 #ifdef HAVE_OPENR2
13064
13065 if (p->mfcr2) {
13066 if (p->mfcr2call) {
13067 return 0;
13068 } else {
13069 return 1;
13070 }
13071 }
13072 #endif
13073 return 1;
13074 }
13075
13076 return 0;
13077 }
13078
13079 #if defined(HAVE_PRI)
13080 #if defined(HAVE_PRI_CALL_WAITING)
13081
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13094 {
13095 struct dahdi_pvt *pvt = priv;
13096
13097 pvt->stripmsd = pri->ch_cfg.stripmsd;
13098 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13099 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13100 pvt->immediate = pri->ch_cfg.immediate;
13101 pvt->priexclusive = pri->ch_cfg.priexclusive;
13102 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13103 pvt->use_callerid = pri->ch_cfg.use_callerid;
13104 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13105 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13106 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13107 }
13108 #endif
13109 #endif
13110
13111 #if defined(HAVE_PRI)
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13125 {
13126 int pvt_idx;
13127 int res;
13128 unsigned idx;
13129 struct dahdi_pvt *pvt;
13130 struct sig_pri_chan *chan;
13131 struct dahdi_bufferinfo bi;
13132
13133 static int nobch_channel = CHAN_PSEUDO;
13134
13135
13136 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13137 if (!pri->pvts[pvt_idx]) {
13138 break;
13139 }
13140 }
13141 if (pri->numchans == pvt_idx) {
13142 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13143 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13144 return -1;
13145 }
13146
13147
13148 pri->pvts[pvt_idx] = NULL;
13149 ++pri->numchans;
13150 }
13151
13152 pvt = ast_calloc(1, sizeof(*pvt));
13153 if (!pvt) {
13154 return -1;
13155 }
13156 pvt->cc_params = ast_cc_config_params_init();
13157 if (!pvt->cc_params) {
13158 ast_free(pvt);
13159 return -1;
13160 }
13161 ast_mutex_init(&pvt->lock);
13162 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13163 pvt->subs[idx].dfd = -1;
13164 }
13165 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13166 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13167 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13168 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13169
13170 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13171 if (!chan) {
13172 destroy_dahdi_pvt(pvt);
13173 return -1;
13174 }
13175 chan->no_b_channel = 1;
13176
13177
13178
13179
13180
13181
13182 pvt->law_default = DAHDI_LAW_ALAW;
13183
13184 pvt->sig = pri->sig;
13185 pvt->outsigmod = -1;
13186 pvt->pri = pri;
13187 pvt->sig_pvt = chan;
13188 pri->pvts[pvt_idx] = chan;
13189
13190 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13191 if (pvt->subs[SUB_REAL].dfd < 0) {
13192 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13193 strerror(errno));
13194 destroy_dahdi_pvt(pvt);
13195 return -1;
13196 }
13197 memset(&bi, 0, sizeof(bi));
13198 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13199 if (!res) {
13200 pvt->bufsize = bi.bufsize;
13201 bi.txbufpolicy = pvt->buf_policy;
13202 bi.rxbufpolicy = pvt->buf_policy;
13203 bi.numbufs = pvt->buf_no;
13204 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13205 if (res < 0) {
13206 ast_log(LOG_WARNING,
13207 "Unable to set buffer policy on no B channel interface: %s\n",
13208 strerror(errno));
13209 }
13210 } else
13211 ast_log(LOG_WARNING,
13212 "Unable to check buffer policy on no B channel interface: %s\n",
13213 strerror(errno));
13214
13215 --nobch_channel;
13216 if (CHAN_PSEUDO < nobch_channel) {
13217 nobch_channel = CHAN_PSEUDO - 1;
13218 }
13219 pvt->channel = nobch_channel;
13220 pvt->span = pri->span;
13221 chan->channel = pvt->channel;
13222
13223 dahdi_nobch_insert(pri, pvt);
13224
13225 return pvt_idx;
13226 }
13227 #endif
13228
13229
13230
13231
13232
13233
13234 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13235 {
13236 struct dahdi_pvt *p;
13237 struct dahdi_bufferinfo bi;
13238 int res;
13239
13240 p = ast_malloc(sizeof(*p));
13241 if (!p) {
13242 return NULL;
13243 }
13244 *p = *src;
13245
13246
13247 p->cc_params = ast_cc_config_params_init();
13248 if (!p->cc_params) {
13249 ast_free(p);
13250 return NULL;
13251 }
13252 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13253
13254 p->which_iflist = DAHDI_IFLIST_NONE;
13255 p->next = NULL;
13256 p->prev = NULL;
13257 ast_mutex_init(&p->lock);
13258 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13259 if (p->subs[SUB_REAL].dfd < 0) {
13260 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13261 destroy_dahdi_pvt(p);
13262 return NULL;
13263 }
13264 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13265 if (!res) {
13266 bi.txbufpolicy = src->buf_policy;
13267 bi.rxbufpolicy = src->buf_policy;
13268 bi.numbufs = src->buf_no;
13269 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13270 if (res < 0) {
13271 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13272 }
13273 } else
13274 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13275 p->destroy = 1;
13276 dahdi_iflist_insert(p);
13277 return p;
13278 }
13279
13280 struct dahdi_starting_point {
13281
13282 ast_group_t groupmatch;
13283
13284 int channelmatch;
13285
13286 int rr_starting_point;
13287
13288 int span;
13289
13290 int cadance;
13291
13292 char opt;
13293
13294 char backwards;
13295
13296 char roundrobin;
13297 };
13298 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13299 {
13300 char *dest;
13301 char *s;
13302 int x;
13303 int res = 0;
13304 struct dahdi_pvt *p;
13305 char *subdir = NULL;
13306 AST_DECLARE_APP_ARGS(args,
13307 AST_APP_ARG(group);
13308
13309
13310 AST_APP_ARG(other);
13311 );
13312
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336 if (data) {
13337 dest = ast_strdupa(data);
13338 } else {
13339 ast_log(LOG_WARNING, "Channel requested with no data\n");
13340 return NULL;
13341 }
13342 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13343 if (!args.argc || ast_strlen_zero(args.group)) {
13344 ast_log(LOG_WARNING, "No channel/group specified\n");
13345 return NULL;
13346 }
13347
13348
13349 memset(param, 0, sizeof(*param));
13350 param->channelmatch = -1;
13351
13352 if (strchr(args.group, '!') != NULL) {
13353 char *prev = args.group;
13354 while ((s = strchr(prev, '!')) != NULL) {
13355 *s++ = '/';
13356 prev = s;
13357 }
13358 *(prev - 1) = '\0';
13359 subdir = args.group;
13360 args.group = prev;
13361 } else if (args.group[0] == 'i') {
13362
13363 res = sscanf(args.group + 1, "%30d", &x);
13364 if (res < 1) {
13365 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13366 return NULL;
13367 }
13368 param->span = x;
13369
13370
13371 s = strchr(args.group, '-');
13372 if (!s) {
13373
13374 return iflist;
13375 }
13376 args.group = s + 1;
13377 res = 0;
13378 }
13379 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13380
13381 s = args.group + 1;
13382 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13383 if (res < 1) {
13384 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13385 return NULL;
13386 }
13387 param->groupmatch = ((ast_group_t) 1 << x);
13388
13389 if (toupper(args.group[0]) == 'G') {
13390 if (args.group[0] == 'G') {
13391 param->backwards = 1;
13392 p = ifend;
13393 } else
13394 p = iflist;
13395 } else {
13396 if (ARRAY_LEN(round_robin) <= x) {
13397 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13398 x, data);
13399 return NULL;
13400 }
13401 if (args.group[0] == 'R') {
13402 param->backwards = 1;
13403 p = round_robin[x] ? round_robin[x]->prev : ifend;
13404 if (!p)
13405 p = ifend;
13406 } else {
13407 p = round_robin[x] ? round_robin[x]->next : iflist;
13408 if (!p)
13409 p = iflist;
13410 }
13411 param->roundrobin = 1;
13412 param->rr_starting_point = x;
13413 }
13414 } else {
13415 s = args.group;
13416 if (!strcasecmp(s, "pseudo")) {
13417
13418 x = CHAN_PSEUDO;
13419 param->channelmatch = x;
13420 } else {
13421 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13422 if (res < 1) {
13423 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13424 return NULL;
13425 } else {
13426 param->channelmatch = x;
13427 }
13428 }
13429 if (subdir) {
13430 char path[PATH_MAX];
13431 struct stat stbuf;
13432
13433 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13434 subdir, param->channelmatch);
13435 if (stat(path, &stbuf) < 0) {
13436 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13437 path, strerror(errno));
13438 return NULL;
13439 }
13440 if (!S_ISCHR(stbuf.st_mode)) {
13441 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13442 path);
13443 return NULL;
13444 }
13445 param->channelmatch = minor(stbuf.st_rdev);
13446 }
13447
13448 p = iflist;
13449 }
13450
13451 if (param->opt == 'r' && res < 3) {
13452 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13453 param->opt = '\0';
13454 }
13455
13456 return p;
13457 }
13458
13459 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13460 {
13461 int callwait = 0;
13462 struct dahdi_pvt *p;
13463 struct ast_channel *tmp = NULL;
13464 struct dahdi_pvt *exitpvt;
13465 int channelmatched = 0;
13466 int groupmatched = 0;
13467 int transcapdigital = 0;
13468 struct dahdi_starting_point start;
13469
13470 ast_mutex_lock(&iflock);
13471 p = determine_starting_point(data, &start);
13472 if (!p) {
13473
13474 ast_mutex_unlock(&iflock);
13475 return NULL;
13476 }
13477
13478
13479 exitpvt = p;
13480 while (p && !tmp) {
13481 if (start.roundrobin)
13482 round_robin[start.rr_starting_point] = p;
13483
13484 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13485 && available(&p, channelmatched)) {
13486 ast_debug(1, "Using channel %d\n", p->channel);
13487
13488 callwait = (p->owner != NULL);
13489 #ifdef HAVE_OPENR2
13490 if (p->mfcr2) {
13491 ast_mutex_lock(&p->lock);
13492 if (p->mfcr2call) {
13493 ast_mutex_unlock(&p->lock);
13494 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13495 goto next;
13496 }
13497 p->mfcr2call = 1;
13498 ast_mutex_unlock(&p->lock);
13499 }
13500 #endif
13501 if (p->channel == CHAN_PSEUDO) {
13502 p = duplicate_pseudo(p);
13503 if (!p) {
13504 break;
13505 }
13506 }
13507
13508 p->distinctivering = 0;
13509
13510 switch (start.opt) {
13511 case '\0':
13512
13513 break;
13514 case 'c':
13515
13516 p->confirmanswer = 1;
13517 break;
13518 case 'r':
13519
13520 p->distinctivering = start.cadance;
13521 break;
13522 case 'd':
13523
13524 transcapdigital = AST_TRANS_CAP_DIGITAL;
13525 break;
13526 default:
13527 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13528 break;
13529 }
13530
13531 p->outgoing = 1;
13532 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13533 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13534 #ifdef HAVE_PRI
13535 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13536
13537
13538
13539
13540
13541 ast_mutex_lock(&p->lock);
13542 ast_mutex_unlock(&p->lock);
13543
13544 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13545 sizeof(p->dnid));
13546 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13547 #endif
13548 #if defined(HAVE_SS7)
13549 } else if (p->sig == SIG_SS7) {
13550 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13551 #endif
13552 } else {
13553 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13554 }
13555 if (!tmp) {
13556 p->outgoing = 0;
13557 #if defined(HAVE_PRI)
13558 switch (p->sig) {
13559 case SIG_PRI_LIB_HANDLE_CASES:
13560 #if defined(HAVE_PRI_CALL_WAITING)
13561 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13562 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13563 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13564 }
13565 #endif
13566
13567
13568
13569
13570 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13571 break;
13572 default:
13573 break;
13574 }
13575 #endif
13576 } else {
13577 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13578 }
13579 break;
13580 }
13581 #ifdef HAVE_OPENR2
13582 next:
13583 #endif
13584 if (start.backwards) {
13585 p = p->prev;
13586 if (!p)
13587 p = ifend;
13588 } else {
13589 p = p->next;
13590 if (!p)
13591 p = iflist;
13592 }
13593
13594 if (p == exitpvt)
13595 break;
13596 }
13597 ast_mutex_unlock(&iflock);
13598 restart_monitor();
13599 if (cause && !tmp) {
13600 if (callwait || channelmatched) {
13601 *cause = AST_CAUSE_BUSY;
13602 } else if (groupmatched) {
13603 *cause = AST_CAUSE_CONGESTION;
13604 } else {
13605
13606
13607
13608
13609 }
13610 }
13611
13612 return tmp;
13613 }
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624
13625 static int dahdi_devicestate(void *data)
13626 {
13627 #if defined(HAVE_PRI)
13628 char *device;
13629 unsigned span;
13630 int res;
13631
13632 device = data;
13633
13634 if (*device != 'I') {
13635
13636 return AST_DEVICE_UNKNOWN;
13637 }
13638 res = sscanf(device, "I%30u", &span);
13639 if (res != 1 || !span || NUM_SPANS < span) {
13640
13641 return AST_DEVICE_UNKNOWN;
13642 }
13643 device = strchr(device, '/');
13644 if (!device) {
13645
13646 return AST_DEVICE_UNKNOWN;
13647 }
13648
13649
13650
13651
13652
13653 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13654 ++device;
13655 if (!strcmp(device, "congestion"))
13656 #endif
13657 {
13658 return pris[span - 1].pri.congestion_devstate;
13659 }
13660 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13661 else if (!strcmp(device, "threshold")) {
13662 return pris[span - 1].pri.threshold_devstate;
13663 }
13664 return AST_DEVICE_UNKNOWN;
13665 #endif
13666 #else
13667 return AST_DEVICE_UNKNOWN;
13668 #endif
13669 }
13670
13671
13672
13673
13674
13675
13676
13677
13678
13679
13680
13681
13682
13683
13684
13685
13686
13687 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13688 {
13689 struct dahdi_pvt *p;
13690 struct dahdi_pvt *exitpvt;
13691 struct dahdi_starting_point start;
13692 int groupmatched = 0;
13693 int channelmatched = 0;
13694
13695 ast_mutex_lock(&iflock);
13696 p = determine_starting_point(dest, &start);
13697 if (!p) {
13698 ast_mutex_unlock(&iflock);
13699 return -1;
13700 }
13701 exitpvt = p;
13702 for (;;) {
13703 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13704
13705 struct ast_str *device_name;
13706 char *dash;
13707 const char *monitor_type;
13708 char dialstring[AST_CHANNEL_NAME];
13709 char full_device_name[AST_CHANNEL_NAME];
13710
13711 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13712 case AST_CC_MONITOR_NEVER:
13713 break;
13714 case AST_CC_MONITOR_NATIVE:
13715 case AST_CC_MONITOR_ALWAYS:
13716 case AST_CC_MONITOR_GENERIC:
13717 #if defined(HAVE_PRI)
13718 if (dahdi_sig_pri_lib_handles(p->sig)) {
13719
13720
13721
13722
13723 snprintf(full_device_name, sizeof(full_device_name),
13724 "DAHDI/I%d/congestion", p->pri->span);
13725 } else
13726 #endif
13727 {
13728 #if defined(HAVE_PRI)
13729 device_name = create_channel_name(p, 1, "");
13730 #else
13731 device_name = create_channel_name(p);
13732 #endif
13733 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13734 device_name ? ast_str_buffer(device_name) : "");
13735 ast_free(device_name);
13736
13737
13738
13739
13740
13741 dash = strrchr(full_device_name, '-');
13742 if (dash) {
13743 *dash = '\0';
13744 }
13745 }
13746 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13747
13748
13749
13750
13751
13752
13753
13754 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13755 callback(inbound,
13756 #if defined(HAVE_PRI)
13757 p->pri ? p->pri->cc_params : p->cc_params,
13758 #else
13759 p->cc_params,
13760 #endif
13761 monitor_type, full_device_name, dialstring, NULL);
13762 break;
13763 }
13764 }
13765 p = start.backwards ? p->prev : p->next;
13766 if (!p) {
13767 p = start.backwards ? ifend : iflist;
13768 }
13769 if (p == exitpvt) {
13770 break;
13771 }
13772 }
13773 ast_mutex_unlock(&iflock);
13774 return 0;
13775 }
13776
13777 #if defined(HAVE_SS7)
13778 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13779 {
13780 int i;
13781
13782 if (ss7) {
13783 for (i = 0; i < NUM_SPANS; i++) {
13784 if (linksets[i].ss7.ss7 == ss7) {
13785 ast_verbose("[%d] %s", i + 1, s);
13786 return;
13787 }
13788 }
13789 }
13790 ast_verbose("%s", s);
13791 }
13792 #endif
13793
13794 #if defined(HAVE_SS7)
13795 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13796 {
13797 int i;
13798
13799 if (ss7) {
13800 for (i = 0; i < NUM_SPANS; i++) {
13801 if (linksets[i].ss7.ss7 == ss7) {
13802 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13803 return;
13804 }
13805 }
13806 }
13807 ast_log(LOG_ERROR, "%s", s);
13808 }
13809 #endif
13810
13811 #if defined(HAVE_OPENR2)
13812 static void *mfcr2_monitor(void *data)
13813 {
13814 struct dahdi_mfcr2 *mfcr2 = data;
13815
13816
13817
13818
13819
13820 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13821 int res = 0;
13822 int i = 0;
13823 int oldstate = 0;
13824 int quit_loop = 0;
13825 int maxsleep = 20;
13826 int was_idle = 0;
13827 int pollsize = 0;
13828
13829
13830 for (i = 0; i < mfcr2->numchans; i++) {
13831 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13832 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13833 }
13834 while (1) {
13835
13836
13837 pollsize = 0;
13838 for (i = 0; i < mfcr2->numchans; i++) {
13839 pollers[i].revents = 0;
13840 pollers[i].events = 0;
13841 if (mfcr2->pvts[i]->owner) {
13842 continue;
13843 }
13844 if (!mfcr2->pvts[i]->r2chan) {
13845 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13846 quit_loop = 1;
13847 break;
13848 }
13849 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13850 pollers[i].events = POLLIN | POLLPRI;
13851 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13852 pollsize++;
13853 }
13854 if (quit_loop) {
13855 break;
13856 }
13857 if (pollsize == 0) {
13858 if (!was_idle) {
13859 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13860 was_idle = 1;
13861 }
13862 poll(NULL, 0, maxsleep);
13863 continue;
13864 }
13865 was_idle = 0;
13866
13867
13868 pthread_testcancel();
13869 res = poll(pollers, mfcr2->numchans, maxsleep);
13870 pthread_testcancel();
13871 if ((res < 0) && (errno != EINTR)) {
13872 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13873 break;
13874 }
13875
13876 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13877 for (i = 0; i < mfcr2->numchans; i++) {
13878 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13879 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13880 }
13881 }
13882 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13883 }
13884 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13885 return 0;
13886 }
13887 #endif
13888
13889 #if defined(HAVE_PRI)
13890 #ifndef PRI_RESTART
13891 #error "Upgrade your libpri"
13892 #endif
13893 static void dahdi_pri_message(struct pri *pri, char *s)
13894 {
13895 int x;
13896 int y;
13897 int dchan = -1;
13898 int span = -1;
13899 int dchancount = 0;
13900
13901 if (pri) {
13902 for (x = 0; x < NUM_SPANS; x++) {
13903 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13904 if (pris[x].pri.dchans[y]) {
13905 dchancount++;
13906 }
13907
13908 if (pris[x].pri.dchans[y] == pri) {
13909 dchan = y;
13910 }
13911 }
13912 if (dchan >= 0) {
13913 span = x;
13914 break;
13915 }
13916 dchancount = 0;
13917 }
13918 if (-1 < span) {
13919 if (1 < dchancount) {
13920 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13921 } else {
13922 ast_verbose("PRI Span: %d %s", span + 1, s);
13923 }
13924 } else {
13925 ast_verbose("PRI Span: ? %s", s);
13926 }
13927 } else {
13928 ast_verbose("PRI Span: ? %s", s);
13929 }
13930
13931 ast_mutex_lock(&pridebugfdlock);
13932
13933 if (pridebugfd >= 0) {
13934 if (write(pridebugfd, s, strlen(s)) < 0) {
13935 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13936 }
13937 }
13938
13939 ast_mutex_unlock(&pridebugfdlock);
13940 }
13941 #endif
13942
13943 #if defined(HAVE_PRI)
13944 static void dahdi_pri_error(struct pri *pri, char *s)
13945 {
13946 int x;
13947 int y;
13948 int dchan = -1;
13949 int span = -1;
13950 int dchancount = 0;
13951
13952 if (pri) {
13953 for (x = 0; x < NUM_SPANS; x++) {
13954 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13955 if (pris[x].pri.dchans[y]) {
13956 dchancount++;
13957 }
13958
13959 if (pris[x].pri.dchans[y] == pri) {
13960 dchan = y;
13961 }
13962 }
13963 if (dchan >= 0) {
13964 span = x;
13965 break;
13966 }
13967 dchancount = 0;
13968 }
13969 if (-1 < span) {
13970 if (1 < dchancount) {
13971 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
13972 } else {
13973 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
13974 }
13975 } else {
13976 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
13977 }
13978 } else {
13979 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
13980 }
13981
13982 ast_mutex_lock(&pridebugfdlock);
13983
13984 if (pridebugfd >= 0) {
13985 if (write(pridebugfd, s, strlen(s)) < 0) {
13986 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13987 }
13988 }
13989
13990 ast_mutex_unlock(&pridebugfdlock);
13991 }
13992 #endif
13993
13994 #if defined(HAVE_PRI)
13995 static int prepare_pri(struct dahdi_pri *pri)
13996 {
13997 int i, res, x;
13998 struct dahdi_params p;
13999 struct dahdi_bufferinfo bi;
14000 struct dahdi_spaninfo si;
14001
14002 pri->pri.calls = &dahdi_pri_callbacks;
14003
14004 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14005 if (!pri->dchannels[i])
14006 break;
14007 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14008 x = pri->dchannels[i];
14009 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14010 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14011 return -1;
14012 }
14013 memset(&p, 0, sizeof(p));
14014 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14015 if (res) {
14016 dahdi_close_pri_fd(pri, i);
14017 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14018 return -1;
14019 }
14020 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14021 dahdi_close_pri_fd(pri, i);
14022 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14023 return -1;
14024 }
14025 memset(&si, 0, sizeof(si));
14026 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14027 if (res) {
14028 dahdi_close_pri_fd(pri, i);
14029 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14030 }
14031 if (!si.alarms) {
14032 pri_event_noalarm(&pri->pri, i, 1);
14033 } else {
14034 pri_event_alarm(&pri->pri, i, 1);
14035 }
14036 memset(&bi, 0, sizeof(bi));
14037 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14038 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14039 bi.numbufs = 32;
14040 bi.bufsize = 1024;
14041 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14042 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14043 dahdi_close_pri_fd(pri, i);
14044 return -1;
14045 }
14046 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14047 }
14048 return 0;
14049 }
14050 #endif
14051
14052 #if defined(HAVE_PRI)
14053 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14054 {
14055 int which, span;
14056 char *ret = NULL;
14057
14058 if (pos != rpos)
14059 return ret;
14060
14061 for (which = span = 0; span < NUM_SPANS; span++) {
14062 if (pris[span].pri.pri && ++which > state) {
14063 if (asprintf(&ret, "%d", span + 1) < 0) {
14064 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
14065 }
14066 break;
14067 }
14068 }
14069 return ret;
14070 }
14071 #endif
14072
14073 #if defined(HAVE_PRI)
14074 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14075 {
14076 return complete_span_helper(line,word,pos,state,3);
14077 }
14078 #endif
14079
14080 #if defined(HAVE_PRI)
14081 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14082 {
14083 int myfd;
14084 switch (cmd) {
14085 case CLI_INIT:
14086 e->command = "pri set debug file";
14087 e->usage = "Usage: pri set debug file [output-file]\n"
14088 " Sends PRI debug output to the specified output file\n";
14089 return NULL;
14090 case CLI_GENERATE:
14091 return NULL;
14092 }
14093 if (a->argc < 5)
14094 return CLI_SHOWUSAGE;
14095
14096 if (ast_strlen_zero(a->argv[4]))
14097 return CLI_SHOWUSAGE;
14098
14099 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14100 if (myfd < 0) {
14101 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14102 return CLI_SUCCESS;
14103 }
14104
14105 ast_mutex_lock(&pridebugfdlock);
14106
14107 if (pridebugfd >= 0)
14108 close(pridebugfd);
14109
14110 pridebugfd = myfd;
14111 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14112 ast_mutex_unlock(&pridebugfdlock);
14113 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14114 return CLI_SUCCESS;
14115 }
14116 #endif
14117
14118 #if defined(HAVE_PRI)
14119 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14120 {
14121 int span;
14122 int x;
14123 int level = 0;
14124 switch (cmd) {
14125 case CLI_INIT:
14126 e->command = "pri set debug {on|off|0|1|2} span";
14127 e->usage =
14128 "Usage: pri set debug {<level>|on|off} span <span>\n"
14129 " Enables debugging on a given PRI span\n";
14130 return NULL;
14131 case CLI_GENERATE:
14132 return complete_span_4(a->line, a->word, a->pos, a->n);
14133 }
14134 if (a->argc < 6) {
14135 return CLI_SHOWUSAGE;
14136 }
14137
14138 if (!strcasecmp(a->argv[3], "on")) {
14139 level = 1;
14140 } else if (!strcasecmp(a->argv[3], "off")) {
14141 level = 0;
14142 } else {
14143 level = atoi(a->argv[3]);
14144 }
14145 span = atoi(a->argv[5]);
14146 if ((span < 1) || (span > NUM_SPANS)) {
14147 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14148 return CLI_SUCCESS;
14149 }
14150 if (!pris[span-1].pri.pri) {
14151 ast_cli(a->fd, "No PRI running on span %d\n", span);
14152 return CLI_SUCCESS;
14153 }
14154
14155
14156 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14157 if (pris[span - 1].pri.dchans[x]) {
14158 switch (level) {
14159 case 0:
14160 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14161 break;
14162 case 1:
14163 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14164 break;
14165 default:
14166 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14167 break;
14168 }
14169 }
14170 }
14171 if (level == 0) {
14172
14173 ast_mutex_lock(&pridebugfdlock);
14174 if (0 <= pridebugfd) {
14175 close(pridebugfd);
14176 pridebugfd = -1;
14177 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14178 pridebugfilename);
14179 }
14180 ast_mutex_unlock(&pridebugfdlock);
14181 }
14182 pris[span - 1].pri.debug = (level) ? 1 : 0;
14183 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14184 return CLI_SUCCESS;
14185 }
14186 #endif
14187
14188 #if defined(HAVE_PRI)
14189 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14190 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14191 {
14192 unsigned *why;
14193 int channel;
14194 int trunkgroup;
14195 int x, y, fd = a->fd;
14196 int interfaceid = 0;
14197 char *c;
14198 char db_chan_name[20], db_answer[5];
14199 struct dahdi_pvt *tmp;
14200 struct dahdi_pri *pri;
14201
14202 if (a->argc < 5 || a->argc > 6)
14203 return CLI_SHOWUSAGE;
14204 if ((c = strchr(a->argv[4], ':'))) {
14205 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14206 return CLI_SHOWUSAGE;
14207 if ((trunkgroup < 1) || (channel < 1))
14208 return CLI_SHOWUSAGE;
14209 pri = NULL;
14210 for (x=0;x<NUM_SPANS;x++) {
14211 if (pris[x].pri.trunkgroup == trunkgroup) {
14212 pri = pris + x;
14213 break;
14214 }
14215 }
14216 if (!pri) {
14217 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14218 return CLI_FAILURE;
14219 }
14220 } else
14221 channel = atoi(a->argv[4]);
14222
14223 if (a->argc == 6)
14224 interfaceid = atoi(a->argv[5]);
14225
14226
14227 for (x = 0; x < NUM_SPANS; x++) {
14228 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14229 if (pris[x].dchannels[y] == channel) {
14230 pri = pris + x;
14231 if (pri->pri.enable_service_message_support) {
14232 ast_mutex_lock(&pri->pri.lock);
14233 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14234 ast_mutex_unlock(&pri->pri.lock);
14235 } else {
14236 ast_cli(fd,
14237 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14238 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14239 }
14240 return CLI_SUCCESS;
14241 }
14242 }
14243 }
14244
14245
14246 ast_mutex_lock(&iflock);
14247 for (tmp = iflist; tmp; tmp = tmp->next) {
14248 if (tmp->pri && tmp->channel == channel) {
14249 ast_mutex_unlock(&iflock);
14250 ast_mutex_lock(&tmp->pri->lock);
14251 if (!tmp->pri->enable_service_message_support) {
14252 ast_mutex_unlock(&tmp->pri->lock);
14253 ast_cli(fd,
14254 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14255 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14256 return CLI_SUCCESS;
14257 }
14258 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14259 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14260 switch(changestatus) {
14261 case 0:
14262
14263 ast_db_del(db_chan_name, SRVST_DBKEY);
14264 *why &= ~SRVST_NEAREND;
14265 if (*why) {
14266 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14267 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14268 } else {
14269 dahdi_pri_update_span_devstate(tmp->pri);
14270 }
14271 break;
14272
14273 case 2:
14274
14275 ast_db_del(db_chan_name, SRVST_DBKEY);
14276 *why |= SRVST_NEAREND;
14277 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14278 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14279 dahdi_pri_update_span_devstate(tmp->pri);
14280 break;
14281
14282
14283 default:
14284 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14285 break;
14286 }
14287 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14288 ast_mutex_unlock(&tmp->pri->lock);
14289 return CLI_SUCCESS;
14290 }
14291 }
14292 ast_mutex_unlock(&iflock);
14293
14294 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14295 return CLI_FAILURE;
14296 }
14297
14298 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14299 {
14300 switch (cmd) {
14301 case CLI_INIT:
14302 e->command = "pri service enable channel";
14303 e->usage =
14304 "Usage: pri service enable channel <channel> [<interface id>]\n"
14305 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14306 " to restore a channel to service, with optional interface id\n"
14307 " as agreed upon with remote switch operator\n";
14308 return NULL;
14309 case CLI_GENERATE:
14310 return NULL;
14311 }
14312 return handle_pri_service_generic(e, cmd, a, 0);
14313 }
14314
14315 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14316 {
14317 switch (cmd) {
14318 case CLI_INIT:
14319 e->command = "pri service disable channel";
14320 e->usage =
14321 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14322 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14323 " to remove a channel from service, with optional interface id\n"
14324 " as agreed upon with remote switch operator\n";
14325 return NULL;
14326 case CLI_GENERATE:
14327 return NULL;
14328 }
14329 return handle_pri_service_generic(e, cmd, a, 2);
14330 }
14331 #endif
14332 #endif
14333
14334 #if defined(HAVE_PRI)
14335 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14336 {
14337 int span;
14338
14339 switch (cmd) {
14340 case CLI_INIT:
14341 e->command = "pri show channels";
14342 e->usage =
14343 "Usage: pri show channels\n"
14344 " Displays PRI channel information such as the current mapping\n"
14345 " of DAHDI B channels to Asterisk channel names and which calls\n"
14346 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14347 " are not associated with any B channel.\n";
14348 return NULL;
14349 case CLI_GENERATE:
14350 return NULL;
14351 }
14352
14353 if (a->argc != 3)
14354 return CLI_SHOWUSAGE;
14355
14356 sig_pri_cli_show_channels_header(a->fd);
14357 for (span = 0; span < NUM_SPANS; ++span) {
14358 if (pris[span].pri.pri) {
14359 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14360 }
14361 }
14362 return CLI_SUCCESS;
14363 }
14364 #endif
14365
14366 #if defined(HAVE_PRI)
14367 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14368 {
14369 int span;
14370
14371 switch (cmd) {
14372 case CLI_INIT:
14373 e->command = "pri show spans";
14374 e->usage =
14375 "Usage: pri show spans\n"
14376 " Displays PRI span information\n";
14377 return NULL;
14378 case CLI_GENERATE:
14379 return NULL;
14380 }
14381
14382 if (a->argc != 3)
14383 return CLI_SHOWUSAGE;
14384
14385 for (span = 0; span < NUM_SPANS; span++) {
14386 if (pris[span].pri.pri) {
14387 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14388 }
14389 }
14390 return CLI_SUCCESS;
14391 }
14392 #endif
14393
14394 #if defined(HAVE_PRI)
14395 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14396 {
14397 int span;
14398
14399 switch (cmd) {
14400 case CLI_INIT:
14401 e->command = "pri show span";
14402 e->usage =
14403 "Usage: pri show span <span>\n"
14404 " Displays PRI Information on a given PRI span\n";
14405 return NULL;
14406 case CLI_GENERATE:
14407 return complete_span_4(a->line, a->word, a->pos, a->n);
14408 }
14409
14410 if (a->argc < 4)
14411 return CLI_SHOWUSAGE;
14412 span = atoi(a->argv[3]);
14413 if ((span < 1) || (span > NUM_SPANS)) {
14414 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14415 return CLI_SUCCESS;
14416 }
14417 if (!pris[span-1].pri.pri) {
14418 ast_cli(a->fd, "No PRI running on span %d\n", span);
14419 return CLI_SUCCESS;
14420 }
14421
14422 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14423
14424 return CLI_SUCCESS;
14425 }
14426 #endif
14427
14428 #if defined(HAVE_PRI)
14429 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14430 {
14431 int x;
14432 int span;
14433 int count=0;
14434 int debug;
14435
14436 switch (cmd) {
14437 case CLI_INIT:
14438 e->command = "pri show debug";
14439 e->usage =
14440 "Usage: pri show debug\n"
14441 " Show the debug state of pri spans\n";
14442 return NULL;
14443 case CLI_GENERATE:
14444 return NULL;
14445 }
14446
14447 for (span = 0; span < NUM_SPANS; span++) {
14448 if (pris[span].pri.pri) {
14449 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14450 if (pris[span].pri.dchans[x]) {
14451 debug = pri_get_debug(pris[span].pri.dchans[x]);
14452 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" );
14453 count++;
14454 }
14455 }
14456 }
14457
14458 }
14459 ast_mutex_lock(&pridebugfdlock);
14460 if (pridebugfd >= 0)
14461 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14462 ast_mutex_unlock(&pridebugfdlock);
14463
14464 if (!count)
14465 ast_cli(a->fd, "No PRI running\n");
14466 return CLI_SUCCESS;
14467 }
14468 #endif
14469
14470 #if defined(HAVE_PRI)
14471 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14472 {
14473 switch (cmd) {
14474 case CLI_INIT:
14475 e->command = "pri show version";
14476 e->usage =
14477 "Usage: pri show version\n"
14478 "Show libpri version information\n";
14479 return NULL;
14480 case CLI_GENERATE:
14481 return NULL;
14482 }
14483
14484 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14485
14486 return CLI_SUCCESS;
14487 }
14488 #endif
14489
14490 #if defined(HAVE_PRI)
14491 static struct ast_cli_entry dahdi_pri_cli[] = {
14492 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14493 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14494 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14495 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14496 #endif
14497 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14498 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14499 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14500 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14501 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14502 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14503 };
14504 #endif
14505
14506 #ifdef HAVE_OPENR2
14507
14508 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14509 {
14510 switch (cmd) {
14511 case CLI_INIT:
14512 e->command = "mfcr2 show version";
14513 e->usage =
14514 "Usage: mfcr2 show version\n"
14515 " Shows the version of the OpenR2 library being used.\n";
14516 return NULL;
14517 case CLI_GENERATE:
14518 return NULL;
14519 }
14520 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14521 return CLI_SUCCESS;
14522 }
14523
14524 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14525 {
14526 #define FORMAT "%4s %40s\n"
14527 int i = 0;
14528 int numvariants = 0;
14529 const openr2_variant_entry_t *variants;
14530 switch (cmd) {
14531 case CLI_INIT:
14532 e->command = "mfcr2 show variants";
14533 e->usage =
14534 "Usage: mfcr2 show variants\n"
14535 " Shows the list of MFC/R2 variants supported.\n";
14536 return NULL;
14537 case CLI_GENERATE:
14538 return NULL;
14539 }
14540 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14541 ast_cli(a->fd, "Failed to get list of variants.\n");
14542 return CLI_FAILURE;
14543 }
14544 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14545 for (i = 0; i < numvariants; i++) {
14546 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14547 }
14548 return CLI_SUCCESS;
14549 #undef FORMAT
14550 }
14551
14552 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14553 {
14554 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14555 int filtertype = 0;
14556 int targetnum = 0;
14557 char channo[5];
14558 char anino[5];
14559 char dnisno[5];
14560 struct dahdi_pvt *p;
14561 openr2_context_t *r2context;
14562 openr2_variant_t r2variant;
14563 switch (cmd) {
14564 case CLI_INIT:
14565 e->command = "mfcr2 show channels [group|context]";
14566 e->usage =
14567 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14568 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14569 return NULL;
14570 case CLI_GENERATE:
14571 return NULL;
14572 }
14573 if (!((a->argc == 3) || (a->argc == 5))) {
14574 return CLI_SHOWUSAGE;
14575 }
14576 if (a->argc == 5) {
14577 if (!strcasecmp(a->argv[3], "group")) {
14578 targetnum = atoi(a->argv[4]);
14579 if ((targetnum < 0) || (targetnum > 63))
14580 return CLI_SHOWUSAGE;
14581 targetnum = 1 << targetnum;
14582 filtertype = 1;
14583 } else if (!strcasecmp(a->argv[3], "context")) {
14584 filtertype = 2;
14585 } else {
14586 return CLI_SHOWUSAGE;
14587 }
14588 }
14589 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14590 ast_mutex_lock(&iflock);
14591 for (p = iflist; p; p = p->next) {
14592 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14593 continue;
14594 }
14595 if (filtertype) {
14596 switch(filtertype) {
14597 case 1:
14598 if (p->group != targetnum) {
14599 continue;
14600 }
14601 break;
14602 case 2:
14603 if (strcasecmp(p->context, a->argv[4])) {
14604 continue;
14605 }
14606 break;
14607 default:
14608 ;
14609 }
14610 }
14611 r2context = openr2_chan_get_context(p->r2chan);
14612 r2variant = openr2_context_get_variant(r2context);
14613 snprintf(channo, sizeof(channo), "%d", p->channel);
14614 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14615 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14616 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14617 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14618 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14619 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14620 }
14621 ast_mutex_unlock(&iflock);
14622 return CLI_SUCCESS;
14623 #undef FORMAT
14624 }
14625
14626 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14627 {
14628 struct dahdi_pvt *p = NULL;
14629 int channo = 0;
14630 char *toklevel = NULL;
14631 char *saveptr = NULL;
14632 char *logval = NULL;
14633 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14634 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14635 switch (cmd) {
14636 case CLI_INIT:
14637 e->command = "mfcr2 set debug";
14638 e->usage =
14639 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14640 " Set a new logging level for the specified channel.\n"
14641 " If no channel is specified the logging level will be applied to all channels.\n";
14642 return NULL;
14643 case CLI_GENERATE:
14644 return NULL;
14645 }
14646 if (a->argc < 4) {
14647 return CLI_SHOWUSAGE;
14648 }
14649 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14650 logval = ast_strdupa(a->argv[3]);
14651 toklevel = strtok_r(logval, ",", &saveptr);
14652 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14653 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14654 return CLI_FAILURE;
14655 } else if (OR2_LOG_NOTHING == tmplevel) {
14656 loglevel = tmplevel;
14657 } else {
14658 loglevel |= tmplevel;
14659 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14660 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14661 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14662 continue;
14663 }
14664 loglevel |= tmplevel;
14665 }
14666 }
14667 ast_mutex_lock(&iflock);
14668 for (p = iflist; p; p = p->next) {
14669 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14670 continue;
14671 }
14672 if ((channo != -1) && (p->channel != channo )) {
14673 continue;
14674 }
14675 openr2_chan_set_log_level(p->r2chan, loglevel);
14676 if (channo != -1) {
14677 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14678 break;
14679 }
14680 }
14681 if ((channo != -1) && !p) {
14682 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14683 }
14684 if (channo == -1) {
14685 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14686 }
14687 ast_mutex_unlock(&iflock);
14688 return CLI_SUCCESS;
14689 }
14690
14691 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14692 {
14693 struct dahdi_pvt *p = NULL;
14694 int channo = 0;
14695 switch (cmd) {
14696 case CLI_INIT:
14697 e->command = "mfcr2 call files [on|off]";
14698 e->usage =
14699 "Usage: mfcr2 call files [on|off] <channel>\n"
14700 " Enable call files creation on the specified channel.\n"
14701 " If no channel is specified call files creation policy will be applied to all channels.\n";
14702 return NULL;
14703 case CLI_GENERATE:
14704 return NULL;
14705 }
14706 if (a->argc < 4) {
14707 return CLI_SHOWUSAGE;
14708 }
14709 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14710 ast_mutex_lock(&iflock);
14711 for (p = iflist; p; p = p->next) {
14712 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14713 continue;
14714 }
14715 if ((channo != -1) && (p->channel != channo )) {
14716 continue;
14717 }
14718 if (ast_true(a->argv[3])) {
14719 openr2_chan_enable_call_files(p->r2chan);
14720 } else {
14721 openr2_chan_disable_call_files(p->r2chan);
14722 }
14723 if (channo != -1) {
14724 if (ast_true(a->argv[3])) {
14725 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14726 } else {
14727 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14728 }
14729 break;
14730 }
14731 }
14732 if ((channo != -1) && !p) {
14733 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14734 }
14735 if (channo == -1) {
14736 if (ast_true(a->argv[3])) {
14737 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14738 } else {
14739 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14740 }
14741 }
14742 ast_mutex_unlock(&iflock);
14743 return CLI_SUCCESS;
14744 }
14745
14746 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14747 {
14748 struct dahdi_pvt *p = NULL;
14749 int channo = 0;
14750 switch (cmd) {
14751 case CLI_INIT:
14752 e->command = "mfcr2 set idle";
14753 e->usage =
14754 "Usage: mfcr2 set idle <channel>\n"
14755 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14756 " Force the given channel into IDLE state.\n"
14757 " If no channel is specified, all channels will be set to IDLE.\n";
14758 return NULL;
14759 case CLI_GENERATE:
14760 return NULL;
14761 }
14762 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14763 ast_mutex_lock(&iflock);
14764 for (p = iflist; p; p = p->next) {
14765 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14766 continue;
14767 }
14768 if ((channo != -1) && (p->channel != channo )) {
14769 continue;
14770 }
14771 openr2_chan_set_idle(p->r2chan);
14772 ast_mutex_lock(&p->lock);
14773 p->locallyblocked = 0;
14774 p->mfcr2call = 0;
14775 ast_mutex_unlock(&p->lock);
14776 if (channo != -1) {
14777 break;
14778 }
14779 }
14780 if ((channo != -1) && !p) {
14781 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14782 }
14783 ast_mutex_unlock(&iflock);
14784 return CLI_SUCCESS;
14785 }
14786
14787 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14788 {
14789 struct dahdi_pvt *p = NULL;
14790 int channo = 0;
14791 switch (cmd) {
14792 case CLI_INIT:
14793 e->command = "mfcr2 set blocked";
14794 e->usage =
14795 "Usage: mfcr2 set blocked <channel>\n"
14796 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14797 " Force the given channel into BLOCKED state.\n"
14798 " If no channel is specified, all channels will be set to BLOCKED.\n";
14799 return NULL;
14800 case CLI_GENERATE:
14801 return NULL;
14802 }
14803 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14804 ast_mutex_lock(&iflock);
14805 for (p = iflist; p; p = p->next) {
14806 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14807 continue;
14808 }
14809 if ((channo != -1) && (p->channel != channo )) {
14810 continue;
14811 }
14812 openr2_chan_set_blocked(p->r2chan);
14813 ast_mutex_lock(&p->lock);
14814 p->locallyblocked = 1;
14815 ast_mutex_unlock(&p->lock);
14816 if (channo != -1) {
14817 break;
14818 }
14819 }
14820 if ((channo != -1) && !p) {
14821 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14822 }
14823 ast_mutex_unlock(&iflock);
14824 return CLI_SUCCESS;
14825 }
14826
14827 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14828 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14829 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14830 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14831 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14832 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14833 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14834 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14835 };
14836
14837 #endif
14838
14839 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14840 {
14841 int channel;
14842 int ret;
14843 switch (cmd) {
14844 case CLI_INIT:
14845 e->command = "dahdi destroy channel";
14846 e->usage =
14847 "Usage: dahdi destroy channel <chan num>\n"
14848 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14849 return NULL;
14850 case CLI_GENERATE:
14851 return NULL;
14852 }
14853 if (a->argc != 4)
14854 return CLI_SHOWUSAGE;
14855
14856 channel = atoi(a->argv[3]);
14857 ret = dahdi_destroy_channel_bynum(channel);
14858 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14859 }
14860
14861 static void dahdi_softhangup_all(void)
14862 {
14863 struct dahdi_pvt *p;
14864 retry:
14865 ast_mutex_lock(&iflock);
14866 for (p = iflist; p; p = p->next) {
14867 ast_mutex_lock(&p->lock);
14868 if (p->owner && !p->restartpending) {
14869 if (ast_channel_trylock(p->owner)) {
14870 if (option_debug > 2)
14871 ast_verbose("Avoiding deadlock\n");
14872
14873 ast_mutex_unlock(&p->lock);
14874 ast_mutex_unlock(&iflock);
14875 goto retry;
14876 }
14877 if (option_debug > 2)
14878 ast_verbose("Softhanging up on %s\n", p->owner->name);
14879 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14880 p->restartpending = 1;
14881 num_restart_pending++;
14882 ast_channel_unlock(p->owner);
14883 }
14884 ast_mutex_unlock(&p->lock);
14885 }
14886 ast_mutex_unlock(&iflock);
14887 }
14888
14889 static int setup_dahdi(int reload);
14890 static int dahdi_restart(void)
14891 {
14892 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14893 int i, j;
14894 #endif
14895 int cancel_code;
14896 struct dahdi_pvt *p;
14897
14898 ast_mutex_lock(&restart_lock);
14899 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14900 dahdi_softhangup_all();
14901 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14902 #ifdef HAVE_OPENR2
14903 dahdi_r2_destroy_links();
14904 #endif
14905
14906 #if defined(HAVE_PRI)
14907 for (i = 0; i < NUM_SPANS; i++) {
14908 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14909 cancel_code = pthread_cancel(pris[i].pri.master);
14910 pthread_kill(pris[i].pri.master, SIGURG);
14911 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);
14912 pthread_join(pris[i].pri.master, NULL);
14913 ast_debug(4, "Joined thread of span %d\n", i);
14914 }
14915 }
14916 #endif
14917
14918 #if defined(HAVE_SS7)
14919 for (i = 0; i < NUM_SPANS; i++) {
14920 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14921 cancel_code = pthread_cancel(linksets[i].ss7.master);
14922 pthread_kill(linksets[i].ss7.master, SIGURG);
14923 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);
14924 pthread_join(linksets[i].ss7.master, NULL);
14925 ast_debug(4, "Joined thread of span %d\n", i);
14926 }
14927 }
14928 #endif
14929
14930 ast_mutex_lock(&monlock);
14931 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14932 cancel_code = pthread_cancel(monitor_thread);
14933 pthread_kill(monitor_thread, SIGURG);
14934 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14935 pthread_join(monitor_thread, NULL);
14936 ast_debug(4, "Joined monitor thread\n");
14937 }
14938 monitor_thread = AST_PTHREADT_NULL;
14939
14940 ast_mutex_lock(&ss_thread_lock);
14941 while (ss_thread_count > 0) {
14942 int x = DAHDI_FLASH;
14943 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14944
14945 ast_mutex_lock(&iflock);
14946 for (p = iflist; p; p = p->next) {
14947 if (p->owner) {
14948
14949 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14950 }
14951 }
14952 ast_mutex_unlock(&iflock);
14953 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14954 }
14955
14956
14957 dahdi_softhangup_all();
14958 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14959 destroy_all_channels();
14960 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14961
14962 ast_mutex_unlock(&monlock);
14963
14964 #ifdef HAVE_PRI
14965 for (i = 0; i < NUM_SPANS; i++) {
14966 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14967 dahdi_close_pri_fd(&(pris[i]), j);
14968 }
14969
14970 memset(pris, 0, sizeof(pris));
14971 for (i = 0; i < NUM_SPANS; i++) {
14972 sig_pri_init_pri(&pris[i].pri);
14973 }
14974 pri_set_error(dahdi_pri_error);
14975 pri_set_message(dahdi_pri_message);
14976 #endif
14977 #if defined(HAVE_SS7)
14978 for (i = 0; i < NUM_SPANS; i++) {
14979 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14980 dahdi_close_ss7_fd(&(linksets[i]), j);
14981 }
14982
14983 memset(linksets, 0, sizeof(linksets));
14984 for (i = 0; i < NUM_SPANS; i++) {
14985 sig_ss7_init_linkset(&linksets[i].ss7);
14986 }
14987 ss7_set_error(dahdi_ss7_error);
14988 ss7_set_message(dahdi_ss7_message);
14989 #endif
14990
14991 if (setup_dahdi(2) != 0) {
14992 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14993 ast_mutex_unlock(&ss_thread_lock);
14994 return 1;
14995 }
14996 ast_mutex_unlock(&ss_thread_lock);
14997 ast_mutex_unlock(&restart_lock);
14998 return 0;
14999 }
15000
15001 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15002 {
15003 switch (cmd) {
15004 case CLI_INIT:
15005 e->command = "dahdi restart";
15006 e->usage =
15007 "Usage: dahdi restart\n"
15008 " Restarts the DAHDI channels: destroys them all and then\n"
15009 " re-reads them from chan_dahdi.conf.\n"
15010 " Note that this will STOP any running CALL on DAHDI channels.\n"
15011 "";
15012 return NULL;
15013 case CLI_GENERATE:
15014 return NULL;
15015 }
15016 if (a->argc != 2)
15017 return CLI_SHOWUSAGE;
15018
15019 if (dahdi_restart() != 0)
15020 return CLI_FAILURE;
15021 return CLI_SUCCESS;
15022 }
15023
15024 static int action_dahdirestart(struct mansession *s, const struct message *m)
15025 {
15026 if (dahdi_restart() != 0) {
15027 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15028 return 1;
15029 }
15030 astman_send_ack(s, m, "DAHDIRestart: Success");
15031 return 0;
15032 }
15033
15034 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15035 {
15036 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15037 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15038 unsigned int targetnum = 0;
15039 int filtertype = 0;
15040 struct dahdi_pvt *tmp = NULL;
15041 char tmps[20] = "";
15042 char statestr[20] = "";
15043 char blockstr[20] = "";
15044
15045 switch (cmd) {
15046 case CLI_INIT:
15047 e->command = "dahdi show channels [group|context]";
15048 e->usage =
15049 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15050 " Shows a list of available channels with optional filtering\n"
15051 " <group> must be a number between 0 and 63\n";
15052 return NULL;
15053 case CLI_GENERATE:
15054 return NULL;
15055 }
15056
15057
15058
15059 if (!((a->argc == 3) || (a->argc == 5)))
15060 return CLI_SHOWUSAGE;
15061
15062 if (a->argc == 5) {
15063 if (!strcasecmp(a->argv[3], "group")) {
15064 targetnum = atoi(a->argv[4]);
15065 if ((targetnum < 0) || (targetnum > 63))
15066 return CLI_SHOWUSAGE;
15067 targetnum = 1 << targetnum;
15068 filtertype = 1;
15069 } else if (!strcasecmp(a->argv[3], "context")) {
15070 filtertype = 2;
15071 }
15072 }
15073
15074 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15075 ast_mutex_lock(&iflock);
15076 for (tmp = iflist; tmp; tmp = tmp->next) {
15077 if (filtertype) {
15078 switch(filtertype) {
15079 case 1:
15080 if (!(tmp->group & targetnum)) {
15081 continue;
15082 }
15083 break;
15084 case 2:
15085 if (strcasecmp(tmp->context, a->argv[4])) {
15086 continue;
15087 }
15088 break;
15089 default:
15090 break;
15091 }
15092 }
15093 if (tmp->channel > 0) {
15094 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15095 } else
15096 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15097
15098 if (tmp->locallyblocked)
15099 blockstr[0] = 'L';
15100 else
15101 blockstr[0] = ' ';
15102
15103 if (tmp->remotelyblocked)
15104 blockstr[1] = 'R';
15105 else
15106 blockstr[1] = ' ';
15107
15108 blockstr[2] = '\0';
15109
15110 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15111
15112 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15113 }
15114 ast_mutex_unlock(&iflock);
15115 return CLI_SUCCESS;
15116 #undef FORMAT
15117 #undef FORMAT2
15118 }
15119
15120 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15121 {
15122 int channel;
15123 struct dahdi_pvt *tmp = NULL;
15124 struct dahdi_confinfo ci;
15125 struct dahdi_params ps;
15126 int x;
15127
15128 switch (cmd) {
15129 case CLI_INIT:
15130 e->command = "dahdi show channel";
15131 e->usage =
15132 "Usage: dahdi show channel <chan num>\n"
15133 " Detailed information about a given channel\n";
15134 return NULL;
15135 case CLI_GENERATE:
15136 return NULL;
15137 }
15138
15139 if (a->argc != 4)
15140 return CLI_SHOWUSAGE;
15141
15142 channel = atoi(a->argv[3]);
15143
15144 ast_mutex_lock(&iflock);
15145 for (tmp = iflist; tmp; tmp = tmp->next) {
15146 if (tmp->channel == channel) {
15147 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15148 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15149 ast_cli(a->fd, "Span: %d\n", tmp->span);
15150 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15151 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15152 ast_cli(a->fd, "Context: %s\n", tmp->context);
15153 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15154 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15155 #if defined(HAVE_PRI)
15156 #if defined(HAVE_PRI_SUBADDR)
15157 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15158 #endif
15159 #endif
15160 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15161 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15162 if (tmp->vars) {
15163 struct ast_variable *v;
15164 ast_cli(a->fd, "Variables:\n");
15165 for (v = tmp->vars ; v ; v = v->next)
15166 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15167 }
15168 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15169 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15170 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15171 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15172 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15173 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)" : "");
15174 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)" : "");
15175 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)" : "");
15176 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15177 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15178 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15179 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15180 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15181 if (tmp->busydetect) {
15182 #if defined(BUSYDETECT_TONEONLY)
15183 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15184 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15185 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15186 #endif
15187 #ifdef BUSYDETECT_DEBUG
15188 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15189 #endif
15190 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15191 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15192 }
15193 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15194 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15195 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15196 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15197 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15198 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15199 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15200 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15201 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15202 ast_cli(a->fd, "Echo Cancellation:\n");
15203
15204 if (tmp->echocancel.head.tap_length) {
15205 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15206 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15207 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15208 }
15209 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15210 } else {
15211 ast_cli(a->fd, "\tnone\n");
15212 }
15213 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15214 if (tmp->master)
15215 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15216 for (x = 0; x < MAX_SLAVES; x++) {
15217 if (tmp->slaves[x])
15218 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15219 }
15220 #ifdef HAVE_OPENR2
15221 if (tmp->mfcr2) {
15222 char calldir[OR2_MAX_PATH];
15223 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15224 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15225 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15226 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15227 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15228 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15229 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15230 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15231 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15232 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15233 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15234 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15235 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15236 #endif
15237 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15238 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15239 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15240 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15241 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15242 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15243 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15244 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15245 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15246 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15247 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15248 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15249 }
15250 #endif
15251 #if defined(HAVE_SS7)
15252 if (tmp->ss7) {
15253 struct sig_ss7_chan *chan = tmp->sig_pvt;
15254
15255 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15256 }
15257 #endif
15258 #ifdef HAVE_PRI
15259 if (tmp->pri) {
15260 struct sig_pri_chan *chan = tmp->sig_pvt;
15261
15262 ast_cli(a->fd, "PRI Flags: ");
15263 if (chan->resetting)
15264 ast_cli(a->fd, "Resetting ");
15265 if (chan->call)
15266 ast_cli(a->fd, "Call ");
15267 if (chan->allocated) {
15268 ast_cli(a->fd, "Allocated ");
15269 }
15270 ast_cli(a->fd, "\n");
15271 if (tmp->logicalspan)
15272 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15273 else
15274 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15275 }
15276 #endif
15277 memset(&ci, 0, sizeof(ci));
15278 ps.channo = tmp->channel;
15279 if (tmp->subs[SUB_REAL].dfd > -1) {
15280 memset(&ci, 0, sizeof(ci));
15281 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15282 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15283 }
15284 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15285 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15286 }
15287 memset(&ps, 0, sizeof(ps));
15288 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15289 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15290 } else {
15291 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15292 }
15293 }
15294 ast_mutex_unlock(&iflock);
15295 return CLI_SUCCESS;
15296 }
15297 }
15298 ast_mutex_unlock(&iflock);
15299
15300 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15301 return CLI_FAILURE;
15302 }
15303
15304 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15305 {
15306 int i, j;
15307 switch (cmd) {
15308 case CLI_INIT:
15309 e->command = "dahdi show cadences";
15310 e->usage =
15311 "Usage: dahdi show cadences\n"
15312 " Shows all cadences currently defined\n";
15313 return NULL;
15314 case CLI_GENERATE:
15315 return NULL;
15316 }
15317 for (i = 0; i < num_cadence; i++) {
15318 char output[1024];
15319 char tmp[16], tmp2[64];
15320 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15321 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15322
15323 for (j = 0; j < 16; j++) {
15324 if (cadences[i].ringcadence[j] == 0)
15325 break;
15326 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15327 if (cidrings[i] * 2 - 1 == j)
15328 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15329 else
15330 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15331 if (j != 0)
15332 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15333 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15334 }
15335 ast_cli(a->fd,"%s\n",output);
15336 }
15337 return CLI_SUCCESS;
15338 }
15339
15340
15341 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15342 {
15343 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15344 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15345 int span;
15346 int res;
15347 char alarmstr[50];
15348
15349 int ctl;
15350 struct dahdi_spaninfo s;
15351
15352 switch (cmd) {
15353 case CLI_INIT:
15354 e->command = "dahdi show status";
15355 e->usage =
15356 "Usage: dahdi show status\n"
15357 " Shows a list of DAHDI cards with status\n";
15358 return NULL;
15359 case CLI_GENERATE:
15360 return NULL;
15361 }
15362 ctl = open("/dev/dahdi/ctl", O_RDWR);
15363 if (ctl < 0) {
15364 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15365 return CLI_FAILURE;
15366 }
15367 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15368
15369 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15370 s.spanno = span;
15371 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15372 if (res) {
15373 continue;
15374 }
15375 alarmstr[0] = '\0';
15376 if (s.alarms > 0) {
15377 if (s.alarms & DAHDI_ALARM_BLUE)
15378 strcat(alarmstr, "BLU/");
15379 if (s.alarms & DAHDI_ALARM_YELLOW)
15380 strcat(alarmstr, "YEL/");
15381 if (s.alarms & DAHDI_ALARM_RED)
15382 strcat(alarmstr, "RED/");
15383 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15384 strcat(alarmstr, "LB/");
15385 if (s.alarms & DAHDI_ALARM_RECOVER)
15386 strcat(alarmstr, "REC/");
15387 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15388 strcat(alarmstr, "NOP/");
15389 if (!strlen(alarmstr))
15390 strcat(alarmstr, "UUU/");
15391 if (strlen(alarmstr)) {
15392
15393 alarmstr[strlen(alarmstr) - 1] = '\0';
15394 }
15395 } else {
15396 if (s.numchans)
15397 strcpy(alarmstr, "OK");
15398 else
15399 strcpy(alarmstr, "UNCONFIGURED");
15400 }
15401
15402 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15403 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15404 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15405 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15406 "CAS",
15407 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15408 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15409 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15410 "Unk",
15411 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15412 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15413 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15414 lbostr[s.lbo]
15415 );
15416 }
15417 close(ctl);
15418
15419 return CLI_SUCCESS;
15420 #undef FORMAT
15421 #undef FORMAT2
15422 }
15423
15424 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15425 {
15426 int pseudo_fd = -1;
15427 struct dahdi_versioninfo vi;
15428
15429 switch (cmd) {
15430 case CLI_INIT:
15431 e->command = "dahdi show version";
15432 e->usage =
15433 "Usage: dahdi show version\n"
15434 " Shows the DAHDI version in use\n";
15435 return NULL;
15436 case CLI_GENERATE:
15437 return NULL;
15438 }
15439 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15440 ast_cli(a->fd, "Failed to open control file to get version.\n");
15441 return CLI_SUCCESS;
15442 }
15443
15444 strcpy(vi.version, "Unknown");
15445 strcpy(vi.echo_canceller, "Unknown");
15446
15447 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15448 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15449 else
15450 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15451
15452 close(pseudo_fd);
15453
15454 return CLI_SUCCESS;
15455 }
15456
15457 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15458 {
15459 int channel;
15460 int gain;
15461 int tx;
15462 struct dahdi_hwgain hwgain;
15463 struct dahdi_pvt *tmp = NULL;
15464
15465 switch (cmd) {
15466 case CLI_INIT:
15467 e->command = "dahdi set hwgain";
15468 e->usage =
15469 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15470 " Sets the hardware gain on a a given channel, overriding the\n"
15471 " value provided at module loadtime, whether the channel is in\n"
15472 " use or not. Changes take effect immediately.\n"
15473 " <rx|tx> which direction do you want to change (relative to our module)\n"
15474 " <chan num> is the channel number relative to the device\n"
15475 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15476 return NULL;
15477 case CLI_GENERATE:
15478 return NULL;
15479 }
15480
15481 if (a->argc != 6)
15482 return CLI_SHOWUSAGE;
15483
15484 if (!strcasecmp("rx", a->argv[3]))
15485 tx = 0;
15486 else if (!strcasecmp("tx", a->argv[3]))
15487 tx = 1;
15488 else
15489 return CLI_SHOWUSAGE;
15490
15491 channel = atoi(a->argv[4]);
15492 gain = atof(a->argv[5])*10.0;
15493
15494 ast_mutex_lock(&iflock);
15495
15496 for (tmp = iflist; tmp; tmp = tmp->next) {
15497
15498 if (tmp->channel != channel)
15499 continue;
15500
15501 if (tmp->subs[SUB_REAL].dfd == -1)
15502 break;
15503
15504 hwgain.newgain = gain;
15505 hwgain.tx = tx;
15506 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15507 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15508 ast_mutex_unlock(&iflock);
15509 return CLI_FAILURE;
15510 }
15511 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15512 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15513 break;
15514 }
15515
15516 ast_mutex_unlock(&iflock);
15517
15518 if (tmp)
15519 return CLI_SUCCESS;
15520
15521 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15522 return CLI_FAILURE;
15523
15524 }
15525
15526 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15527 {
15528 int channel;
15529 float gain;
15530 int tx;
15531 int res;
15532 struct dahdi_pvt *tmp = NULL;
15533
15534 switch (cmd) {
15535 case CLI_INIT:
15536 e->command = "dahdi set swgain";
15537 e->usage =
15538 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15539 " Sets the software gain on a a given channel, overriding the\n"
15540 " value provided at module loadtime, whether the channel is in\n"
15541 " use or not. Changes take effect immediately.\n"
15542 " <rx|tx> which direction do you want to change (relative to our module)\n"
15543 " <chan num> is the channel number relative to the device\n"
15544 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15545 return NULL;
15546 case CLI_GENERATE:
15547 return NULL;
15548 }
15549
15550 if (a->argc != 6)
15551 return CLI_SHOWUSAGE;
15552
15553 if (!strcasecmp("rx", a->argv[3]))
15554 tx = 0;
15555 else if (!strcasecmp("tx", a->argv[3]))
15556 tx = 1;
15557 else
15558 return CLI_SHOWUSAGE;
15559
15560 channel = atoi(a->argv[4]);
15561 gain = atof(a->argv[5]);
15562
15563 ast_mutex_lock(&iflock);
15564 for (tmp = iflist; tmp; tmp = tmp->next) {
15565
15566 if (tmp->channel != channel)
15567 continue;
15568
15569 if (tmp->subs[SUB_REAL].dfd == -1)
15570 break;
15571
15572 if (tx)
15573 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15574 else
15575 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15576
15577 if (res) {
15578 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15579 ast_mutex_unlock(&iflock);
15580 return CLI_FAILURE;
15581 }
15582
15583 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15584 tx ? "tx" : "rx", gain, channel);
15585 break;
15586 }
15587 ast_mutex_unlock(&iflock);
15588
15589 if (tmp)
15590 return CLI_SUCCESS;
15591
15592 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15593 return CLI_FAILURE;
15594
15595 }
15596
15597 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15598 {
15599 int channel;
15600 int on;
15601 struct dahdi_pvt *dahdi_chan = NULL;
15602
15603 switch (cmd) {
15604 case CLI_INIT:
15605 e->command = "dahdi set dnd";
15606 e->usage =
15607 "Usage: dahdi set dnd <chan#> <on|off>\n"
15608 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15609 " Changes take effect immediately.\n"
15610 " <chan num> is the channel number\n"
15611 " <on|off> Enable or disable DND mode?\n"
15612 ;
15613 return NULL;
15614 case CLI_GENERATE:
15615 return NULL;
15616 }
15617
15618 if (a->argc != 5)
15619 return CLI_SHOWUSAGE;
15620
15621 if ((channel = atoi(a->argv[3])) <= 0) {
15622 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15623 return CLI_SHOWUSAGE;
15624 }
15625
15626 if (ast_true(a->argv[4]))
15627 on = 1;
15628 else if (ast_false(a->argv[4]))
15629 on = 0;
15630 else {
15631 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15632 return CLI_SHOWUSAGE;
15633 }
15634
15635 ast_mutex_lock(&iflock);
15636 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15637 if (dahdi_chan->channel != channel)
15638 continue;
15639
15640
15641 dahdi_dnd(dahdi_chan, on);
15642 break;
15643 }
15644 ast_mutex_unlock(&iflock);
15645
15646 if (!dahdi_chan) {
15647 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15648 return CLI_FAILURE;
15649 }
15650
15651 return CLI_SUCCESS;
15652 }
15653
15654 static struct ast_cli_entry dahdi_cli[] = {
15655 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15656 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15657 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15658 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15659 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15660 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15661 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15662 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15663 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15664 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15665 };
15666
15667 #define TRANSFER 0
15668 #define HANGUP 1
15669
15670 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15671 {
15672 if (p) {
15673 switch (mode) {
15674 case TRANSFER:
15675 p->fake_event = DAHDI_EVENT_WINKFLASH;
15676 break;
15677 case HANGUP:
15678 p->fake_event = DAHDI_EVENT_ONHOOK;
15679 break;
15680 default:
15681 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15682 }
15683 }
15684 return 0;
15685 }
15686 static struct dahdi_pvt *find_channel(int channel)
15687 {
15688 struct dahdi_pvt *p;
15689
15690 ast_mutex_lock(&iflock);
15691 for (p = iflist; p; p = p->next) {
15692 if (p->channel == channel) {
15693 break;
15694 }
15695 }
15696 ast_mutex_unlock(&iflock);
15697 return p;
15698 }
15699
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15710 {
15711 int chan_num;
15712
15713 if (sscanf(channel, "%30d", &chan_num) != 1) {
15714
15715 return NULL;
15716 }
15717
15718 return find_channel(chan_num);
15719 }
15720
15721 static int action_dahdidndon(struct mansession *s, const struct message *m)
15722 {
15723 struct dahdi_pvt *p;
15724 const char *channel = astman_get_header(m, "DAHDIChannel");
15725
15726 if (ast_strlen_zero(channel)) {
15727 astman_send_error(s, m, "No channel specified");
15728 return 0;
15729 }
15730 p = find_channel_from_str(channel);
15731 if (!p) {
15732 astman_send_error(s, m, "No such channel");
15733 return 0;
15734 }
15735 dahdi_dnd(p, 1);
15736 astman_send_ack(s, m, "DND Enabled");
15737 return 0;
15738 }
15739
15740 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15741 {
15742 struct dahdi_pvt *p;
15743 const char *channel = astman_get_header(m, "DAHDIChannel");
15744
15745 if (ast_strlen_zero(channel)) {
15746 astman_send_error(s, m, "No channel specified");
15747 return 0;
15748 }
15749 p = find_channel_from_str(channel);
15750 if (!p) {
15751 astman_send_error(s, m, "No such channel");
15752 return 0;
15753 }
15754 dahdi_dnd(p, 0);
15755 astman_send_ack(s, m, "DND Disabled");
15756 return 0;
15757 }
15758
15759 static int action_transfer(struct mansession *s, const struct message *m)
15760 {
15761 struct dahdi_pvt *p;
15762 const char *channel = astman_get_header(m, "DAHDIChannel");
15763
15764 if (ast_strlen_zero(channel)) {
15765 astman_send_error(s, m, "No channel specified");
15766 return 0;
15767 }
15768 p = find_channel_from_str(channel);
15769 if (!p) {
15770 astman_send_error(s, m, "No such channel");
15771 return 0;
15772 }
15773 if (!analog_lib_handles(p->sig, 0, 0)) {
15774 astman_send_error(s, m, "Channel signaling is not analog");
15775 return 0;
15776 }
15777 dahdi_fake_event(p,TRANSFER);
15778 astman_send_ack(s, m, "DAHDITransfer");
15779 return 0;
15780 }
15781
15782 static int action_transferhangup(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,HANGUP);
15801 astman_send_ack(s, m, "DAHDIHangup");
15802 return 0;
15803 }
15804
15805 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15806 {
15807 struct dahdi_pvt *p;
15808 const char *channel = astman_get_header(m, "DAHDIChannel");
15809 const char *number = astman_get_header(m, "Number");
15810 int i;
15811
15812 if (ast_strlen_zero(channel)) {
15813 astman_send_error(s, m, "No channel specified");
15814 return 0;
15815 }
15816 if (ast_strlen_zero(number)) {
15817 astman_send_error(s, m, "No number specified");
15818 return 0;
15819 }
15820 p = find_channel_from_str(channel);
15821 if (!p) {
15822 astman_send_error(s, m, "No such channel");
15823 return 0;
15824 }
15825 if (!p->owner) {
15826 astman_send_error(s, m, "Channel does not have it's owner");
15827 return 0;
15828 }
15829 for (i = 0; i < strlen(number); i++) {
15830 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15831 dahdi_queue_frame(p, &f);
15832 }
15833 astman_send_ack(s, m, "DAHDIDialOffhook");
15834 return 0;
15835 }
15836
15837 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15838 {
15839 struct dahdi_pvt *tmp = NULL;
15840 const char *id = astman_get_header(m, "ActionID");
15841 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15842 char idText[256] = "";
15843 int channels = 0;
15844 int dahdichanquery;
15845
15846 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
15847
15848 dahdichanquery = -1;
15849 }
15850
15851 astman_send_ack(s, m, "DAHDI channel status will follow");
15852 if (!ast_strlen_zero(id))
15853 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15854
15855 ast_mutex_lock(&iflock);
15856
15857 for (tmp = iflist; tmp; tmp = tmp->next) {
15858 if (tmp->channel > 0) {
15859 int alm;
15860
15861
15862 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15863 continue;
15864
15865 alm = get_alarms(tmp);
15866 channels++;
15867 if (tmp->owner) {
15868
15869 astman_append(s,
15870 "Event: DAHDIShowChannels\r\n"
15871 "DAHDIChannel: %d\r\n"
15872 "Channel: %s\r\n"
15873 "Uniqueid: %s\r\n"
15874 "AccountCode: %s\r\n"
15875 "Signalling: %s\r\n"
15876 "SignallingCode: %d\r\n"
15877 "Context: %s\r\n"
15878 "DND: %s\r\n"
15879 "Alarm: %s\r\n"
15880 "%s"
15881 "\r\n",
15882 tmp->channel,
15883 tmp->owner->name,
15884 tmp->owner->uniqueid,
15885 tmp->owner->accountcode,
15886 sig2str(tmp->sig),
15887 tmp->sig,
15888 tmp->context,
15889 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15890 alarm2str(alm), idText);
15891 } else {
15892 astman_append(s,
15893 "Event: DAHDIShowChannels\r\n"
15894 "DAHDIChannel: %d\r\n"
15895 "Signalling: %s\r\n"
15896 "SignallingCode: %d\r\n"
15897 "Context: %s\r\n"
15898 "DND: %s\r\n"
15899 "Alarm: %s\r\n"
15900 "%s"
15901 "\r\n",
15902 tmp->channel, sig2str(tmp->sig), tmp->sig,
15903 tmp->context,
15904 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15905 alarm2str(alm), idText);
15906 }
15907 }
15908 }
15909
15910 ast_mutex_unlock(&iflock);
15911
15912 astman_append(s,
15913 "Event: DAHDIShowChannelsComplete\r\n"
15914 "%s"
15915 "Items: %d\r\n"
15916 "\r\n",
15917 idText,
15918 channels);
15919 return 0;
15920 }
15921
15922 #if defined(HAVE_SS7)
15923 static int linkset_addsigchan(int sigchan)
15924 {
15925 struct dahdi_ss7 *link;
15926 int res;
15927 int curfd;
15928 struct dahdi_params params;
15929 struct dahdi_bufferinfo bi;
15930 struct dahdi_spaninfo si;
15931
15932 if (sigchan < 0) {
15933 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15934 return -1;
15935 }
15936 if (cur_ss7type < 0) {
15937 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15938 return -1;
15939 }
15940 if (cur_pointcode < 0) {
15941 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15942 return -1;
15943 }
15944 if (cur_adjpointcode < 0) {
15945 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15946 return -1;
15947 }
15948 if (cur_defaultdpc < 0) {
15949 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15950 return -1;
15951 }
15952 if (cur_networkindicator < 0) {
15953 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15954 return -1;
15955 }
15956 link = ss7_resolve_linkset(cur_linkset);
15957 if (!link) {
15958 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15959 return -1;
15960 }
15961 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15962 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15963 return -1;
15964 }
15965
15966 curfd = link->ss7.numsigchans;
15967
15968
15969 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15970 if (link->ss7.fds[curfd] < 0) {
15971 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15972 strerror(errno));
15973 return -1;
15974 }
15975 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15976 dahdi_close_ss7_fd(link, curfd);
15977 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15978 strerror(errno));
15979 return -1;
15980 }
15981
15982
15983 memset(¶ms, 0, sizeof(params));
15984 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
15985 if (res) {
15986 dahdi_close_ss7_fd(link, curfd);
15987 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15988 strerror(errno));
15989 return -1;
15990 }
15991 if (params.sigtype != DAHDI_SIG_HDLCFCS
15992 && params.sigtype != DAHDI_SIG_HARDHDLC
15993 && params.sigtype != DAHDI_SIG_MTP2) {
15994 dahdi_close_ss7_fd(link, curfd);
15995 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15996 return -1;
15997 }
15998
15999
16000 memset(&bi, 0, sizeof(bi));
16001 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16002 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16003 bi.numbufs = 32;
16004 bi.bufsize = 512;
16005 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16006 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16007 sigchan, strerror(errno));
16008 dahdi_close_ss7_fd(link, curfd);
16009 return -1;
16010 }
16011
16012
16013 memset(&si, 0, sizeof(si));
16014 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16015 if (res) {
16016 dahdi_close_ss7_fd(link, curfd);
16017 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16018 strerror(errno));
16019 }
16020
16021 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16022 (params.sigtype == DAHDI_SIG_MTP2)
16023 ? SS7_TRANSPORT_DAHDIMTP2
16024 : SS7_TRANSPORT_DAHDIDCHAN,
16025 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16026 if (res) {
16027 dahdi_close_ss7_fd(link, curfd);
16028 return -1;
16029 }
16030
16031 ++link->ss7.numsigchans;
16032
16033 return 0;
16034 }
16035 #endif
16036
16037 #if defined(HAVE_SS7)
16038 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16039 {
16040 int span;
16041 switch (cmd) {
16042 case CLI_INIT:
16043 e->command = "ss7 set debug {on|off} linkset";
16044 e->usage =
16045 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16046 " Enables debugging on a given SS7 linkset\n";
16047 return NULL;
16048 case CLI_GENERATE:
16049 return NULL;
16050 }
16051 if (a->argc < 6)
16052 return CLI_SHOWUSAGE;
16053 span = atoi(a->argv[5]);
16054 if ((span < 1) || (span > NUM_SPANS)) {
16055 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16056 return CLI_SUCCESS;
16057 }
16058 if (!linksets[span-1].ss7.ss7) {
16059 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16060 } else {
16061 if (!strcasecmp(a->argv[3], "on")) {
16062 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16063 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16064 } else {
16065 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16066 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16067 }
16068 }
16069
16070 return CLI_SUCCESS;
16071 }
16072 #endif
16073
16074 #if defined(HAVE_SS7)
16075 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16076 {
16077 int linkset, cic;
16078 int blocked = -1, i;
16079 switch (cmd) {
16080 case CLI_INIT:
16081 e->command = "ss7 block cic";
16082 e->usage =
16083 "Usage: ss7 block cic <linkset> <CIC>\n"
16084 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16085 return NULL;
16086 case CLI_GENERATE:
16087 return NULL;
16088 }
16089 if (a->argc == 5)
16090 linkset = atoi(a->argv[3]);
16091 else
16092 return CLI_SHOWUSAGE;
16093
16094 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16095 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16096 return CLI_SUCCESS;
16097 }
16098
16099 if (!linksets[linkset-1].ss7.ss7) {
16100 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16101 return CLI_SUCCESS;
16102 }
16103
16104 cic = atoi(a->argv[4]);
16105
16106 if (cic < 1) {
16107 ast_cli(a->fd, "Invalid CIC specified!\n");
16108 return CLI_SUCCESS;
16109 }
16110
16111 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16112 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16113 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16114 if (!blocked) {
16115 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16116 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16117 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16118 }
16119 }
16120 }
16121
16122 if (blocked < 0) {
16123 ast_cli(a->fd, "Invalid CIC specified!\n");
16124 return CLI_SUCCESS;
16125 }
16126
16127 if (!blocked)
16128 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16129 else
16130 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16131
16132
16133 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16134
16135 return CLI_SUCCESS;
16136 }
16137 #endif
16138
16139 #if defined(HAVE_SS7)
16140 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16141 {
16142 int linkset;
16143 int i;
16144 switch (cmd) {
16145 case CLI_INIT:
16146 e->command = "ss7 block linkset";
16147 e->usage =
16148 "Usage: ss7 block linkset <linkset number>\n"
16149 " Sends a remote blocking request for all CICs on the given linkset\n";
16150 return NULL;
16151 case CLI_GENERATE:
16152 return NULL;
16153 }
16154 if (a->argc == 4)
16155 linkset = atoi(a->argv[3]);
16156 else
16157 return CLI_SHOWUSAGE;
16158
16159 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16160 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16161 return CLI_SUCCESS;
16162 }
16163
16164 if (!linksets[linkset-1].ss7.ss7) {
16165 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16166 return CLI_SUCCESS;
16167 }
16168
16169 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16170 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16171 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16172 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16173 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16174 }
16175
16176
16177 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16178
16179 return CLI_SUCCESS;
16180 }
16181 #endif
16182
16183 #if defined(HAVE_SS7)
16184 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16185 {
16186 int linkset, cic;
16187 int i, blocked = -1;
16188 switch (cmd) {
16189 case CLI_INIT:
16190 e->command = "ss7 unblock cic";
16191 e->usage =
16192 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16193 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16194 return NULL;
16195 case CLI_GENERATE:
16196 return NULL;
16197 }
16198
16199 if (a->argc == 5)
16200 linkset = atoi(a->argv[3]);
16201 else
16202 return CLI_SHOWUSAGE;
16203
16204 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16205 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16206 return CLI_SUCCESS;
16207 }
16208
16209 if (!linksets[linkset-1].ss7.ss7) {
16210 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16211 return CLI_SUCCESS;
16212 }
16213
16214 cic = atoi(a->argv[4]);
16215
16216 if (cic < 1) {
16217 ast_cli(a->fd, "Invalid CIC specified!\n");
16218 return CLI_SUCCESS;
16219 }
16220
16221 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16222 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16223 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16224 if (blocked) {
16225 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16226 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16227 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16228 }
16229 }
16230 }
16231
16232 if (blocked > 0)
16233 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16234
16235
16236 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16237
16238 return CLI_SUCCESS;
16239 }
16240 #endif
16241
16242 #if defined(HAVE_SS7)
16243 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16244 {
16245 int linkset;
16246 int i;
16247 switch (cmd) {
16248 case CLI_INIT:
16249 e->command = "ss7 unblock linkset";
16250 e->usage =
16251 "Usage: ss7 unblock linkset <linkset number>\n"
16252 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16253 return NULL;
16254 case CLI_GENERATE:
16255 return NULL;
16256 }
16257
16258 if (a->argc == 4)
16259 linkset = atoi(a->argv[3]);
16260 else
16261 return CLI_SHOWUSAGE;
16262
16263 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16264 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16265 return CLI_SUCCESS;
16266 }
16267
16268 if (!linksets[linkset-1].ss7.ss7) {
16269 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16270 return CLI_SUCCESS;
16271 }
16272
16273 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16274 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16275 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16276 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16277 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16278 }
16279
16280
16281 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16282
16283 return CLI_SUCCESS;
16284 }
16285 #endif
16286
16287 #if defined(HAVE_SS7)
16288 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16289 {
16290 int linkset;
16291 struct sig_ss7_linkset *ss7;
16292 switch (cmd) {
16293 case CLI_INIT:
16294 e->command = "ss7 show linkset";
16295 e->usage =
16296 "Usage: ss7 show linkset <span>\n"
16297 " Shows the status of an SS7 linkset.\n";
16298 return NULL;
16299 case CLI_GENERATE:
16300 return NULL;
16301 }
16302
16303 if (a->argc < 4)
16304 return CLI_SHOWUSAGE;
16305 linkset = atoi(a->argv[3]);
16306 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16307 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16308 return CLI_SUCCESS;
16309 }
16310 ss7 = &linksets[linkset - 1].ss7;
16311 if (!ss7->ss7) {
16312 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16313 return CLI_SUCCESS;
16314 }
16315
16316 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16317
16318 return CLI_SUCCESS;
16319 }
16320 #endif
16321
16322 #if defined(HAVE_SS7)
16323 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16324 {
16325 switch (cmd) {
16326 case CLI_INIT:
16327 e->command = "ss7 show version";
16328 e->usage =
16329 "Usage: ss7 show version\n"
16330 " Show the libss7 version\n";
16331 return NULL;
16332 case CLI_GENERATE:
16333 return NULL;
16334 }
16335
16336 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16337
16338 return CLI_SUCCESS;
16339 }
16340 #endif
16341
16342 #if defined(HAVE_SS7)
16343 static struct ast_cli_entry dahdi_ss7_cli[] = {
16344 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16345 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16346 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16347 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16348 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16349 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16350 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16351 };
16352 #endif
16353
16354 #if defined(HAVE_PRI)
16355 #if defined(HAVE_PRI_CCSS)
16356
16357
16358
16359
16360
16361
16362
16363
16364
16365
16366
16367
16368
16369
16370
16371
16372
16373 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16374 {
16375 struct dahdi_pvt *pvt;
16376 struct sig_pri_chan *pvt_chan;
16377 int res;
16378
16379 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16380
16381 pvt = chan->tech_pvt;
16382 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16383 pvt_chan = pvt->sig_pvt;
16384 } else {
16385 pvt_chan = NULL;
16386 }
16387 if (!pvt_chan) {
16388 return -1;
16389 }
16390
16391 ast_module_ref(ast_module_info->self);
16392
16393 res = sig_pri_cc_agent_init(agent, pvt_chan);
16394 if (res) {
16395 ast_module_unref(ast_module_info->self);
16396 }
16397 return res;
16398 }
16399 #endif
16400 #endif
16401
16402 #if defined(HAVE_PRI)
16403 #if defined(HAVE_PRI_CCSS)
16404
16405
16406
16407
16408
16409
16410
16411
16412
16413
16414
16415
16416
16417 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16418 {
16419 sig_pri_cc_agent_destructor(agent);
16420
16421 ast_module_unref(ast_module_info->self);
16422 }
16423 #endif
16424 #endif
16425
16426 #if defined(HAVE_PRI)
16427 #if defined(HAVE_PRI_CCSS)
16428 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16429 .type = dahdi_pri_cc_type,
16430 .init = dahdi_pri_cc_agent_init,
16431 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16432 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16433 .respond = sig_pri_cc_agent_req_rsp,
16434 .status_request = sig_pri_cc_agent_status_req,
16435 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16436 .party_b_free = sig_pri_cc_agent_party_b_free,
16437 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16438 .callee_available = sig_pri_cc_agent_callee_available,
16439 .destructor = dahdi_pri_cc_agent_destructor,
16440 };
16441 #endif
16442 #endif
16443
16444 #if defined(HAVE_PRI)
16445 #if defined(HAVE_PRI_CCSS)
16446 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16447 .type = dahdi_pri_cc_type,
16448 .request_cc = sig_pri_cc_monitor_req_cc,
16449 .suspend = sig_pri_cc_monitor_suspend,
16450 .unsuspend = sig_pri_cc_monitor_unsuspend,
16451 .status_response = sig_pri_cc_monitor_status_rsp,
16452 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16453 .destructor = sig_pri_cc_monitor_destructor,
16454 };
16455 #endif
16456 #endif
16457
16458 static int __unload_module(void)
16459 {
16460 struct dahdi_pvt *p;
16461 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16462 int i, j;
16463 #endif
16464
16465 #ifdef HAVE_PRI
16466 for (i = 0; i < NUM_SPANS; i++) {
16467 if (pris[i].pri.master != AST_PTHREADT_NULL)
16468 pthread_cancel(pris[i].pri.master);
16469 }
16470 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16471 ast_unregister_application(dahdi_send_keypad_facility_app);
16472 #ifdef HAVE_PRI_PROG_W_CAUSE
16473 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16474 #endif
16475 #endif
16476 #if defined(HAVE_SS7)
16477 for (i = 0; i < NUM_SPANS; i++) {
16478 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16479 pthread_cancel(linksets[i].ss7.master);
16480 }
16481 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16482 #endif
16483 #if defined(HAVE_OPENR2)
16484 dahdi_r2_destroy_links();
16485 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16486 ast_unregister_application(dahdi_accept_r2_call_app);
16487 #endif
16488
16489 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16490 ast_manager_unregister("DAHDIDialOffhook");
16491 ast_manager_unregister("DAHDIHangup");
16492 ast_manager_unregister("DAHDITransfer");
16493 ast_manager_unregister("DAHDIDNDoff");
16494 ast_manager_unregister("DAHDIDNDon");
16495 ast_manager_unregister("DAHDIShowChannels");
16496 ast_manager_unregister("DAHDIRestart");
16497 ast_data_unregister(NULL);
16498 ast_channel_unregister(&dahdi_tech);
16499
16500
16501 ast_mutex_lock(&iflock);
16502 for (p = iflist; p; p = p->next) {
16503 if (p->owner)
16504 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16505 }
16506 ast_mutex_unlock(&iflock);
16507
16508 ast_mutex_lock(&monlock);
16509 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16510 pthread_cancel(monitor_thread);
16511 pthread_kill(monitor_thread, SIGURG);
16512 pthread_join(monitor_thread, NULL);
16513 }
16514 monitor_thread = AST_PTHREADT_STOP;
16515 ast_mutex_unlock(&monlock);
16516
16517 destroy_all_channels();
16518
16519 #if defined(HAVE_PRI)
16520 for (i = 0; i < NUM_SPANS; i++) {
16521 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16522 pthread_join(pris[i].pri.master, NULL);
16523 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16524 dahdi_close_pri_fd(&(pris[i]), j);
16525 }
16526 sig_pri_stop_pri(&pris[i].pri);
16527 }
16528 #if defined(HAVE_PRI_CCSS)
16529 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16530 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16531 #endif
16532 sig_pri_unload();
16533 #endif
16534
16535 #if defined(HAVE_SS7)
16536 for (i = 0; i < NUM_SPANS; i++) {
16537 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16538 pthread_join(linksets[i].ss7.master, NULL);
16539 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16540 dahdi_close_ss7_fd(&(linksets[i]), j);
16541 }
16542 }
16543 #endif
16544 ast_cond_destroy(&ss_thread_complete);
16545 return 0;
16546 }
16547
16548 static int unload_module(void)
16549 {
16550 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16551 int y;
16552 #endif
16553 #ifdef HAVE_PRI
16554 for (y = 0; y < NUM_SPANS; y++)
16555 ast_mutex_destroy(&pris[y].pri.lock);
16556 #endif
16557 #if defined(HAVE_SS7)
16558 for (y = 0; y < NUM_SPANS; y++)
16559 ast_mutex_destroy(&linksets[y].ss7.lock);
16560 #endif
16561 return __unload_module();
16562 }
16563
16564 static void string_replace(char *str, int char1, int char2)
16565 {
16566 for (; *str; str++) {
16567 if (*str == char1) {
16568 *str = char2;
16569 }
16570 }
16571 }
16572
16573 static char *parse_spanchan(char *chanstr, char **subdir)
16574 {
16575 char *p;
16576
16577 if ((p = strrchr(chanstr, '!')) == NULL) {
16578 *subdir = NULL;
16579 return chanstr;
16580 }
16581 *p++ = '\0';
16582 string_replace(chanstr, '!', '/');
16583 *subdir = chanstr;
16584 return p;
16585 }
16586
16587 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16588 {
16589 char *c, *chan;
16590 char *subdir;
16591 int x, start, finish;
16592 struct dahdi_pvt *tmp;
16593
16594 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16595 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16596 return -1;
16597 }
16598
16599 c = ast_strdupa(value);
16600 c = parse_spanchan(c, &subdir);
16601
16602 while ((chan = strsep(&c, ","))) {
16603 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16604
16605 } else if (sscanf(chan, "%30d", &start)) {
16606
16607 finish = start;
16608 } else if (!strcasecmp(chan, "pseudo")) {
16609 finish = start = CHAN_PSEUDO;
16610 if (found_pseudo)
16611 *found_pseudo = 1;
16612 } else {
16613 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16614 return -1;
16615 }
16616 if (finish < start) {
16617 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16618 x = finish;
16619 finish = start;
16620 start = x;
16621 }
16622
16623 for (x = start; x <= finish; x++) {
16624 char fn[PATH_MAX];
16625 int real_channel = x;
16626
16627 if (!ast_strlen_zero(subdir)) {
16628 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16629 if (real_channel < 0) {
16630 if (conf->ignore_failed_channels) {
16631 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16632 subdir, x, real_channel);
16633 continue;
16634 } else {
16635 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16636 subdir, x, real_channel);
16637 return -1;
16638 }
16639 }
16640 }
16641 tmp = mkintf(real_channel, conf, reload);
16642
16643 if (tmp) {
16644 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16645 } else {
16646 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16647 (reload == 1) ? "reconfigure" : "register", value);
16648 return -1;
16649 }
16650 }
16651 }
16652
16653 return 0;
16654 }
16655
16656
16657
16658 #define MAX_CHANLIST_LEN 80
16659
16660 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16661 {
16662 char *parse = ast_strdupa(data);
16663 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16664 unsigned int param_count;
16665 unsigned int x;
16666
16667 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16668 return;
16669
16670 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16671
16672
16673
16674 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16675
16676 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16677 confp->chan.echocancel.head.tap_length = x;
16678 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16679 confp->chan.echocancel.head.tap_length = 128;
16680
16681
16682
16683 for (x = 1; x < param_count; x++) {
16684 struct {
16685 char *name;
16686 char *value;
16687 } param;
16688
16689 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16690 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16691 continue;
16692 }
16693
16694 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16695 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16696 continue;
16697 }
16698
16699 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16700
16701 if (param.value) {
16702 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16703 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16704 continue;
16705 }
16706 }
16707 confp->chan.echocancel.head.param_count++;
16708 }
16709 }
16710
16711
16712 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16713
16714 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16715
16716 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16717 {
16718 struct dahdi_pvt *tmp;
16719 int y;
16720 int found_pseudo = 0;
16721 struct ast_variable *dahdichan = NULL;
16722
16723 for (; v; v = v->next) {
16724 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16725 continue;
16726
16727
16728 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16729 if (options & PROC_DAHDI_OPT_NOCHAN) {
16730 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16731 continue;
16732 }
16733 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16734 if (confp->ignore_failed_channels) {
16735 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16736 continue;
16737 } else {
16738 return -1;
16739 }
16740 }
16741 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16742 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16743 confp->ignore_failed_channels = ast_true(v->value);
16744 } else if (!strcasecmp(v->name, "buffers")) {
16745 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16746 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16747 confp->chan.buf_no = numbufs;
16748 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16749 }
16750 } else if (!strcasecmp(v->name, "faxbuffers")) {
16751 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16752 confp->chan.usefaxbuffers = 1;
16753 }
16754 } else if (!strcasecmp(v->name, "dahdichan")) {
16755
16756 dahdichan = v;
16757 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16758 usedistinctiveringdetection = ast_true(v->value);
16759 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16760 distinctiveringaftercid = ast_true(v->value);
16761 } else if (!strcasecmp(v->name, "dring1context")) {
16762 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16763 } else if (!strcasecmp(v->name, "dring2context")) {
16764 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16765 } else if (!strcasecmp(v->name, "dring3context")) {
16766 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16767 } else if (!strcasecmp(v->name, "dring1range")) {
16768 confp->chan.drings.ringnum[0].range = atoi(v->value);
16769 } else if (!strcasecmp(v->name, "dring2range")) {
16770 confp->chan.drings.ringnum[1].range = atoi(v->value);
16771 } else if (!strcasecmp(v->name, "dring3range")) {
16772 confp->chan.drings.ringnum[2].range = atoi(v->value);
16773 } else if (!strcasecmp(v->name, "dring1")) {
16774 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]);
16775 } else if (!strcasecmp(v->name, "dring2")) {
16776 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]);
16777 } else if (!strcasecmp(v->name, "dring3")) {
16778 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]);
16779 } else if (!strcasecmp(v->name, "usecallerid")) {
16780 confp->chan.use_callerid = ast_true(v->value);
16781 } else if (!strcasecmp(v->name, "cidsignalling")) {
16782 if (!strcasecmp(v->value, "bell"))
16783 confp->chan.cid_signalling = CID_SIG_BELL;
16784 else if (!strcasecmp(v->value, "v23"))
16785 confp->chan.cid_signalling = CID_SIG_V23;
16786 else if (!strcasecmp(v->value, "dtmf"))
16787 confp->chan.cid_signalling = CID_SIG_DTMF;
16788 else if (!strcasecmp(v->value, "smdi"))
16789 confp->chan.cid_signalling = CID_SIG_SMDI;
16790 else if (!strcasecmp(v->value, "v23_jp"))
16791 confp->chan.cid_signalling = CID_SIG_V23_JP;
16792 else if (ast_true(v->value))
16793 confp->chan.cid_signalling = CID_SIG_BELL;
16794 } else if (!strcasecmp(v->name, "cidstart")) {
16795 if (!strcasecmp(v->value, "ring"))
16796 confp->chan.cid_start = CID_START_RING;
16797 else if (!strcasecmp(v->value, "polarity_in"))
16798 confp->chan.cid_start = CID_START_POLARITY_IN;
16799 else if (!strcasecmp(v->value, "polarity"))
16800 confp->chan.cid_start = CID_START_POLARITY;
16801 else if (!strcasecmp(v->value, "dtmf"))
16802 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16803 else if (ast_true(v->value))
16804 confp->chan.cid_start = CID_START_RING;
16805 } else if (!strcasecmp(v->name, "threewaycalling")) {
16806 confp->chan.threewaycalling = ast_true(v->value);
16807 } else if (!strcasecmp(v->name, "cancallforward")) {
16808 confp->chan.cancallforward = ast_true(v->value);
16809 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16810 if (ast_true(v->value))
16811 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16812 else
16813 confp->chan.dtmfrelax = 0;
16814 } else if (!strcasecmp(v->name, "mailbox")) {
16815 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16816 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16817 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16818 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16819 }
16820 } else if (!strcasecmp(v->name, "adsi")) {
16821 confp->chan.adsi = ast_true(v->value);
16822 } else if (!strcasecmp(v->name, "usesmdi")) {
16823 confp->chan.use_smdi = ast_true(v->value);
16824 } else if (!strcasecmp(v->name, "smdiport")) {
16825 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16826 } else if (!strcasecmp(v->name, "transfer")) {
16827 confp->chan.transfer = ast_true(v->value);
16828 } else if (!strcasecmp(v->name, "canpark")) {
16829 confp->chan.canpark = ast_true(v->value);
16830 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16831 confp->chan.echocanbridged = ast_true(v->value);
16832 } else if (!strcasecmp(v->name, "busydetect")) {
16833 confp->chan.busydetect = ast_true(v->value);
16834 } else if (!strcasecmp(v->name, "busycount")) {
16835 confp->chan.busycount = atoi(v->value);
16836 } else if (!strcasecmp(v->name, "busypattern")) {
16837 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16838 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16839 }
16840 } else if (!strcasecmp(v->name, "callprogress")) {
16841 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16842 if (ast_true(v->value))
16843 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16844 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16845 confp->chan.waitfordialtone = atoi(v->value);
16846 } else if (!strcasecmp(v->name, "faxdetect")) {
16847 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16848 if (!strcasecmp(v->value, "incoming")) {
16849 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16850 } else if (!strcasecmp(v->value, "outgoing")) {
16851 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16852 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16853 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16854 } else if (!strcasecmp(v->name, "echocancel")) {
16855 process_echocancel(confp, v->value, v->lineno);
16856 } else if (!strcasecmp(v->name, "echotraining")) {
16857 if (sscanf(v->value, "%30d", &y) == 1) {
16858 if ((y < 10) || (y > 4000)) {
16859 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16860 } else {
16861 confp->chan.echotraining = y;
16862 }
16863 } else if (ast_true(v->value)) {
16864 confp->chan.echotraining = 400;
16865 } else
16866 confp->chan.echotraining = 0;
16867 } else if (!strcasecmp(v->name, "hidecallerid")) {
16868 confp->chan.hidecallerid = ast_true(v->value);
16869 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16870 confp->chan.hidecalleridname = ast_true(v->value);
16871 } else if (!strcasecmp(v->name, "pulsedial")) {
16872 confp->chan.pulse = ast_true(v->value);
16873 } else if (!strcasecmp(v->name, "callreturn")) {
16874 confp->chan.callreturn = ast_true(v->value);
16875 } else if (!strcasecmp(v->name, "callwaiting")) {
16876 confp->chan.callwaiting = ast_true(v->value);
16877 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16878 confp->chan.callwaitingcallerid = ast_true(v->value);
16879 } else if (!strcasecmp(v->name, "context")) {
16880 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16881 } else if (!strcasecmp(v->name, "language")) {
16882 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16883 } else if (!strcasecmp(v->name, "progzone")) {
16884 ast_copy_string(progzone, v->value, sizeof(progzone));
16885 } else if (!strcasecmp(v->name, "mohinterpret")
16886 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16887 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16888 } else if (!strcasecmp(v->name, "mohsuggest")) {
16889 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16890 } else if (!strcasecmp(v->name, "parkinglot")) {
16891 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16892 } else if (!strcasecmp(v->name, "stripmsd")) {
16893 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16894 confp->chan.stripmsd = atoi(v->value);
16895 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16896 numbufs = atoi(v->value);
16897 } else if (!strcasecmp(v->name, "group")) {
16898 confp->chan.group = ast_get_group(v->value);
16899 } else if (!strcasecmp(v->name, "callgroup")) {
16900 if (!strcasecmp(v->value, "none"))
16901 confp->chan.callgroup = 0;
16902 else
16903 confp->chan.callgroup = ast_get_group(v->value);
16904 } else if (!strcasecmp(v->name, "pickupgroup")) {
16905 if (!strcasecmp(v->value, "none"))
16906 confp->chan.pickupgroup = 0;
16907 else
16908 confp->chan.pickupgroup = ast_get_group(v->value);
16909 } else if (!strcasecmp(v->name, "setvar")) {
16910 char *varname = ast_strdupa(v->value), *varval = NULL;
16911 struct ast_variable *tmpvar;
16912 if (varname && (varval = strchr(varname, '='))) {
16913 *varval++ = '\0';
16914 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16915 tmpvar->next = confp->chan.vars;
16916 confp->chan.vars = tmpvar;
16917 }
16918 }
16919 } else if (!strcasecmp(v->name, "immediate")) {
16920 confp->chan.immediate = ast_true(v->value);
16921 } else if (!strcasecmp(v->name, "transfertobusy")) {
16922 confp->chan.transfertobusy = ast_true(v->value);
16923 } else if (!strcasecmp(v->name, "mwimonitor")) {
16924 confp->chan.mwimonitor_neon = 0;
16925 confp->chan.mwimonitor_fsk = 0;
16926 confp->chan.mwimonitor_rpas = 0;
16927 if (strcasestr(v->value, "fsk")) {
16928 confp->chan.mwimonitor_fsk = 1;
16929 }
16930 if (strcasestr(v->value, "rpas")) {
16931 confp->chan.mwimonitor_rpas = 1;
16932 }
16933 if (strcasestr(v->value, "neon")) {
16934 confp->chan.mwimonitor_neon = 1;
16935 }
16936
16937 if (ast_true(v->value)) {
16938 confp->chan.mwimonitor_fsk = 1;
16939 }
16940 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16941 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16942 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16943 }
16944 } else if (!strcasecmp(v->name, "rxgain")) {
16945 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16946 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16947 }
16948 } else if (!strcasecmp(v->name, "txgain")) {
16949 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16950 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16951 }
16952 } else if (!strcasecmp(v->name, "txdrc")) {
16953 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16954 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16955 }
16956 } else if (!strcasecmp(v->name, "rxdrc")) {
16957 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16958 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16959 }
16960 } else if (!strcasecmp(v->name, "tonezone")) {
16961 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16962 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16963 }
16964 } else if (!strcasecmp(v->name, "callerid")) {
16965 if (!strcasecmp(v->value, "asreceived")) {
16966 confp->chan.cid_num[0] = '\0';
16967 confp->chan.cid_name[0] = '\0';
16968 } else {
16969 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16970 }
16971 } else if (!strcasecmp(v->name, "fullname")) {
16972 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16973 } else if (!strcasecmp(v->name, "cid_number")) {
16974 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16975 } else if (!strcasecmp(v->name, "cid_tag")) {
16976 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16977 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16978 confp->chan.dahditrcallerid = ast_true(v->value);
16979 } else if (!strcasecmp(v->name, "restrictcid")) {
16980 confp->chan.restrictcid = ast_true(v->value);
16981 } else if (!strcasecmp(v->name, "usecallingpres")) {
16982 confp->chan.use_callingpres = ast_true(v->value);
16983 } else if (!strcasecmp(v->name, "accountcode")) {
16984 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16985 } else if (!strcasecmp(v->name, "amaflags")) {
16986 y = ast_cdr_amaflags2int(v->value);
16987 if (y < 0)
16988 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16989 else
16990 confp->chan.amaflags = y;
16991 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16992 confp->chan.polarityonanswerdelay = atoi(v->value);
16993 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16994 confp->chan.answeronpolarityswitch = ast_true(v->value);
16995 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16996 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16997 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16998 confp->chan.sendcalleridafter = atoi(v->value);
16999 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17000 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17001 } else if (ast_cc_is_config_param(v->name)) {
17002 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17003 } else if (!strcasecmp(v->name, "mwisendtype")) {
17004 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17005 if (!strcasecmp(v->value, "rpas")) {
17006 mwisend_rpas = 1;
17007 } else {
17008 mwisend_rpas = 0;
17009 }
17010 #else
17011
17012 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17013 if (strcasestr(v->value, "nofsk")) {
17014 confp->chan.mwisend_fsk = 0;
17015 } else {
17016 confp->chan.mwisend_fsk = 1;
17017 }
17018 if (strcasestr(v->value, "rpas")) {
17019 confp->chan.mwisend_rpas = 1;
17020 } else {
17021 confp->chan.mwisend_rpas = 0;
17022 }
17023 if (strcasestr(v->value, "lrev")) {
17024 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17025 }
17026 if (strcasestr(v->value, "hvdc")) {
17027 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17028 }
17029 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17030 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17031 }
17032 #endif
17033 } else if (reload != 1) {
17034 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17035 int orig_radio = confp->chan.radio;
17036 int orig_outsigmod = confp->chan.outsigmod;
17037 int orig_auto = confp->is_sig_auto;
17038
17039 confp->chan.radio = 0;
17040 confp->chan.outsigmod = -1;
17041 confp->is_sig_auto = 0;
17042 if (!strcasecmp(v->value, "em")) {
17043 confp->chan.sig = SIG_EM;
17044 } else if (!strcasecmp(v->value, "em_e1")) {
17045 confp->chan.sig = SIG_EM_E1;
17046 } else if (!strcasecmp(v->value, "em_w")) {
17047 confp->chan.sig = SIG_EMWINK;
17048 } else if (!strcasecmp(v->value, "fxs_ls")) {
17049 confp->chan.sig = SIG_FXSLS;
17050 } else if (!strcasecmp(v->value, "fxs_gs")) {
17051 confp->chan.sig = SIG_FXSGS;
17052 } else if (!strcasecmp(v->value, "fxs_ks")) {
17053 confp->chan.sig = SIG_FXSKS;
17054 } else if (!strcasecmp(v->value, "fxo_ls")) {
17055 confp->chan.sig = SIG_FXOLS;
17056 } else if (!strcasecmp(v->value, "fxo_gs")) {
17057 confp->chan.sig = SIG_FXOGS;
17058 } else if (!strcasecmp(v->value, "fxo_ks")) {
17059 confp->chan.sig = SIG_FXOKS;
17060 } else if (!strcasecmp(v->value, "fxs_rx")) {
17061 confp->chan.sig = SIG_FXSKS;
17062 confp->chan.radio = 1;
17063 } else if (!strcasecmp(v->value, "fxo_rx")) {
17064 confp->chan.sig = SIG_FXOLS;
17065 confp->chan.radio = 1;
17066 } else if (!strcasecmp(v->value, "fxs_tx")) {
17067 confp->chan.sig = SIG_FXSLS;
17068 confp->chan.radio = 1;
17069 } else if (!strcasecmp(v->value, "fxo_tx")) {
17070 confp->chan.sig = SIG_FXOGS;
17071 confp->chan.radio = 1;
17072 } else if (!strcasecmp(v->value, "em_rx")) {
17073 confp->chan.sig = SIG_EM;
17074 confp->chan.radio = 1;
17075 } else if (!strcasecmp(v->value, "em_tx")) {
17076 confp->chan.sig = SIG_EM;
17077 confp->chan.radio = 1;
17078 } else if (!strcasecmp(v->value, "em_rxtx")) {
17079 confp->chan.sig = SIG_EM;
17080 confp->chan.radio = 2;
17081 } else if (!strcasecmp(v->value, "em_txrx")) {
17082 confp->chan.sig = SIG_EM;
17083 confp->chan.radio = 2;
17084 } else if (!strcasecmp(v->value, "sf")) {
17085 confp->chan.sig = SIG_SF;
17086 } else if (!strcasecmp(v->value, "sf_w")) {
17087 confp->chan.sig = SIG_SFWINK;
17088 } else if (!strcasecmp(v->value, "sf_featd")) {
17089 confp->chan.sig = SIG_FEATD;
17090 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17091 confp->chan.sig = SIG_FEATDMF;
17092 } else if (!strcasecmp(v->value, "sf_featb")) {
17093 confp->chan.sig = SIG_SF_FEATB;
17094 } else if (!strcasecmp(v->value, "sf")) {
17095 confp->chan.sig = SIG_SF;
17096 } else if (!strcasecmp(v->value, "sf_rx")) {
17097 confp->chan.sig = SIG_SF;
17098 confp->chan.radio = 1;
17099 } else if (!strcasecmp(v->value, "sf_tx")) {
17100 confp->chan.sig = SIG_SF;
17101 confp->chan.radio = 1;
17102 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17103 confp->chan.sig = SIG_SF;
17104 confp->chan.radio = 2;
17105 } else if (!strcasecmp(v->value, "sf_txrx")) {
17106 confp->chan.sig = SIG_SF;
17107 confp->chan.radio = 2;
17108 } else if (!strcasecmp(v->value, "featd")) {
17109 confp->chan.sig = SIG_FEATD;
17110 } else if (!strcasecmp(v->value, "featdmf")) {
17111 confp->chan.sig = SIG_FEATDMF;
17112 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17113 confp->chan.sig = SIG_FEATDMF_TA;
17114 } else if (!strcasecmp(v->value, "e911")) {
17115 confp->chan.sig = SIG_E911;
17116 } else if (!strcasecmp(v->value, "fgccama")) {
17117 confp->chan.sig = SIG_FGC_CAMA;
17118 } else if (!strcasecmp(v->value, "fgccamamf")) {
17119 confp->chan.sig = SIG_FGC_CAMAMF;
17120 } else if (!strcasecmp(v->value, "featb")) {
17121 confp->chan.sig = SIG_FEATB;
17122 #ifdef HAVE_PRI
17123 } else if (!strcasecmp(v->value, "pri_net")) {
17124 confp->chan.sig = SIG_PRI;
17125 confp->pri.pri.nodetype = PRI_NETWORK;
17126 } else if (!strcasecmp(v->value, "pri_cpe")) {
17127 confp->chan.sig = SIG_PRI;
17128 confp->pri.pri.nodetype = PRI_CPE;
17129 } else if (!strcasecmp(v->value, "bri_cpe")) {
17130 confp->chan.sig = SIG_BRI;
17131 confp->pri.pri.nodetype = PRI_CPE;
17132 } else if (!strcasecmp(v->value, "bri_net")) {
17133 confp->chan.sig = SIG_BRI;
17134 confp->pri.pri.nodetype = PRI_NETWORK;
17135 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17136 confp->chan.sig = SIG_BRI_PTMP;
17137 confp->pri.pri.nodetype = PRI_CPE;
17138 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17139 #if defined(HAVE_PRI_CALL_HOLD)
17140 confp->chan.sig = SIG_BRI_PTMP;
17141 confp->pri.pri.nodetype = PRI_NETWORK;
17142 #else
17143 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17144 #endif
17145 #endif
17146 #if defined(HAVE_SS7)
17147 } else if (!strcasecmp(v->value, "ss7")) {
17148 confp->chan.sig = SIG_SS7;
17149 #endif
17150 #ifdef HAVE_OPENR2
17151 } else if (!strcasecmp(v->value, "mfcr2")) {
17152 confp->chan.sig = SIG_MFCR2;
17153 #endif
17154 } else if (!strcasecmp(v->value, "auto")) {
17155 confp->is_sig_auto = 1;
17156 } else {
17157 confp->chan.outsigmod = orig_outsigmod;
17158 confp->chan.radio = orig_radio;
17159 confp->is_sig_auto = orig_auto;
17160 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17161 }
17162 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17163 if (!strcasecmp(v->value, "em")) {
17164 confp->chan.outsigmod = SIG_EM;
17165 } else if (!strcasecmp(v->value, "em_e1")) {
17166 confp->chan.outsigmod = SIG_EM_E1;
17167 } else if (!strcasecmp(v->value, "em_w")) {
17168 confp->chan.outsigmod = SIG_EMWINK;
17169 } else if (!strcasecmp(v->value, "sf")) {
17170 confp->chan.outsigmod = SIG_SF;
17171 } else if (!strcasecmp(v->value, "sf_w")) {
17172 confp->chan.outsigmod = SIG_SFWINK;
17173 } else if (!strcasecmp(v->value, "sf_featd")) {
17174 confp->chan.outsigmod = SIG_FEATD;
17175 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17176 confp->chan.outsigmod = SIG_FEATDMF;
17177 } else if (!strcasecmp(v->value, "sf_featb")) {
17178 confp->chan.outsigmod = SIG_SF_FEATB;
17179 } else if (!strcasecmp(v->value, "sf")) {
17180 confp->chan.outsigmod = SIG_SF;
17181 } else if (!strcasecmp(v->value, "featd")) {
17182 confp->chan.outsigmod = SIG_FEATD;
17183 } else if (!strcasecmp(v->value, "featdmf")) {
17184 confp->chan.outsigmod = SIG_FEATDMF;
17185 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17186 confp->chan.outsigmod = SIG_FEATDMF_TA;
17187 } else if (!strcasecmp(v->value, "e911")) {
17188 confp->chan.outsigmod = SIG_E911;
17189 } else if (!strcasecmp(v->value, "fgccama")) {
17190 confp->chan.outsigmod = SIG_FGC_CAMA;
17191 } else if (!strcasecmp(v->value, "fgccamamf")) {
17192 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17193 } else if (!strcasecmp(v->value, "featb")) {
17194 confp->chan.outsigmod = SIG_FEATB;
17195 } else {
17196 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17197 }
17198 #ifdef HAVE_PRI
17199 } else if (!strcasecmp(v->name, "pridialplan")) {
17200 if (!strcasecmp(v->value, "national")) {
17201 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17202 } else if (!strcasecmp(v->value, "unknown")) {
17203 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17204 } else if (!strcasecmp(v->value, "private")) {
17205 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17206 } else if (!strcasecmp(v->value, "international")) {
17207 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17208 } else if (!strcasecmp(v->value, "local")) {
17209 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17210 } else if (!strcasecmp(v->value, "dynamic")) {
17211 confp->pri.pri.dialplan = -1;
17212 } else if (!strcasecmp(v->value, "redundant")) {
17213 confp->pri.pri.dialplan = -2;
17214 } else {
17215 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17216 }
17217 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17218 if (!strcasecmp(v->value, "national")) {
17219 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17220 } else if (!strcasecmp(v->value, "unknown")) {
17221 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17222 } else if (!strcasecmp(v->value, "private")) {
17223 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17224 } else if (!strcasecmp(v->value, "international")) {
17225 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17226 } else if (!strcasecmp(v->value, "local")) {
17227 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17228 } else if (!strcasecmp(v->value, "dynamic")) {
17229 confp->pri.pri.localdialplan = -1;
17230 } else if (!strcasecmp(v->value, "redundant")) {
17231 confp->pri.pri.localdialplan = -2;
17232 } else {
17233 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17234 }
17235 } else if (!strcasecmp(v->name, "switchtype")) {
17236 if (!strcasecmp(v->value, "national"))
17237 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17238 else if (!strcasecmp(v->value, "ni1"))
17239 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17240 else if (!strcasecmp(v->value, "dms100"))
17241 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17242 else if (!strcasecmp(v->value, "4ess"))
17243 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17244 else if (!strcasecmp(v->value, "5ess"))
17245 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17246 else if (!strcasecmp(v->value, "euroisdn"))
17247 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17248 else if (!strcasecmp(v->value, "qsig"))
17249 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17250 else {
17251 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17252 return -1;
17253 }
17254 } else if (!strcasecmp(v->name, "msn")) {
17255 ast_copy_string(confp->pri.pri.msn_list, v->value,
17256 sizeof(confp->pri.pri.msn_list));
17257 } else if (!strcasecmp(v->name, "nsf")) {
17258 if (!strcasecmp(v->value, "sdn"))
17259 confp->pri.pri.nsf = PRI_NSF_SDN;
17260 else if (!strcasecmp(v->value, "megacom"))
17261 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17262 else if (!strcasecmp(v->value, "tollfreemegacom"))
17263 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17264 else if (!strcasecmp(v->value, "accunet"))
17265 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17266 else if (!strcasecmp(v->value, "none"))
17267 confp->pri.pri.nsf = PRI_NSF_NONE;
17268 else {
17269 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17270 confp->pri.pri.nsf = PRI_NSF_NONE;
17271 }
17272 } else if (!strcasecmp(v->name, "priindication")) {
17273 if (!strcasecmp(v->value, "outofband"))
17274 confp->chan.priindication_oob = 1;
17275 else if (!strcasecmp(v->value, "inband"))
17276 confp->chan.priindication_oob = 0;
17277 else
17278 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17279 v->value, v->lineno);
17280 } else if (!strcasecmp(v->name, "priexclusive")) {
17281 confp->chan.priexclusive = ast_true(v->value);
17282 } else if (!strcasecmp(v->name, "internationalprefix")) {
17283 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17284 } else if (!strcasecmp(v->name, "nationalprefix")) {
17285 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17286 } else if (!strcasecmp(v->name, "localprefix")) {
17287 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17288 } else if (!strcasecmp(v->name, "privateprefix")) {
17289 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17290 } else if (!strcasecmp(v->name, "unknownprefix")) {
17291 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17292 } else if (!strcasecmp(v->name, "resetinterval")) {
17293 if (!strcasecmp(v->value, "never"))
17294 confp->pri.pri.resetinterval = -1;
17295 else if (atoi(v->value) >= 60)
17296 confp->pri.pri.resetinterval = atoi(v->value);
17297 else
17298 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17299 v->value, v->lineno);
17300 } else if (!strcasecmp(v->name, "minunused")) {
17301 confp->pri.pri.minunused = atoi(v->value);
17302 } else if (!strcasecmp(v->name, "minidle")) {
17303 confp->pri.pri.minidle = atoi(v->value);
17304 } else if (!strcasecmp(v->name, "idleext")) {
17305 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17306 } else if (!strcasecmp(v->name, "idledial")) {
17307 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17308 } else if (!strcasecmp(v->name, "overlapdial")) {
17309 if (ast_true(v->value)) {
17310 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17311 } else if (!strcasecmp(v->value, "incoming")) {
17312 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17313 } else if (!strcasecmp(v->value, "outgoing")) {
17314 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17315 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17316 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17317 } else {
17318 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17319 }
17320 #ifdef HAVE_PRI_PROG_W_CAUSE
17321 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17322 if (!strcasecmp(v->value, "logical")) {
17323 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17324 } else if (!strcasecmp(v->value, "physical")) {
17325 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17326 } else {
17327 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17328 }
17329 #endif
17330 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17331 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17332 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17333 } else if (!strcasecmp(v->name, "service_message_support")) {
17334
17335 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17336 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17337 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17338 confp->pri.pri.enable_service_message_support = 1;
17339 } else {
17340 confp->pri.pri.enable_service_message_support = 0;
17341 }
17342 #endif
17343 #ifdef HAVE_PRI_INBANDDISCONNECT
17344 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17345 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17346 #endif
17347 } else if (!strcasecmp(v->name, "pritimer")) {
17348 #ifdef PRI_GETSET_TIMERS
17349 char tmp[20];
17350 char *timerc;
17351 char *c;
17352 int timer;
17353 int timeridx;
17354
17355 ast_copy_string(tmp, v->value, sizeof(tmp));
17356 c = tmp;
17357 timerc = strsep(&c, ",");
17358 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17359 timeridx = pri_timer2idx(timerc);
17360 timer = atoi(c);
17361 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17362 ast_log(LOG_WARNING,
17363 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17364 v->lineno);
17365 } else if (!timer) {
17366 ast_log(LOG_WARNING,
17367 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17368 c, timerc, v->lineno);
17369 } else {
17370 confp->pri.pri.pritimers[timeridx] = timer;
17371 }
17372 } else {
17373 ast_log(LOG_WARNING,
17374 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17375 v->value, v->lineno);
17376 }
17377 #endif
17378 } else if (!strcasecmp(v->name, "facilityenable")) {
17379 confp->pri.pri.facilityenable = ast_true(v->value);
17380 #if defined(HAVE_PRI_AOC_EVENTS)
17381 } else if (!strcasecmp(v->name, "aoc_enable")) {
17382 confp->pri.pri.aoc_passthrough_flag = 0;
17383 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17384 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17385 }
17386 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17387 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17388 }
17389 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17390 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17391 }
17392 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17393 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17394 #endif
17395 #if defined(HAVE_PRI_CALL_HOLD)
17396 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17397 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17398 #endif
17399 #if defined(HAVE_PRI_CCSS)
17400 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17401 if (!strcasecmp(v->value, "global")) {
17402 confp->pri.pri.cc_ptmp_recall_mode = 0;
17403 } else if (!strcasecmp(v->value, "specific")) {
17404 confp->pri.pri.cc_ptmp_recall_mode = 1;
17405 } else {
17406 confp->pri.pri.cc_ptmp_recall_mode = 1;
17407 }
17408 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17409 if (!strcasecmp(v->value, "release")) {
17410 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17411 } else if (!strcasecmp(v->value, "retain")) {
17412 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17413 } else if (!strcasecmp(v->value, "do_not_care")) {
17414 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17415 } else {
17416 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17417 }
17418 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17419 if (!strcasecmp(v->value, "release")) {
17420 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17421 } else if (!strcasecmp(v->value, "retain")) {
17422 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17423 } else {
17424 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17425 }
17426 #endif
17427 #if defined(HAVE_PRI_CALL_WAITING)
17428 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17429 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17430 if (confp->pri.pri.max_call_waiting_calls < 0) {
17431
17432 confp->pri.pri.max_call_waiting_calls = 0;
17433 }
17434 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17435 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17436 #endif
17437 #if defined(HAVE_PRI_MWI)
17438 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17439 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17440 sizeof(confp->pri.pri.mwi_mailboxes));
17441 #endif
17442 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17443 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17444 #if defined(HAVE_PRI_L2_PERSISTENCE)
17445 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17446 if (!strcasecmp(v->value, "keep_up")) {
17447 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17448 } else if (!strcasecmp(v->value, "leave_down")) {
17449 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17450 } else {
17451 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17452 }
17453 #endif
17454 #endif
17455 #if defined(HAVE_SS7)
17456 } else if (!strcasecmp(v->name, "ss7type")) {
17457 if (!strcasecmp(v->value, "itu")) {
17458 cur_ss7type = SS7_ITU;
17459 } else if (!strcasecmp(v->value, "ansi")) {
17460 cur_ss7type = SS7_ANSI;
17461 } else
17462 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17463 } else if (!strcasecmp(v->name, "linkset")) {
17464 cur_linkset = atoi(v->value);
17465 } else if (!strcasecmp(v->name, "pointcode")) {
17466 cur_pointcode = parse_pointcode(v->value);
17467 } else if (!strcasecmp(v->name, "adjpointcode")) {
17468 cur_adjpointcode = parse_pointcode(v->value);
17469 } else if (!strcasecmp(v->name, "defaultdpc")) {
17470 cur_defaultdpc = parse_pointcode(v->value);
17471 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17472 cur_cicbeginswith = atoi(v->value);
17473 } else if (!strcasecmp(v->name, "networkindicator")) {
17474 if (!strcasecmp(v->value, "national"))
17475 cur_networkindicator = SS7_NI_NAT;
17476 else if (!strcasecmp(v->value, "national_spare"))
17477 cur_networkindicator = SS7_NI_NAT_SPARE;
17478 else if (!strcasecmp(v->value, "international"))
17479 cur_networkindicator = SS7_NI_INT;
17480 else if (!strcasecmp(v->value, "international_spare"))
17481 cur_networkindicator = SS7_NI_INT_SPARE;
17482 else
17483 cur_networkindicator = -1;
17484 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17485 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17486 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17487 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17488 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17489 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17490 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17491 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17492 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17493 if (!strcasecmp(v->value, "national")) {
17494 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17495 } else if (!strcasecmp(v->value, "international")) {
17496 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17497 } else if (!strcasecmp(v->value, "subscriber")) {
17498 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17499 } else if (!strcasecmp(v->value, "unknown")) {
17500 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17501 } else if (!strcasecmp(v->value, "dynamic")) {
17502 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17503 } else {
17504 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17505 }
17506 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17507 if (!strcasecmp(v->value, "national")) {
17508 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17509 } else if (!strcasecmp(v->value, "international")) {
17510 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17511 } else if (!strcasecmp(v->value, "subscriber")) {
17512 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17513 } else if (!strcasecmp(v->value, "unknown")) {
17514 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17515 } else if (!strcasecmp(v->value, "dynamic")) {
17516 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17517 } else {
17518 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17519 }
17520 } else if (!strcasecmp(v->name, "sigchan")) {
17521 int sigchan, res;
17522 sigchan = atoi(v->value);
17523 res = linkset_addsigchan(sigchan);
17524 if (res < 0)
17525 return -1;
17526
17527 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17528 struct dahdi_ss7 *link;
17529 link = ss7_resolve_linkset(cur_linkset);
17530 if (!link) {
17531 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17532 return -1;
17533 }
17534 if (ast_true(v->value))
17535 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17536 #endif
17537 #ifdef HAVE_OPENR2
17538 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17539 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17540 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);
17541 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17542 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17543 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17544 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17545 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17546 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17547 confp->mfcr2.variant = OR2_VAR_ITU;
17548 }
17549 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17550 confp->mfcr2.mfback_timeout = atoi(v->value);
17551 if (!confp->mfcr2.mfback_timeout) {
17552 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17553 confp->mfcr2.mfback_timeout = -1;
17554 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17555 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17556 }
17557 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17558 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17559 if (confp->mfcr2.metering_pulse_timeout > 500) {
17560 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17561 }
17562 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17563 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17564 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17565 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17566 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17567 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17568 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17569 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17570 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17571 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17572 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17573 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17574 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17575 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17576 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17577 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17578 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17579 #endif
17580 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17581 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17582 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17583 confp->mfcr2.max_ani = atoi(v->value);
17584 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17585 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17586 }
17587 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17588 confp->mfcr2.max_dnis = atoi(v->value);
17589 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17590 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17591 }
17592 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17593 confp->mfcr2.category = openr2_proto_get_category(v->value);
17594 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17595 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17596 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17597 v->value, v->lineno);
17598 }
17599 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17600 openr2_log_level_t tmplevel;
17601 char *clevel;
17602 char *logval = ast_strdupa(v->value);
17603 while (logval) {
17604 clevel = strsep(&logval,",");
17605 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17606 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17607 continue;
17608 }
17609 confp->mfcr2.loglevel |= tmplevel;
17610 }
17611 #endif
17612 } else if (!strcasecmp(v->name, "cadence")) {
17613
17614 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17615 int i;
17616 struct dahdi_ring_cadence new_cadence;
17617 int cid_location = -1;
17618 int firstcadencepos = 0;
17619 char original_args[80];
17620 int cadence_is_ok = 1;
17621
17622 ast_copy_string(original_args, v->value, sizeof(original_args));
17623
17624 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]);
17625
17626
17627 if (element_count % 2 == 1) {
17628 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17629 cadence_is_ok = 0;
17630 }
17631
17632
17633 for (i = 0; i < element_count; i++) {
17634 if (c[i] == 0) {
17635 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17636 cadence_is_ok = 0;
17637 break;
17638 } else if (c[i] < 0) {
17639 if (i % 2 == 1) {
17640
17641 if (cid_location == -1) {
17642 cid_location = i;
17643 c[i] *= -1;
17644 } else {
17645 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17646 cadence_is_ok = 0;
17647 break;
17648 }
17649 } else {
17650 if (firstcadencepos == 0) {
17651 firstcadencepos = i;
17652
17653 } else {
17654 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17655 cadence_is_ok = 0;
17656 break;
17657 }
17658 }
17659 }
17660 }
17661
17662
17663 for (i = 0; i < 16; i++) {
17664 new_cadence.ringcadence[i] = c[i];
17665 }
17666
17667 if (cadence_is_ok) {
17668
17669 if (element_count < 2) {
17670 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17671 } else {
17672 if (cid_location == -1) {
17673
17674 cid_location = 1;
17675 } else {
17676
17677 cid_location = (cid_location + 1) / 2;
17678 }
17679
17680 if (!user_has_defined_cadences++)
17681
17682 num_cadence = 0;
17683 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17684 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17685 else {
17686 cadences[num_cadence] = new_cadence;
17687 cidrings[num_cadence++] = cid_location;
17688 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17689 }
17690 }
17691 }
17692 } else if (!strcasecmp(v->name, "ringtimeout")) {
17693 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17694 } else if (!strcasecmp(v->name, "prewink")) {
17695 confp->timing.prewinktime = atoi(v->value);
17696 } else if (!strcasecmp(v->name, "preflash")) {
17697 confp->timing.preflashtime = atoi(v->value);
17698 } else if (!strcasecmp(v->name, "wink")) {
17699 confp->timing.winktime = atoi(v->value);
17700 } else if (!strcasecmp(v->name, "flash")) {
17701 confp->timing.flashtime = atoi(v->value);
17702 } else if (!strcasecmp(v->name, "start")) {
17703 confp->timing.starttime = atoi(v->value);
17704 } else if (!strcasecmp(v->name, "rxwink")) {
17705 confp->timing.rxwinktime = atoi(v->value);
17706 } else if (!strcasecmp(v->name, "rxflash")) {
17707 confp->timing.rxflashtime = atoi(v->value);
17708 } else if (!strcasecmp(v->name, "debounce")) {
17709 confp->timing.debouncetime = atoi(v->value);
17710 } else if (!strcasecmp(v->name, "toneduration")) {
17711 int toneduration;
17712 int ctlfd;
17713 int res;
17714 struct dahdi_dialparams dps;
17715
17716 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17717 if (ctlfd == -1) {
17718 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17719 return -1;
17720 }
17721
17722 toneduration = atoi(v->value);
17723 if (toneduration > -1) {
17724 memset(&dps, 0, sizeof(dps));
17725
17726 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17727 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17728 if (res < 0) {
17729 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17730 close(ctlfd);
17731 return -1;
17732 }
17733 }
17734 close(ctlfd);
17735 } else if (!strcasecmp(v->name, "defaultcic")) {
17736 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17737 } else if (!strcasecmp(v->name, "defaultozz")) {
17738 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17739 } else if (!strcasecmp(v->name, "mwilevel")) {
17740 mwilevel = atoi(v->value);
17741 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17742 dtmfcid_level = atoi(v->value);
17743 } else if (!strcasecmp(v->name, "reportalarms")) {
17744 if (!strcasecmp(v->value, "all"))
17745 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17746 if (!strcasecmp(v->value, "none"))
17747 report_alarms = 0;
17748 else if (!strcasecmp(v->value, "channels"))
17749 report_alarms = REPORT_CHANNEL_ALARMS;
17750 else if (!strcasecmp(v->value, "spans"))
17751 report_alarms = REPORT_SPAN_ALARMS;
17752 }
17753 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17754 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17755 }
17756
17757
17758 if (confp->chan.vars) {
17759 ast_variables_destroy(confp->chan.vars);
17760 confp->chan.vars = NULL;
17761 }
17762
17763 if (dahdichan) {
17764
17765 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17766 &found_pseudo)) {
17767 if (confp->ignore_failed_channels) {
17768 ast_log(LOG_WARNING,
17769 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17770 dahdichan->value);
17771 } else {
17772 return -1;
17773 }
17774 }
17775 }
17776
17777
17778 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17779 if (!tmp->destroy && tmp->span != y) {
17780 tmp->manages_span_alarms = 1;
17781 y = tmp->span;
17782 } else {
17783 tmp->manages_span_alarms = 0;
17784 }
17785 }
17786
17787
17788
17789 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
17790
17791
17792
17793
17794 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17795
17796 if (conf.chan.cc_params) {
17797 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17798 } else {
17799 tmp = NULL;
17800 }
17801 if (tmp) {
17802 ast_verb(3, "Automatically generated pseudo channel\n");
17803 } else {
17804 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17805 }
17806 ast_cc_config_params_destroy(conf.chan.cc_params);
17807 }
17808 return 0;
17809 }
17810
17811
17812
17813
17814
17815
17816
17817
17818
17819
17820
17821 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17822 {
17823 struct ast_cc_config_params *cc_params;
17824
17825 cc_params = dest->chan.cc_params;
17826 *dest = *src;
17827 dest->chan.cc_params = cc_params;
17828 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17829 }
17830
17831
17832
17833
17834
17835
17836
17837
17838
17839
17840
17841
17842
17843 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17844 {
17845 struct ast_config *cfg;
17846 struct ast_config *ucfg;
17847 struct ast_variable *v;
17848 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17849 const char *chans;
17850 const char *cat;
17851 int res;
17852
17853 #ifdef HAVE_PRI
17854 char *c;
17855 int spanno;
17856 int i;
17857 int logicalspan;
17858 int trunkgroup;
17859 int dchannels[SIG_PRI_NUM_DCHANS];
17860 #endif
17861 int have_cfg_now;
17862 static int had_cfg_before = 1;
17863
17864 cfg = ast_config_load(config, config_flags);
17865 have_cfg_now = !!cfg;
17866 if (!cfg) {
17867
17868 if (had_cfg_before) {
17869 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17870 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17871 }
17872 cfg = ast_config_new();
17873 if (!cfg) {
17874 return 0;
17875 }
17876 ucfg = ast_config_load("users.conf", config_flags);
17877 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17878 ast_config_destroy(cfg);
17879 return 0;
17880 }
17881 if (ucfg == CONFIG_STATUS_FILEINVALID) {
17882 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17883 ast_config_destroy(cfg);
17884 return 0;
17885 }
17886 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17887 ucfg = ast_config_load("users.conf", config_flags);
17888 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17889 return 0;
17890 }
17891 if (ucfg == CONFIG_STATUS_FILEINVALID) {
17892 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17893 return 0;
17894 }
17895 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17896 cfg = ast_config_load(config, config_flags);
17897 have_cfg_now = !!cfg;
17898 if (!cfg) {
17899 if (had_cfg_before) {
17900
17901 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
17902 ast_config_destroy(ucfg);
17903 return 0;
17904 }
17905 cfg = ast_config_new();
17906 if (!cfg) {
17907 ast_config_destroy(ucfg);
17908 return 0;
17909 }
17910 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17911 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17912 ast_config_destroy(ucfg);
17913 return 0;
17914 }
17915 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17916 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17917 return 0;
17918 } else {
17919 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17920 ucfg = ast_config_load("users.conf", config_flags);
17921 if (ucfg == CONFIG_STATUS_FILEINVALID) {
17922 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17923 ast_config_destroy(cfg);
17924 return 0;
17925 }
17926 }
17927 had_cfg_before = have_cfg_now;
17928
17929
17930 ast_mutex_lock(&iflock);
17931 #ifdef HAVE_PRI
17932 if (reload != 1) {
17933
17934 v = ast_variable_browse(cfg, "trunkgroups");
17935 while (v) {
17936 if (!strcasecmp(v->name, "trunkgroup")) {
17937 trunkgroup = atoi(v->value);
17938 if (trunkgroup > 0) {
17939 if ((c = strchr(v->value, ','))) {
17940 i = 0;
17941 memset(dchannels, 0, sizeof(dchannels));
17942 while (c && (i < SIG_PRI_NUM_DCHANS)) {
17943 dchannels[i] = atoi(c + 1);
17944 if (dchannels[i] < 0) {
17945 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);
17946 } else
17947 i++;
17948 c = strchr(c + 1, ',');
17949 }
17950 if (i) {
17951 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17952 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);
17953 } else
17954 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");
17955 } else
17956 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17957 } else
17958 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17959 } else
17960 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17961 } else if (!strcasecmp(v->name, "spanmap")) {
17962 spanno = atoi(v->value);
17963 if (spanno > 0) {
17964 if ((c = strchr(v->value, ','))) {
17965 trunkgroup = atoi(c + 1);
17966 if (trunkgroup > 0) {
17967 if ((c = strchr(c + 1, ',')))
17968 logicalspan = atoi(c + 1);
17969 else
17970 logicalspan = 0;
17971 if (logicalspan >= 0) {
17972 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17973 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17974 } else
17975 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17976 } else
17977 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);
17978 } else
17979 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17980 } else
17981 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17982 } else
17983 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17984 } else {
17985 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17986 }
17987 v = v->next;
17988 }
17989 }
17990 #endif
17991
17992
17993 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17994
17995 mwimonitornotify[0] = '\0';
17996
17997 v = ast_variable_browse(cfg, "channels");
17998 if ((res = process_dahdi(base_conf,
17999 "" ,
18000 v, reload, 0))) {
18001 ast_mutex_unlock(&iflock);
18002 ast_config_destroy(cfg);
18003 if (ucfg) {
18004 ast_config_destroy(ucfg);
18005 }
18006 return res;
18007 }
18008
18009
18010 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18011
18012
18013
18014 if (!strcasecmp(cat, "general") ||
18015 !strcasecmp(cat, "trunkgroups") ||
18016 !strcasecmp(cat, "globals") ||
18017 !strcasecmp(cat, "channels")) {
18018 continue;
18019 }
18020
18021 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18022 if (ast_strlen_zero(chans)) {
18023
18024 continue;
18025 }
18026
18027
18028 deep_copy_dahdi_chan_conf(conf, base_conf);
18029
18030 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18031 ast_mutex_unlock(&iflock);
18032 ast_config_destroy(cfg);
18033 if (ucfg) {
18034 ast_config_destroy(ucfg);
18035 }
18036 return res;
18037 }
18038 }
18039
18040 ast_config_destroy(cfg);
18041
18042 if (ucfg) {
18043
18044 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18045 process_dahdi(base_conf,
18046 "" ,
18047 ast_variable_browse(ucfg, "general"), 1, 0);
18048
18049 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18050 if (!strcasecmp(cat, "general")) {
18051 continue;
18052 }
18053
18054 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18055 if (ast_strlen_zero(chans)) {
18056
18057 continue;
18058 }
18059
18060
18061 deep_copy_dahdi_chan_conf(conf, base_conf);
18062
18063 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18064 ast_config_destroy(ucfg);
18065 ast_mutex_unlock(&iflock);
18066 return res;
18067 }
18068 }
18069 ast_config_destroy(ucfg);
18070 }
18071 ast_mutex_unlock(&iflock);
18072
18073 #ifdef HAVE_PRI
18074 if (reload != 1) {
18075 int x;
18076 for (x = 0; x < NUM_SPANS; x++) {
18077 if (pris[x].pri.pvts[0]) {
18078 prepare_pri(pris + x);
18079 if (sig_pri_start_pri(&pris[x].pri)) {
18080 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18081 return -1;
18082 } else
18083 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18084 }
18085 }
18086 }
18087 #endif
18088 #if defined(HAVE_SS7)
18089 if (reload != 1) {
18090 int x;
18091 for (x = 0; x < NUM_SPANS; x++) {
18092 if (linksets[x].ss7.ss7) {
18093 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18094 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18095 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18096 return -1;
18097 } else
18098 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18099 }
18100 }
18101 }
18102 #endif
18103 #ifdef HAVE_OPENR2
18104 if (reload != 1) {
18105 int x;
18106 for (x = 0; x < r2links_count; x++) {
18107 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18108 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18109 return -1;
18110 } else {
18111 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18112 }
18113 }
18114 }
18115 #endif
18116
18117 restart_monitor();
18118 return 0;
18119 }
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130 static int setup_dahdi(int reload)
18131 {
18132 int res;
18133 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18134 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18135 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18136
18137 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18138 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18139 } else {
18140 res = -1;
18141 }
18142 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18143 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18144 ast_cc_config_params_destroy(conf.chan.cc_params);
18145
18146 return res;
18147 }
18148
18149
18150
18151
18152
18153
18154
18155
18156 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18157 struct ast_data *data_root)
18158 {
18159 int ctl, res, span;
18160 struct ast_data *data_span, *data_alarms;
18161 struct dahdi_spaninfo s;
18162
18163 ctl = open("/dev/dahdi/ctl", O_RDWR);
18164 if (ctl < 0) {
18165 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18166 return -1;
18167 }
18168 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18169 s.spanno = span;
18170 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18171 if (res) {
18172 continue;
18173 }
18174
18175 data_span = ast_data_add_node(data_root, "span");
18176 if (!data_span) {
18177 continue;
18178 }
18179 ast_data_add_str(data_span, "description", s.desc);
18180
18181
18182 data_alarms = ast_data_add_node(data_span, "alarms");
18183 if (!data_alarms) {
18184 continue;
18185 }
18186
18187 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18188 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18189 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18190 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18191 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18192 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18193
18194 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18195 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18196 ast_data_add_int(data_span, "crc4", s.crc4count);
18197 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18198 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18199 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18200 "CAS");
18201 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18202 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18203 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18204 "Unknown");
18205 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18206 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18207 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18208 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18209
18210
18211 if (!ast_data_search_match(search, data_span)) {
18212 ast_data_remove_node(data_root, data_span);
18213 }
18214 }
18215 close(ctl);
18216
18217 return 0;
18218 }
18219
18220
18221
18222
18223
18224
18225
18226
18227 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18228 struct ast_data *data_root)
18229 {
18230 struct dahdi_pvt *tmp;
18231 struct ast_data *data_channel;
18232
18233 ast_mutex_lock(&iflock);
18234 for (tmp = iflist; tmp; tmp = tmp->next) {
18235 data_channel = ast_data_add_node(data_root, "channel");
18236 if (!data_channel) {
18237 continue;
18238 }
18239
18240 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18241
18242
18243 if (!ast_data_search_match(search, data_channel)) {
18244 ast_data_remove_node(data_root, data_channel);
18245 }
18246 }
18247 ast_mutex_unlock(&iflock);
18248
18249 return 0;
18250 }
18251
18252
18253
18254
18255
18256
18257
18258
18259 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18260 struct ast_data *data_root)
18261 {
18262 int pseudo_fd = -1;
18263 struct dahdi_versioninfo vi = {
18264 .version = "Unknown",
18265 .echo_canceller = "Unknown"
18266 };
18267
18268 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18269 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18270 return -1;
18271 }
18272
18273 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18274 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18275 }
18276
18277 close(pseudo_fd);
18278
18279 ast_data_add_str(data_root, "value", vi.version);
18280 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18281
18282 return 0;
18283 }
18284
18285 static const struct ast_data_handler dahdi_status_data_provider = {
18286 .version = AST_DATA_HANDLER_VERSION,
18287 .get = dahdi_status_data_provider_get
18288 };
18289
18290 static const struct ast_data_handler dahdi_channels_data_provider = {
18291 .version = AST_DATA_HANDLER_VERSION,
18292 .get = dahdi_channels_data_provider_get
18293 };
18294
18295 static const struct ast_data_handler dahdi_version_data_provider = {
18296 .version = AST_DATA_HANDLER_VERSION,
18297 .get = dahdi_version_data_provider_get
18298 };
18299
18300 static const struct ast_data_entry dahdi_data_providers[] = {
18301 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18302 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18303 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18304 };
18305
18306 static int load_module(void)
18307 {
18308 int res;
18309 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18310 int y;
18311 #endif
18312
18313 #ifdef HAVE_PRI
18314 memset(pris, 0, sizeof(pris));
18315 for (y = 0; y < NUM_SPANS; y++) {
18316 sig_pri_init_pri(&pris[y].pri);
18317 }
18318 pri_set_error(dahdi_pri_error);
18319 pri_set_message(dahdi_pri_message);
18320 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18321 #ifdef HAVE_PRI_PROG_W_CAUSE
18322 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18323 #endif
18324 #if defined(HAVE_PRI_CCSS)
18325 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18326 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18327 __unload_module();
18328 return AST_MODULE_LOAD_FAILURE;
18329 }
18330 #endif
18331 if (sig_pri_load(
18332 #if defined(HAVE_PRI_CCSS)
18333 dahdi_pri_cc_type
18334 #else
18335 NULL
18336 #endif
18337 )) {
18338 __unload_module();
18339 return AST_MODULE_LOAD_FAILURE;
18340 }
18341 #endif
18342 #if defined(HAVE_SS7)
18343 memset(linksets, 0, sizeof(linksets));
18344 for (y = 0; y < NUM_SPANS; y++) {
18345 sig_ss7_init_linkset(&linksets[y].ss7);
18346 }
18347 ss7_set_error(dahdi_ss7_error);
18348 ss7_set_message(dahdi_ss7_message);
18349 #endif
18350 res = setup_dahdi(0);
18351
18352 if (res)
18353 return AST_MODULE_LOAD_DECLINE;
18354 if (ast_channel_register(&dahdi_tech)) {
18355 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18356 __unload_module();
18357 return AST_MODULE_LOAD_FAILURE;
18358 }
18359 #ifdef HAVE_PRI
18360 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18361 #endif
18362 #if defined(HAVE_SS7)
18363 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18364 #endif
18365 #ifdef HAVE_OPENR2
18366 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18367 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18368 #endif
18369
18370 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18371
18372 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18373 memset(round_robin, 0, sizeof(round_robin));
18374 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18375 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18376 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18377 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18378 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18379 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18380 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18381
18382 ast_cond_init(&ss_thread_complete, NULL);
18383
18384 return res;
18385 }
18386
18387 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18388 {
18389 #define END_SILENCE_LEN 400
18390 #define HEADER_MS 50
18391 #define TRAILER_MS 5
18392 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18393 #define ASCII_BYTES_PER_CHAR 80
18394
18395 unsigned char *buf,*mybuf;
18396 struct dahdi_pvt *p = c->tech_pvt;
18397 struct pollfd fds[1];
18398 int size,res,fd,len,x;
18399 int bytes=0;
18400
18401 float cr = 1.0;
18402 float ci = 0.0;
18403 float scont = 0.0;
18404 int idx;
18405
18406 idx = dahdi_get_index(c, p, 0);
18407 if (idx < 0) {
18408 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18409 return -1;
18410 }
18411 if (!text[0]) return(0);
18412 if ((!p->tdd) && (!p->mate)) return(0);
18413 if (p->mate)
18414 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18415 else
18416 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18417 if (!buf)
18418 return -1;
18419 mybuf = buf;
18420 if (p->mate) {
18421 int codec = AST_LAW(p);
18422 for (x = 0; x < HEADER_MS; x++) {
18423 PUT_CLID_MARKMS;
18424 }
18425
18426 for (x = 0; text[x]; x++) {
18427 PUT_CLID(text[x]);
18428 }
18429 for (x = 0; x < TRAILER_MS; x++) {
18430 PUT_CLID_MARKMS;
18431 }
18432 len = bytes;
18433 buf = mybuf;
18434 } else {
18435 len = tdd_generate(p->tdd, buf, text);
18436 if (len < 1) {
18437 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18438 ast_free(mybuf);
18439 return -1;
18440 }
18441 }
18442 memset(buf + len, 0x7f, END_SILENCE_LEN);
18443 len += END_SILENCE_LEN;
18444 fd = p->subs[idx].dfd;
18445 while (len) {
18446 if (ast_check_hangup(c)) {
18447 ast_free(mybuf);
18448 return -1;
18449 }
18450 size = len;
18451 if (size > READ_SIZE)
18452 size = READ_SIZE;
18453 fds[0].fd = fd;
18454 fds[0].events = POLLOUT | POLLPRI;
18455 fds[0].revents = 0;
18456 res = poll(fds, 1, -1);
18457 if (!res) {
18458 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18459 continue;
18460 }
18461
18462 if (fds[0].revents & POLLPRI) {
18463 ast_free(mybuf);
18464 return -1;
18465 }
18466 if (!(fds[0].revents & POLLOUT)) {
18467 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18468 continue;
18469 }
18470 res = write(fd, buf, size);
18471 if (res != size) {
18472 if (res == -1) {
18473 ast_free(mybuf);
18474 return -1;
18475 }
18476 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18477 break;
18478 }
18479 len -= size;
18480 buf += size;
18481 }
18482 ast_free(mybuf);
18483 return(0);
18484 }
18485
18486
18487 static int reload(void)
18488 {
18489 int res = 0;
18490
18491 res = setup_dahdi(1);
18492 if (res) {
18493 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18494 return -1;
18495 }
18496 return 0;
18497 }
18498
18499
18500
18501
18502
18503 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18504 .load = load_module,
18505 .unload = unload_module,
18506 .reload = reload,
18507 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18508 .nonoptreq = "res_smdi",
18509 );