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: 371590 $")
00053
00054 #if defined(__NetBSD__) || defined(__FreeBSD__)
00055 #include <pthread.h>
00056 #include <signal.h>
00057 #else
00058 #include <sys/signal.h>
00059 #endif
00060 #include <sys/ioctl.h>
00061 #include <sys/stat.h>
00062 #include <math.h>
00063 #include <ctype.h>
00064
00065 #include <dahdi/user.h>
00066 #include <dahdi/tonezone.h>
00067 #include "sig_analog.h"
00068
00069
00070
00071
00072
00073
00074 #if defined(HAVE_PRI)
00075 #include "sig_pri.h"
00076 #ifndef PRI_RESTART
00077 #error "Upgrade your libpri"
00078 #endif
00079 #endif
00080
00081 #if defined(HAVE_SS7)
00082 #include "sig_ss7.h"
00083 #if defined(LIBSS7_ABI_COMPATIBILITY)
00084 #error "Your installed libss7 is not compatible"
00085 #endif
00086 #endif
00087
00088 #ifdef HAVE_OPENR2
00089
00090 #define SIG_MFCR2_MAX_CHANNELS 672
00091 #include <openr2.h>
00092 #endif
00093
00094 #include "asterisk/lock.h"
00095 #include "asterisk/channel.h"
00096 #include "asterisk/config.h"
00097 #include "asterisk/module.h"
00098 #include "asterisk/pbx.h"
00099 #include "asterisk/file.h"
00100 #include "asterisk/ulaw.h"
00101 #include "asterisk/alaw.h"
00102 #include "asterisk/callerid.h"
00103 #include "asterisk/adsi.h"
00104 #include "asterisk/cli.h"
00105 #include "asterisk/cdr.h"
00106 #include "asterisk/cel.h"
00107 #include "asterisk/features.h"
00108 #include "asterisk/musiconhold.h"
00109 #include "asterisk/say.h"
00110 #include "asterisk/tdd.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/dsp.h"
00113 #include "asterisk/astdb.h"
00114 #include "asterisk/manager.h"
00115 #include "asterisk/causes.h"
00116 #include "asterisk/term.h"
00117 #include "asterisk/utils.h"
00118 #include "asterisk/transcap.h"
00119 #include "asterisk/stringfields.h"
00120 #include "asterisk/abstract_jb.h"
00121 #include "asterisk/smdi.h"
00122 #include "asterisk/astobj.h"
00123 #include "asterisk/event.h"
00124 #include "asterisk/devicestate.h"
00125 #include "asterisk/paths.h"
00126 #include "asterisk/ccss.h"
00127 #include "asterisk/data.h"
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 #define SMDI_MD_WAIT_TIMEOUT 1500
00282
00283 static const char * const lbostr[] = {
00284 "0 db (CSU)/0-133 feet (DSX-1)",
00285 "133-266 feet (DSX-1)",
00286 "266-399 feet (DSX-1)",
00287 "399-533 feet (DSX-1)",
00288 "533-655 feet (DSX-1)",
00289 "-7.5db (CSU)",
00290 "-15db (CSU)",
00291 "-22.5db (CSU)"
00292 };
00293
00294
00295
00296 static struct ast_jb_conf default_jbconf =
00297 {
00298 .flags = 0,
00299 .max_size = 200,
00300 .resync_threshold = 1000,
00301 .impl = "fixed",
00302 .target_extra = 40,
00303 };
00304 static struct ast_jb_conf global_jbconf;
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 #define DEFAULT_CIDRINGS 1
00319
00320 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00321
00322
00323
00324 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
00325
00326 static const char tdesc[] = "DAHDI Telephony Driver"
00327 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00328 " w/"
00329 #if defined(HAVE_PRI)
00330 "PRI"
00331 #endif
00332 #if defined(HAVE_SS7)
00333 #if defined(HAVE_PRI)
00334 " & "
00335 #endif
00336 "SS7"
00337 #endif
00338 #if defined(HAVE_OPENR2)
00339 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00340 " & "
00341 #endif
00342 "MFC/R2"
00343 #endif
00344 #endif
00345 ;
00346
00347 static const char config[] = "chan_dahdi.conf";
00348
00349 #define SIG_EM DAHDI_SIG_EM
00350 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00351 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00352 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00353 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00354 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00355 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00356 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00357 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00358 #define SIG_FXSLS DAHDI_SIG_FXSLS
00359 #define SIG_FXSGS DAHDI_SIG_FXSGS
00360 #define SIG_FXSKS DAHDI_SIG_FXSKS
00361 #define SIG_FXOLS DAHDI_SIG_FXOLS
00362 #define SIG_FXOGS DAHDI_SIG_FXOGS
00363 #define SIG_FXOKS DAHDI_SIG_FXOKS
00364 #define SIG_PRI DAHDI_SIG_CLEAR
00365 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00366 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00367 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00368 #define SIG_MFCR2 DAHDI_SIG_CAS
00369 #define SIG_SF DAHDI_SIG_SF
00370 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00371 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00372 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00373 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00374 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00375
00376 #ifdef LOTS_OF_SPANS
00377 #define NUM_SPANS DAHDI_MAX_SPANS
00378 #else
00379 #define NUM_SPANS 32
00380 #endif
00381
00382 #define CHAN_PSEUDO -2
00383
00384 #define CALLPROGRESS_PROGRESS 1
00385 #define CALLPROGRESS_FAX_OUTGOING 2
00386 #define CALLPROGRESS_FAX_INCOMING 4
00387 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00388
00389 #define NUM_CADENCE_MAX 25
00390 static int num_cadence = 4;
00391 static int user_has_defined_cadences = 0;
00392
00393 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00394 { { 125, 125, 2000, 4000 } },
00395 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00396 { { 125, 125, 125, 125, 125, 4000 } },
00397 { { 1000, 500, 2500, 5000 } },
00398 };
00399
00400
00401
00402
00403
00404 static int cidrings[NUM_CADENCE_MAX] = {
00405 2,
00406 4,
00407 3,
00408 2,
00409 };
00410
00411
00412 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00413
00414 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00415 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00416
00417 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00418 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00419
00420 static char defaultcic[64] = "";
00421 static char defaultozz[64] = "";
00422
00423
00424 static char mwimonitornotify[PATH_MAX] = "";
00425 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00426 static int mwisend_rpas = 0;
00427 #endif
00428
00429 static char progzone[10] = "";
00430
00431 static int usedistinctiveringdetection = 0;
00432 static int distinctiveringaftercid = 0;
00433
00434 static int numbufs = 4;
00435
00436 static int mwilevel = 512;
00437 static int dtmfcid_level = 256;
00438
00439 #define REPORT_CHANNEL_ALARMS 1
00440 #define REPORT_SPAN_ALARMS 2
00441 static int report_alarms = REPORT_CHANNEL_ALARMS;
00442
00443 #ifdef HAVE_PRI
00444 static int pridebugfd = -1;
00445 static char pridebugfilename[1024] = "";
00446 #endif
00447
00448
00449 static int firstdigittimeout = 16000;
00450
00451
00452 static int gendigittimeout = 8000;
00453
00454
00455 static int matchdigittimeout = 3000;
00456
00457
00458 AST_MUTEX_DEFINE_STATIC(iflock);
00459
00460
00461 static int ifcount = 0;
00462
00463 #ifdef HAVE_PRI
00464 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00465 #endif
00466
00467
00468
00469 AST_MUTEX_DEFINE_STATIC(monlock);
00470
00471
00472
00473 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00474 static ast_cond_t ss_thread_complete;
00475 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00476 AST_MUTEX_DEFINE_STATIC(restart_lock);
00477 static int ss_thread_count = 0;
00478 static int num_restart_pending = 0;
00479
00480 static int restart_monitor(void);
00481
00482 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
00483
00484 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00485
00486 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00487 {
00488
00489
00490
00491
00492 }
00493
00494
00495 static inline int dahdi_get_event(int fd)
00496 {
00497 int j;
00498 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00499 return -1;
00500 return j;
00501 }
00502
00503
00504 static inline int dahdi_wait_event(int fd)
00505 {
00506 int i, j = 0;
00507 i = DAHDI_IOMUX_SIGEVENT;
00508 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00509 return -1;
00510 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00511 return -1;
00512 return j;
00513 }
00514
00515
00516 #define READ_SIZE 160
00517
00518 #define MASK_AVAIL (1 << 0)
00519 #define MASK_INUSE (1 << 1)
00520
00521 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00522 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00523 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00524 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00525 #define MIN_MS_SINCE_FLASH ((2000) )
00526 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00527
00528 struct dahdi_pvt;
00529
00530
00531
00532
00533
00534 static int ringt_base = DEFAULT_RINGT;
00535
00536 #if defined(HAVE_SS7)
00537
00538 struct dahdi_ss7 {
00539 struct sig_ss7_linkset ss7;
00540 };
00541
00542 static struct dahdi_ss7 linksets[NUM_SPANS];
00543
00544 static int cur_ss7type = -1;
00545 static int cur_linkset = -1;
00546 static int cur_pointcode = -1;
00547 static int cur_cicbeginswith = -1;
00548 static int cur_adjpointcode = -1;
00549 static int cur_networkindicator = -1;
00550 static int cur_defaultdpc = -1;
00551 #endif
00552
00553 #ifdef HAVE_OPENR2
00554 struct dahdi_mfcr2 {
00555 pthread_t r2master;
00556 openr2_context_t *protocol_context;
00557 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00558 int numchans;
00559 int monitored_count;
00560 };
00561
00562 struct dahdi_mfcr2_conf {
00563 openr2_variant_t variant;
00564 int mfback_timeout;
00565 int metering_pulse_timeout;
00566 int max_ani;
00567 int max_dnis;
00568 signed int get_ani_first:2;
00569 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00570 signed int skip_category_request:2;
00571 #endif
00572 unsigned int call_files:1;
00573 unsigned int allow_collect_calls:1;
00574 unsigned int charge_calls:1;
00575 unsigned int accept_on_offer:1;
00576 unsigned int forced_release:1;
00577 unsigned int double_answer:1;
00578 signed int immediate_accept:2;
00579 char logdir[OR2_MAX_PATH];
00580 char r2proto_file[OR2_MAX_PATH];
00581 openr2_log_level_t loglevel;
00582 openr2_calling_party_category_t category;
00583 };
00584
00585
00586 static struct dahdi_mfcr2 **r2links;
00587
00588 static int r2links_count = 0;
00589
00590 #endif
00591
00592 #ifdef HAVE_PRI
00593
00594 struct dahdi_pri {
00595 int dchannels[SIG_PRI_NUM_DCHANS];
00596 int mastertrunkgroup;
00597 int prilogicalspan;
00598 struct sig_pri_span pri;
00599 };
00600
00601 static struct dahdi_pri pris[NUM_SPANS];
00602
00603 #if defined(HAVE_PRI_CCSS)
00604
00605 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00606 #endif
00607
00608 #else
00609
00610 struct dahdi_pri;
00611 #endif
00612
00613 #define SUB_REAL 0
00614 #define SUB_CALLWAIT 1
00615 #define SUB_THREEWAY 2
00616
00617
00618 #define POLARITY_IDLE 0
00619 #define POLARITY_REV 1
00620
00621
00622 struct distRingData {
00623 int ring[3];
00624 int range;
00625 };
00626 struct ringContextData {
00627 char contextData[AST_MAX_CONTEXT];
00628 };
00629 struct dahdi_distRings {
00630 struct distRingData ringnum[3];
00631 struct ringContextData ringContext[3];
00632 };
00633
00634 static const char * const subnames[] = {
00635 "Real",
00636 "Callwait",
00637 "Threeway"
00638 };
00639
00640 struct dahdi_subchannel {
00641 int dfd;
00642 struct ast_channel *owner;
00643 int chan;
00644 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00645 struct ast_frame f;
00646 unsigned int needringing:1;
00647 unsigned int needbusy:1;
00648 unsigned int needcongestion:1;
00649 unsigned int needanswer:1;
00650 unsigned int needflash:1;
00651 unsigned int needhold:1;
00652 unsigned int needunhold:1;
00653 unsigned int linear:1;
00654 unsigned int inthreeway:1;
00655 struct dahdi_confinfo curconf;
00656 };
00657
00658 #define CONF_USER_REAL (1 << 0)
00659 #define CONF_USER_THIRDCALL (1 << 1)
00660
00661 #define MAX_SLAVES 4
00662
00663
00664
00665
00666 typedef enum {
00667 MWI_SEND_NULL = 0,
00668 MWI_SEND_SA,
00669 MWI_SEND_SA_WAIT,
00670 MWI_SEND_PAUSE,
00671 MWI_SEND_SPILL,
00672 MWI_SEND_CLEANUP,
00673 MWI_SEND_DONE,
00674 } mwisend_states;
00675
00676 struct mwisend_info {
00677 struct timeval pause;
00678 mwisend_states mwisend_current;
00679 };
00680
00681
00682 enum DAHDI_IFLIST {
00683 DAHDI_IFLIST_NONE,
00684 DAHDI_IFLIST_MAIN,
00685 #if defined(HAVE_PRI)
00686 DAHDI_IFLIST_NO_B_CHAN,
00687 #endif
00688 };
00689
00690 struct dahdi_pvt {
00691 ast_mutex_t lock;
00692 struct callerid_state *cs;
00693 struct ast_channel *owner;
00694
00695
00696 struct dahdi_subchannel sub_unused;
00697 struct dahdi_subchannel subs[3];
00698 struct dahdi_confinfo saveconf;
00699
00700 struct dahdi_pvt *slaves[MAX_SLAVES];
00701 struct dahdi_pvt *master;
00702 int inconference;
00703
00704 int bufsize;
00705 int buf_no;
00706 int buf_policy;
00707 int faxbuf_no;
00708 int faxbuf_policy;
00709 int sig;
00710
00711
00712
00713
00714 int radio;
00715 int outsigmod;
00716 int oprmode;
00717 struct dahdi_pvt *oprpeer;
00718
00719 float cid_rxgain;
00720
00721 float rxgain;
00722
00723 float txgain;
00724
00725 float txdrc;
00726 float rxdrc;
00727
00728 int tonezone;
00729 enum DAHDI_IFLIST which_iflist;
00730 struct dahdi_pvt *next;
00731 struct dahdi_pvt *prev;
00732
00733
00734
00735
00736
00737
00738
00739 unsigned int adsi:1;
00740
00741
00742
00743
00744
00745 unsigned int answeronpolarityswitch:1;
00746
00747
00748
00749
00750
00751 unsigned int busydetect:1;
00752
00753
00754
00755
00756
00757 unsigned int callreturn:1;
00758
00759
00760
00761
00762
00763
00764 unsigned int callwaiting:1;
00765
00766
00767
00768
00769 unsigned int callwaitingcallerid:1;
00770
00771
00772
00773
00774
00775
00776 unsigned int cancallforward:1;
00777
00778
00779
00780
00781 unsigned int canpark:1;
00782
00783 unsigned int confirmanswer:1;
00784
00785
00786
00787
00788 unsigned int destroy:1;
00789 unsigned int didtdd:1;
00790
00791 unsigned int dialednone:1;
00792
00793
00794
00795
00796 unsigned int dialing:1;
00797
00798 unsigned int digital:1;
00799
00800 unsigned int dnd:1;
00801
00802 unsigned int echobreak:1;
00803
00804
00805
00806
00807
00808 unsigned int echocanbridged:1;
00809
00810 unsigned int echocanon:1;
00811
00812 unsigned int faxhandled:1;
00813
00814 unsigned int usefaxbuffers:1;
00815
00816 unsigned int bufferoverrideinuse:1;
00817
00818 unsigned int firstradio:1;
00819
00820
00821
00822
00823 unsigned int hanguponpolarityswitch:1;
00824
00825 unsigned int hardwaredtmf:1;
00826
00827
00828
00829
00830
00831
00832 unsigned int hidecallerid:1;
00833
00834
00835
00836
00837
00838 unsigned int hidecalleridname:1;
00839
00840 unsigned int ignoredtmf:1;
00841
00842
00843
00844
00845
00846 unsigned int immediate:1;
00847
00848 unsigned int inalarm:1;
00849
00850 unsigned int mate:1;
00851
00852 unsigned int outgoing:1;
00853
00854
00855
00856
00857
00858
00859 unsigned int permcallwaiting:1;
00860
00861
00862
00863
00864 unsigned int permhidecallerid:1;
00865
00866
00867
00868
00869 unsigned int priindication_oob:1;
00870
00871
00872
00873
00874 unsigned int priexclusive:1;
00875
00876
00877
00878
00879 unsigned int pulse:1;
00880
00881 unsigned int pulsedial:1;
00882 unsigned int restartpending:1;
00883
00884
00885
00886
00887
00888 unsigned int restrictcid:1;
00889
00890
00891
00892
00893 unsigned int threewaycalling:1;
00894
00895
00896
00897
00898
00899
00900
00901
00902 unsigned int transfer:1;
00903
00904
00905
00906
00907
00908
00909
00910 unsigned int use_callerid:1;
00911
00912
00913
00914
00915
00916
00917 unsigned int use_callingpres:1;
00918
00919
00920
00921
00922
00923 unsigned int usedistinctiveringdetection:1;
00924
00925
00926
00927
00928 unsigned int dahditrcallerid:1;
00929
00930
00931
00932
00933 unsigned int transfertobusy:1;
00934
00935
00936
00937
00938 unsigned int mwimonitor_neon:1;
00939
00940
00941
00942
00943 unsigned int mwimonitor_fsk:1;
00944
00945
00946
00947
00948
00949 unsigned int mwimonitor_rpas:1;
00950
00951 unsigned int mwimonitoractive:1;
00952
00953 unsigned int mwisendactive:1;
00954
00955
00956
00957
00958 unsigned int inservice:1;
00959
00960
00961
00962
00963 unsigned int locallyblocked:1;
00964
00965
00966
00967
00968 unsigned int remotelyblocked:1;
00969
00970
00971
00972
00973 unsigned int manages_span_alarms:1;
00974
00975 #if defined(HAVE_PRI)
00976 struct sig_pri_span *pri;
00977 int logicalspan;
00978 #endif
00979
00980
00981
00982
00983 unsigned int use_smdi:1;
00984 struct mwisend_info mwisend_data;
00985
00986 struct ast_smdi_interface *smdi_iface;
00987
00988
00989 struct dahdi_distRings drings;
00990
00991
00992
00993
00994
00995 char context[AST_MAX_CONTEXT];
00996
00997
00998
00999 char defcontext[AST_MAX_CONTEXT];
01000
01001 char exten[AST_MAX_EXTENSION];
01002
01003
01004
01005
01006 char language[MAX_LANGUAGE];
01007
01008
01009
01010
01011 char mohinterpret[MAX_MUSICCLASS];
01012
01013
01014
01015
01016 char mohsuggest[MAX_MUSICCLASS];
01017 char parkinglot[AST_MAX_EXTENSION];
01018 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01019
01020 char cid_ani[AST_MAX_EXTENSION];
01021 #endif
01022
01023 int cid_ani2;
01024
01025 char cid_num[AST_MAX_EXTENSION];
01026
01027
01028
01029
01030 char cid_tag[AST_MAX_EXTENSION];
01031
01032 int cid_ton;
01033
01034 char cid_name[AST_MAX_EXTENSION];
01035
01036 char cid_subaddr[AST_MAX_EXTENSION];
01037 char *origcid_num;
01038 char *origcid_name;
01039
01040 char callwait_num[AST_MAX_EXTENSION];
01041
01042 char callwait_name[AST_MAX_EXTENSION];
01043
01044 char rdnis[AST_MAX_EXTENSION];
01045
01046 char dnid[AST_MAX_EXTENSION];
01047
01048
01049
01050
01051 ast_group_t group;
01052
01053 int law_default;
01054
01055 int law;
01056 int confno;
01057 int confusers;
01058 int propconfno;
01059
01060
01061
01062
01063 ast_group_t callgroup;
01064
01065
01066
01067
01068 ast_group_t pickupgroup;
01069
01070
01071
01072
01073 struct ast_variable *vars;
01074 int channel;
01075 int span;
01076 time_t guardtime;
01077 int cid_signalling;
01078 int cid_start;
01079 int dtmfcid_holdoff_state;
01080 struct timeval dtmfcid_delay;
01081 int callingpres;
01082 int callwaitingrepeat;
01083 int cidcwexpire;
01084 int cid_suppress_expire;
01085
01086 unsigned char *cidspill;
01087
01088 int cidpos;
01089
01090 int cidlen;
01091
01092 int ringt;
01093
01094
01095
01096
01097 int ringt_base;
01098
01099
01100
01101
01102
01103
01104 int stripmsd;
01105
01106
01107
01108
01109
01110
01111 int callwaitcas;
01112
01113 int callwaitrings;
01114
01115 struct {
01116 struct dahdi_echocanparams head;
01117 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01118 } echocancel;
01119
01120
01121
01122
01123 int echotraining;
01124
01125 char echorest[20];
01126
01127
01128
01129
01130 int busycount;
01131
01132
01133
01134
01135 int busy_tonelength;
01136
01137
01138
01139
01140 int busy_quietlength;
01141
01142
01143
01144
01145 int callprogress;
01146
01147
01148
01149
01150 int waitfordialtone;
01151 struct timeval waitingfordt;
01152 struct timeval flashtime;
01153
01154 struct ast_dsp *dsp;
01155
01156 struct dahdi_dialoperation dop;
01157 int whichwink;
01158
01159 char finaldial[64];
01160 char accountcode[AST_MAX_ACCOUNT_CODE];
01161 int amaflags;
01162 struct tdd_state *tdd;
01163
01164 char call_forward[AST_MAX_EXTENSION];
01165
01166
01167
01168
01169 char mailbox[AST_MAX_EXTENSION];
01170
01171 struct ast_event_sub *mwi_event_sub;
01172
01173 char dialdest[256];
01174 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01175 struct dahdi_vmwi_info mwisend_setting;
01176 unsigned int mwisend_fsk: 1;
01177 unsigned int mwisend_rpas:1;
01178 #endif
01179 int distinctivering;
01180 int dtmfrelax;
01181
01182 int fake_event;
01183
01184
01185
01186
01187 int polarityonanswerdelay;
01188
01189 struct timeval polaritydelaytv;
01190
01191
01192
01193
01194 int sendcalleridafter;
01195
01196 int polarity;
01197
01198 int dsp_features;
01199 #if defined(HAVE_SS7)
01200
01201 struct sig_ss7_linkset *ss7;
01202 #endif
01203 #ifdef HAVE_OPENR2
01204 struct dahdi_mfcr2 *mfcr2;
01205 openr2_chan_t *r2chan;
01206 openr2_calling_party_category_t mfcr2_recvd_category;
01207 openr2_calling_party_category_t mfcr2_category;
01208 int mfcr2_dnis_index;
01209 int mfcr2_ani_index;
01210 int mfcr2call:1;
01211 int mfcr2_answer_pending:1;
01212 int mfcr2_charge_calls:1;
01213 int mfcr2_allow_collect_calls:1;
01214 int mfcr2_forced_release:1;
01215 int mfcr2_dnis_matched:1;
01216 int mfcr2_call_accepted:1;
01217 int mfcr2_progress:1;
01218 int mfcr2_accept_on_offer:1;
01219 #endif
01220
01221 char begindigit;
01222
01223 int muting;
01224 void *sig_pvt;
01225 struct ast_cc_config_params *cc_params;
01226
01227
01228
01229
01230
01231
01232 char dialstring[AST_CHANNEL_NAME];
01233 };
01234
01235 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01236 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01237 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01238 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01239 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01240 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01241 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01242 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01286 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01287 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01288 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01289 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01290 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01291 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01292 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01293 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01294 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01295 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01296 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01297 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01298 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01299 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01300 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01301 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01302 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01303
01304 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01305
01306 static struct dahdi_pvt *iflist = NULL;
01307 static struct dahdi_pvt *ifend = NULL;
01308
01309 #if defined(HAVE_PRI)
01310 static struct dahdi_parms_pseudo {
01311 int buf_no;
01312 int buf_policy;
01313 int faxbuf_no;
01314 int faxbuf_policy;
01315 } dahdi_pseudo_parms;
01316 #endif
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 struct dahdi_chan_conf {
01329 struct dahdi_pvt chan;
01330 #ifdef HAVE_PRI
01331 struct dahdi_pri pri;
01332 #endif
01333
01334 #if defined(HAVE_SS7)
01335 struct dahdi_ss7 ss7;
01336 #endif
01337
01338 #ifdef HAVE_OPENR2
01339 struct dahdi_mfcr2_conf mfcr2;
01340 #endif
01341 struct dahdi_params timing;
01342 int is_sig_auto;
01343
01344 int ignore_failed_channels;
01345
01346
01347
01348
01349
01350 char smdi_port[SMDI_MAX_FILENAME_LEN];
01351 };
01352
01353
01354 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01355 {
01356
01357
01358
01359 struct dahdi_chan_conf conf = {
01360 #ifdef HAVE_PRI
01361 .pri.pri = {
01362 .nsf = PRI_NSF_NONE,
01363 .switchtype = PRI_SWITCH_NI2,
01364 .dialplan = PRI_UNKNOWN + 1,
01365 .localdialplan = PRI_NATIONAL_ISDN + 1,
01366 .nodetype = PRI_CPE,
01367 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01368
01369 #if defined(HAVE_PRI_CCSS)
01370 .cc_ptmp_recall_mode = 1,
01371 .cc_qsig_signaling_link_req = 1,
01372 .cc_qsig_signaling_link_rsp = 1,
01373 #endif
01374
01375 .minunused = 2,
01376 .idleext = "",
01377 .idledial = "",
01378 .internationalprefix = "",
01379 .nationalprefix = "",
01380 .localprefix = "",
01381 .privateprefix = "",
01382 .unknownprefix = "",
01383 .resetinterval = -1,
01384 },
01385 #endif
01386 #if defined(HAVE_SS7)
01387 .ss7.ss7 = {
01388 .called_nai = SS7_NAI_NATIONAL,
01389 .calling_nai = SS7_NAI_NATIONAL,
01390 .internationalprefix = "",
01391 .nationalprefix = "",
01392 .subscriberprefix = "",
01393 .unknownprefix = ""
01394 },
01395 #endif
01396 #ifdef HAVE_OPENR2
01397 .mfcr2 = {
01398 .variant = OR2_VAR_ITU,
01399 .mfback_timeout = -1,
01400 .metering_pulse_timeout = -1,
01401 .max_ani = 10,
01402 .max_dnis = 4,
01403 .get_ani_first = -1,
01404 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01405 .skip_category_request = -1,
01406 #endif
01407 .call_files = 0,
01408 .allow_collect_calls = 0,
01409 .charge_calls = 1,
01410 .accept_on_offer = 1,
01411 .forced_release = 0,
01412 .double_answer = 0,
01413 .immediate_accept = -1,
01414 .logdir = "",
01415 .r2proto_file = "",
01416 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01417 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01418 },
01419 #endif
01420 .chan = {
01421 .context = "default",
01422 .cid_num = "",
01423 .cid_name = "",
01424 .cid_tag = "",
01425 .mohinterpret = "default",
01426 .mohsuggest = "",
01427 .parkinglot = "",
01428 .transfertobusy = 1,
01429
01430 .cid_signalling = CID_SIG_BELL,
01431 .cid_start = CID_START_RING,
01432 .dahditrcallerid = 0,
01433 .use_callerid = 1,
01434 .sig = -1,
01435 .outsigmod = -1,
01436
01437 .cid_rxgain = +5.0,
01438
01439 .tonezone = -1,
01440
01441 .echocancel.head.tap_length = 1,
01442
01443 .busycount = 3,
01444
01445 .accountcode = "",
01446
01447 .mailbox = "",
01448
01449 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01450 .mwisend_fsk = 1,
01451 #endif
01452 .polarityonanswerdelay = 600,
01453
01454 .sendcalleridafter = DEFAULT_CIDRINGS,
01455
01456 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01457 .buf_no = numbufs,
01458 .usefaxbuffers = 0,
01459 .cc_params = ast_cc_config_params_init(),
01460 },
01461 .timing = {
01462 .prewinktime = -1,
01463 .preflashtime = -1,
01464 .winktime = -1,
01465 .flashtime = -1,
01466 .starttime = -1,
01467 .rxwinktime = -1,
01468 .rxflashtime = -1,
01469 .debouncetime = -1
01470 },
01471 .is_sig_auto = 1,
01472 .smdi_port = "/dev/ttyS0",
01473 };
01474
01475 return conf;
01476 }
01477
01478
01479 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01480 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01481 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01482 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01483 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01484 static int dahdi_hangup(struct ast_channel *ast);
01485 static int dahdi_answer(struct ast_channel *ast);
01486 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01487 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01488 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01489 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01490 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01491 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01492 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01493 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01494 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01495 static int dahdi_devicestate(void *data);
01496 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01497
01498 static const struct ast_channel_tech dahdi_tech = {
01499 .type = "DAHDI",
01500 .description = tdesc,
01501 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01502 .requester = dahdi_request,
01503 .send_digit_begin = dahdi_digit_begin,
01504 .send_digit_end = dahdi_digit_end,
01505 .send_text = dahdi_sendtext,
01506 .call = dahdi_call,
01507 .hangup = dahdi_hangup,
01508 .answer = dahdi_answer,
01509 .read = dahdi_read,
01510 .write = dahdi_write,
01511 .bridge = dahdi_bridge,
01512 .exception = dahdi_exception,
01513 .indicate = dahdi_indicate,
01514 .fixup = dahdi_fixup,
01515 .setoption = dahdi_setoption,
01516 .queryoption = dahdi_queryoption,
01517 .func_channel_read = dahdi_func_read,
01518 .func_channel_write = dahdi_func_write,
01519 .devicestate = dahdi_devicestate,
01520 .cc_callback = dahdi_cc_callback,
01521 };
01522
01523 #define GET_CHANNEL(p) ((p)->channel)
01524
01525 #define SIG_PRI_LIB_HANDLE_CASES \
01526 SIG_PRI: \
01527 case SIG_BRI: \
01528 case SIG_BRI_PTMP
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539 static inline int dahdi_sig_pri_lib_handles(int signaling)
01540 {
01541 int handles;
01542
01543 switch (signaling) {
01544 case SIG_PRI_LIB_HANDLE_CASES:
01545 handles = 1;
01546 break;
01547 default:
01548 handles = 0;
01549 break;
01550 }
01551
01552 return handles;
01553 }
01554
01555 static int analog_lib_handles(int signalling, int radio, int oprmode)
01556 {
01557 switch (signalling) {
01558 case SIG_FXOLS:
01559 case SIG_FXOGS:
01560 case SIG_FXOKS:
01561 case SIG_FXSLS:
01562 case SIG_FXSGS:
01563 case SIG_FXSKS:
01564 case SIG_EMWINK:
01565 case SIG_EM:
01566 case SIG_EM_E1:
01567 case SIG_FEATD:
01568 case SIG_FEATDMF:
01569 case SIG_E911:
01570 case SIG_FGC_CAMA:
01571 case SIG_FGC_CAMAMF:
01572 case SIG_FEATB:
01573 case SIG_SFWINK:
01574 case SIG_SF:
01575 case SIG_SF_FEATD:
01576 case SIG_SF_FEATDMF:
01577 case SIG_FEATDMF_TA:
01578 case SIG_SF_FEATB:
01579 break;
01580 default:
01581
01582 return 0;
01583 }
01584
01585 if (radio) {
01586 return 0;
01587 }
01588
01589 if (oprmode) {
01590 return 0;
01591 }
01592
01593 return 1;
01594 }
01595
01596 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01597 {
01598 switch (sig) {
01599 case SIG_FXOLS:
01600 return ANALOG_SIG_FXOLS;
01601 case SIG_FXOGS:
01602 return ANALOG_SIG_FXOGS;
01603 case SIG_FXOKS:
01604 return ANALOG_SIG_FXOKS;
01605 case SIG_FXSLS:
01606 return ANALOG_SIG_FXSLS;
01607 case SIG_FXSGS:
01608 return ANALOG_SIG_FXSGS;
01609 case SIG_FXSKS:
01610 return ANALOG_SIG_FXSKS;
01611 case SIG_EMWINK:
01612 return ANALOG_SIG_EMWINK;
01613 case SIG_EM:
01614 return ANALOG_SIG_EM;
01615 case SIG_EM_E1:
01616 return ANALOG_SIG_EM_E1;
01617 case SIG_FEATD:
01618 return ANALOG_SIG_FEATD;
01619 case SIG_FEATDMF:
01620 return ANALOG_SIG_FEATDMF;
01621 case SIG_E911:
01622 return SIG_E911;
01623 case SIG_FGC_CAMA:
01624 return ANALOG_SIG_FGC_CAMA;
01625 case SIG_FGC_CAMAMF:
01626 return ANALOG_SIG_FGC_CAMAMF;
01627 case SIG_FEATB:
01628 return ANALOG_SIG_FEATB;
01629 case SIG_SFWINK:
01630 return ANALOG_SIG_SFWINK;
01631 case SIG_SF:
01632 return ANALOG_SIG_SF;
01633 case SIG_SF_FEATD:
01634 return ANALOG_SIG_SF_FEATD;
01635 case SIG_SF_FEATDMF:
01636 return ANALOG_SIG_SF_FEATDMF;
01637 case SIG_FEATDMF_TA:
01638 return ANALOG_SIG_FEATDMF_TA;
01639 case SIG_SF_FEATB:
01640 return ANALOG_SIG_FEATB;
01641 default:
01642 return -1;
01643 }
01644 }
01645
01646
01647 static int analog_tone_to_dahditone(enum analog_tone tone)
01648 {
01649 switch (tone) {
01650 case ANALOG_TONE_RINGTONE:
01651 return DAHDI_TONE_RINGTONE;
01652 case ANALOG_TONE_STUTTER:
01653 return DAHDI_TONE_STUTTER;
01654 case ANALOG_TONE_CONGESTION:
01655 return DAHDI_TONE_CONGESTION;
01656 case ANALOG_TONE_DIALTONE:
01657 return DAHDI_TONE_DIALTONE;
01658 case ANALOG_TONE_DIALRECALL:
01659 return DAHDI_TONE_DIALRECALL;
01660 case ANALOG_TONE_INFO:
01661 return DAHDI_TONE_INFO;
01662 default:
01663 return -1;
01664 }
01665 }
01666
01667 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01668 {
01669 int index;
01670
01671 switch (analogsub) {
01672 case ANALOG_SUB_REAL:
01673 index = SUB_REAL;
01674 break;
01675 case ANALOG_SUB_CALLWAIT:
01676 index = SUB_CALLWAIT;
01677 break;
01678 case ANALOG_SUB_THREEWAY:
01679 index = SUB_THREEWAY;
01680 break;
01681 default:
01682 ast_log(LOG_ERROR, "Unidentified sub!\n");
01683 index = SUB_REAL;
01684 }
01685
01686 return index;
01687 }
01688
01689 static enum analog_event dahdievent_to_analogevent(int event);
01690 static int bump_gains(struct dahdi_pvt *p);
01691 static int dahdi_setlinear(int dfd, int linear);
01692
01693 static int my_start_cid_detect(void *pvt, int cid_signalling)
01694 {
01695 struct dahdi_pvt *p = pvt;
01696 int index = SUB_REAL;
01697 p->cs = callerid_new(cid_signalling);
01698 if (!p->cs) {
01699 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01700 return -1;
01701 }
01702 bump_gains(p);
01703 dahdi_setlinear(p->subs[index].dfd, 0);
01704
01705 return 0;
01706 }
01707
01708 static int my_stop_cid_detect(void *pvt)
01709 {
01710 struct dahdi_pvt *p = pvt;
01711 int index = SUB_REAL;
01712 if (p->cs)
01713 callerid_free(p->cs);
01714 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01715 return 0;
01716 }
01717
01718 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01719 {
01720 struct dahdi_pvt *p = pvt;
01721 struct analog_pvt *analog_p = p->sig_pvt;
01722 struct pollfd poller;
01723 char *name, *num;
01724 int index = SUB_REAL;
01725 int res;
01726 unsigned char buf[256];
01727 int flags;
01728
01729 poller.fd = p->subs[SUB_REAL].dfd;
01730 poller.events = POLLPRI | POLLIN;
01731 poller.revents = 0;
01732
01733 res = poll(&poller, 1, timeout);
01734
01735 if (poller.revents & POLLPRI) {
01736 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01737 return 1;
01738 }
01739
01740 if (poller.revents & POLLIN) {
01741
01742
01743
01744
01745
01746 res = read(p->subs[index].dfd, buf, sizeof(buf));
01747 if (res < 0) {
01748 if (errno != ELAST) {
01749 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01750 callerid_free(p->cs);
01751 return -1;
01752 }
01753 }
01754
01755 if (analog_p->ringt > 0) {
01756 if (!(--analog_p->ringt)) {
01757
01758 return -1;
01759 }
01760 }
01761
01762 if (p->cid_signalling == CID_SIG_V23_JP) {
01763 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01764 } else {
01765 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01766 }
01767 if (res < 0) {
01768
01769
01770
01771
01772 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01773 return -1;
01774 }
01775
01776 if (res == 1) {
01777 callerid_get(p->cs, &name, &num, &flags);
01778 if (name)
01779 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01780 if (num)
01781 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01782
01783 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01784 return 0;
01785 }
01786 }
01787
01788 *ev = ANALOG_EVENT_NONE;
01789 return 2;
01790 }
01791
01792 static const char *event2str(int event);
01793 static int restore_gains(struct dahdi_pvt *p);
01794
01795 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01796 {
01797 unsigned char buf[256];
01798 int distMatches;
01799 int curRingData[RING_PATTERNS];
01800 int receivedRingT;
01801 int counter1;
01802 int counter;
01803 int i;
01804 int res;
01805 int checkaftercid = 0;
01806
01807 struct dahdi_pvt *p = pvt;
01808 struct analog_pvt *analog_p = p->sig_pvt;
01809
01810 if (ringdata == NULL) {
01811 ringdata = curRingData;
01812 } else {
01813 checkaftercid = 1;
01814 }
01815
01816
01817
01818 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01819
01820 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01821 ringdata[receivedRingT] = 0;
01822 receivedRingT = 0;
01823 if (checkaftercid && distinctiveringaftercid)
01824 ast_verb(3, "Detecting post-CID distinctive ring\n");
01825
01826 else if (strcmp(p->context,p->defcontext) != 0) {
01827 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01828 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01829 }
01830
01831 for (;;) {
01832 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01833 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01834 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01835 ast_hangup(chan);
01836 return 1;
01837 }
01838 if (i & DAHDI_IOMUX_SIGEVENT) {
01839 res = dahdi_get_event(p->subs[idx].dfd);
01840 if (res == DAHDI_EVENT_NOALARM) {
01841 p->inalarm = 0;
01842 analog_p->inalarm = 0;
01843 }
01844 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01845 res = 0;
01846
01847
01848 ringdata[receivedRingT] = analog_p->ringt;
01849
01850 if (analog_p->ringt < analog_p->ringt_base/2)
01851 break;
01852
01853
01854 if (++receivedRingT == RING_PATTERNS)
01855 break;
01856 } else if (i & DAHDI_IOMUX_READ) {
01857 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01858 if (res < 0) {
01859 if (errno != ELAST) {
01860 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01861 ast_hangup(chan);
01862 return 1;
01863 }
01864 break;
01865 }
01866 if (analog_p->ringt > 0) {
01867 if (!(--analog_p->ringt)) {
01868 res = -1;
01869 break;
01870 }
01871 }
01872 }
01873 }
01874 }
01875 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01876
01877 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01878 for (counter = 0; counter < 3; counter++) {
01879
01880 distMatches = 0;
01881
01882 ast_verb(3, "Checking %d,%d,%d\n",
01883 p->drings.ringnum[counter].ring[0],
01884 p->drings.ringnum[counter].ring[1],
01885 p->drings.ringnum[counter].ring[2]);
01886 for (counter1 = 0; counter1 < 3; counter1++) {
01887 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01888 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01889 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01890 ringdata[counter1]);
01891 distMatches++;
01892 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01893 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01894 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01895 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01896 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01897 distMatches++;
01898 }
01899 }
01900
01901 if (distMatches == 3) {
01902
01903 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01904 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01905 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01906 break;
01907 }
01908 }
01909 }
01910
01911 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01912 restore_gains(p);
01913
01914 return 0;
01915 }
01916
01917 static int my_stop_callwait(void *pvt)
01918 {
01919 struct dahdi_pvt *p = pvt;
01920 p->callwaitingrepeat = 0;
01921 p->cidcwexpire = 0;
01922 p->cid_suppress_expire = 0;
01923
01924 return 0;
01925 }
01926
01927 static int send_callerid(struct dahdi_pvt *p);
01928 static int save_conference(struct dahdi_pvt *p);
01929 static int restore_conference(struct dahdi_pvt *p);
01930
01931 static int my_callwait(void *pvt)
01932 {
01933 struct dahdi_pvt *p = pvt;
01934 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01935 if (p->cidspill) {
01936 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01937 ast_free(p->cidspill);
01938 }
01939
01940
01941
01942
01943
01944 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01945 return -1;
01946 save_conference(p);
01947
01948 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01949 if (!p->callwaitrings && p->callwaitingcallerid) {
01950 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01951 p->callwaitcas = 1;
01952 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01953 } else {
01954 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01955 p->callwaitcas = 0;
01956 p->cidlen = 2400 + READ_SIZE * 4;
01957 }
01958 p->cidpos = 0;
01959 send_callerid(p);
01960
01961 return 0;
01962 }
01963
01964 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01965 {
01966 struct dahdi_pvt *p = pvt;
01967
01968 ast_debug(2, "Starting cid spill\n");
01969
01970 if (p->cidspill) {
01971 ast_log(LOG_WARNING, "cidspill already exists??\n");
01972 ast_free(p->cidspill);
01973 }
01974
01975 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01976 if (cwcid == 0) {
01977 p->cidlen = ast_callerid_generate(p->cidspill,
01978 caller->id.name.str,
01979 caller->id.number.str,
01980 AST_LAW(p));
01981 } else {
01982 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01983 caller->id.name.str, caller->id.number.str);
01984 p->callwaitcas = 0;
01985 p->cidcwexpire = 0;
01986 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01987 caller->id.name.str,
01988 caller->id.number.str,
01989 AST_LAW(p));
01990 p->cidlen += READ_SIZE * 4;
01991 }
01992 p->cidpos = 0;
01993 p->cid_suppress_expire = 0;
01994 send_callerid(p);
01995 }
01996 return 0;
01997 }
01998
01999 static int my_dsp_reset_and_flush_digits(void *pvt)
02000 {
02001 struct dahdi_pvt *p = pvt;
02002 if (p->dsp)
02003 ast_dsp_digitreset(p->dsp);
02004
02005 return 0;
02006 }
02007
02008 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
02009 {
02010 struct dahdi_pvt *p = pvt;
02011
02012 if (p->channel == CHAN_PSEUDO)
02013 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
02014
02015 if (mode == ANALOG_DIGITMODE_DTMF) {
02016
02017 if (p->hardwaredtmf) {
02018 if (p->dsp) {
02019 ast_dsp_free(p->dsp);
02020 p->dsp = NULL;
02021 }
02022 return 0;
02023 }
02024
02025 if (!p->dsp) {
02026 p->dsp = ast_dsp_new();
02027 if (!p->dsp) {
02028 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02029 return -1;
02030 }
02031 }
02032
02033 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
02034 } else if (mode == ANALOG_DIGITMODE_MF) {
02035 if (!p->dsp) {
02036 p->dsp = ast_dsp_new();
02037 if (!p->dsp) {
02038 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
02039 return -1;
02040 }
02041 }
02042 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
02043 }
02044 return 0;
02045 }
02046
02047 static int dahdi_wink(struct dahdi_pvt *p, int index);
02048
02049 static int my_wink(void *pvt, enum analog_sub sub)
02050 {
02051 struct dahdi_pvt *p = pvt;
02052 int index = analogsub_to_dahdisub(sub);
02053 if (index != SUB_REAL) {
02054 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02055 }
02056 return dahdi_wink(p, index);
02057 }
02058
02059 static void wakeup_sub(struct dahdi_pvt *p, int a);
02060
02061 static int reset_conf(struct dahdi_pvt *p);
02062
02063 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02064
02065 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02066 {
02067 struct ast_frame *f = *dest;
02068 struct dahdi_pvt *p = pvt;
02069 int idx = analogsub_to_dahdisub(analog_index);
02070
02071 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02072 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02073 f->subclass.integer, f->subclass.integer, ast->name);
02074
02075 if (f->subclass.integer == 'f') {
02076 if (f->frametype == AST_FRAME_DTMF_END) {
02077
02078 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02079
02080 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02081 struct dahdi_bufferinfo bi = {
02082 .txbufpolicy = p->faxbuf_policy,
02083 .bufsize = p->bufsize,
02084 .numbufs = p->faxbuf_no
02085 };
02086 int res;
02087
02088 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02089 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02090 } else {
02091 p->bufferoverrideinuse = 1;
02092 }
02093 }
02094 p->faxhandled = 1;
02095 if (p->dsp) {
02096 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02097 ast_dsp_set_features(p->dsp, p->dsp_features);
02098 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02099 }
02100 if (strcmp(ast->exten, "fax")) {
02101 const char *target_context = S_OR(ast->macrocontext, ast->context);
02102
02103
02104
02105
02106
02107 ast_mutex_unlock(&p->lock);
02108 ast_channel_unlock(ast);
02109 if (ast_exists_extension(ast, target_context, "fax", 1,
02110 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02111 ast_channel_lock(ast);
02112 ast_mutex_lock(&p->lock);
02113 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02114
02115 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02116 if (ast_async_goto(ast, target_context, "fax", 1))
02117 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02118 } else {
02119 ast_channel_lock(ast);
02120 ast_mutex_lock(&p->lock);
02121 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02122 }
02123 } else {
02124 ast_debug(1, "Already in a fax extension, not redirecting\n");
02125 }
02126 } else {
02127 ast_debug(1, "Fax already handled\n");
02128 }
02129 dahdi_confmute(p, 0);
02130 }
02131 p->subs[idx].f.frametype = AST_FRAME_NULL;
02132 p->subs[idx].f.subclass.integer = 0;
02133 *dest = &p->subs[idx].f;
02134 }
02135 }
02136
02137 static void my_lock_private(void *pvt)
02138 {
02139 struct dahdi_pvt *p = pvt;
02140 ast_mutex_lock(&p->lock);
02141 }
02142
02143 static void my_unlock_private(void *pvt)
02144 {
02145 struct dahdi_pvt *p = pvt;
02146 ast_mutex_unlock(&p->lock);
02147 }
02148
02149 static void my_deadlock_avoidance_private(void *pvt)
02150 {
02151 struct dahdi_pvt *p = pvt;
02152
02153 DEADLOCK_AVOIDANCE(&p->lock);
02154 }
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166 static void dahdi_ami_channel_event(struct dahdi_pvt *p, struct ast_channel *chan)
02167 {
02168 char ch_name[20];
02169
02170 if (p->channel < CHAN_PSEUDO) {
02171
02172 snprintf(ch_name, sizeof(ch_name), "no-media (%d)", p->channel);
02173 } else if (p->channel == CHAN_PSEUDO) {
02174
02175 strcpy(ch_name, "pseudo");
02176 } else {
02177
02178 snprintf(ch_name, sizeof(ch_name), "%d", p->channel);
02179 }
02180 ast_manager_event(chan, EVENT_FLAG_CALL, "DAHDIChannel",
02181 "Channel: %s\r\n"
02182 "Uniqueid: %s\r\n"
02183 "DAHDISpan: %d\r\n"
02184 "DAHDIChannel: %s\r\n",
02185 chan->name,
02186 chan->uniqueid,
02187 p->span,
02188 ch_name);
02189 }
02190
02191 #ifdef HAVE_PRI
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202 static void my_ami_channel_event(void *pvt, struct ast_channel *chan)
02203 {
02204 struct dahdi_pvt *p = pvt;
02205
02206 dahdi_ami_channel_event(p, chan);
02207 }
02208 #endif
02209
02210
02211
02212
02213 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02214 {
02215 struct dahdi_pvt *p = pvt;
02216 int oldval;
02217 int idx = analogsub_to_dahdisub(sub);
02218
02219 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02220 oldval = p->subs[idx].linear;
02221 p->subs[idx].linear = linear_mode ? 1 : 0;
02222 return oldval;
02223 }
02224
02225 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02226 {
02227 struct dahdi_pvt *p = pvt;
02228 int idx = analogsub_to_dahdisub(sub);
02229
02230 p->subs[idx].inthreeway = inthreeway;
02231 }
02232
02233 static int get_alarms(struct dahdi_pvt *p);
02234 static void handle_alarms(struct dahdi_pvt *p, int alms);
02235 static void my_get_and_handle_alarms(void *pvt)
02236 {
02237 int res;
02238 struct dahdi_pvt *p = pvt;
02239
02240 res = get_alarms(p);
02241 handle_alarms(p, res);
02242 }
02243
02244 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02245 {
02246 struct ast_channel *bridged = ast_bridged_channel(chan);
02247
02248 if (bridged && bridged->tech == &dahdi_tech) {
02249 struct dahdi_pvt *p = bridged->tech_pvt;
02250
02251 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
02252 return p->sig_pvt;
02253 }
02254 }
02255 return NULL;
02256 }
02257
02258 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02259 {
02260 struct dahdi_pvt *p = pvt;
02261 int dahdi_sub = analogsub_to_dahdisub(sub);
02262 return p->subs[dahdi_sub].dfd;
02263 }
02264
02265 static void my_set_cadence(void *pvt, int *cid_rings, struct ast_channel *ast)
02266 {
02267 struct dahdi_pvt *p = pvt;
02268
02269
02270 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02271 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02272 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02273 *cid_rings = cidrings[p->distinctivering - 1];
02274 } else {
02275 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02276 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02277 *cid_rings = p->sendcalleridafter;
02278 }
02279 }
02280
02281 static void my_set_alarm(void *pvt, int in_alarm)
02282 {
02283 struct dahdi_pvt *p = pvt;
02284
02285 p->inalarm = in_alarm;
02286 }
02287
02288 static void my_set_dialing(void *pvt, int is_dialing)
02289 {
02290 struct dahdi_pvt *p = pvt;
02291
02292 p->dialing = is_dialing;
02293 }
02294
02295 static void my_set_outgoing(void *pvt, int is_outgoing)
02296 {
02297 struct dahdi_pvt *p = pvt;
02298
02299 p->outgoing = is_outgoing;
02300 }
02301
02302 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02303 static void my_set_digital(void *pvt, int is_digital)
02304 {
02305 struct dahdi_pvt *p = pvt;
02306
02307 p->digital = is_digital;
02308 }
02309 #endif
02310
02311 #if defined(HAVE_SS7)
02312 static void my_set_inservice(void *pvt, int is_inservice)
02313 {
02314 struct dahdi_pvt *p = pvt;
02315
02316 p->inservice = is_inservice;
02317 }
02318 #endif
02319
02320 #if defined(HAVE_SS7)
02321 static void my_set_locallyblocked(void *pvt, int is_blocked)
02322 {
02323 struct dahdi_pvt *p = pvt;
02324
02325 p->locallyblocked = is_blocked;
02326 }
02327 #endif
02328
02329 #if defined(HAVE_SS7)
02330 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02331 {
02332 struct dahdi_pvt *p = pvt;
02333
02334 p->remotelyblocked = is_blocked;
02335 }
02336 #endif
02337
02338 static void my_set_ringtimeout(void *pvt, int ringt)
02339 {
02340 struct dahdi_pvt *p = pvt;
02341 p->ringt = ringt;
02342 }
02343
02344 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02345 {
02346 struct dahdi_pvt *p = pvt;
02347
02348 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02349 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02350 gettimeofday(&p->waitingfordt, NULL);
02351 ast_setstate(ast, AST_STATE_OFFHOOK);
02352 }
02353 }
02354
02355 static int my_check_waitingfordt(void *pvt)
02356 {
02357 struct dahdi_pvt *p = pvt;
02358
02359 if (p->waitingfordt.tv_usec) {
02360 return 1;
02361 }
02362
02363 return 0;
02364 }
02365
02366 static void my_set_confirmanswer(void *pvt, int flag)
02367 {
02368 struct dahdi_pvt *p = pvt;
02369 p->confirmanswer = flag;
02370 }
02371
02372 static int my_check_confirmanswer(void *pvt)
02373 {
02374 struct dahdi_pvt *p = pvt;
02375 if (p->confirmanswer) {
02376 return 1;
02377 }
02378
02379 return 0;
02380 }
02381
02382 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02383 {
02384 struct dahdi_pvt *p = pvt;
02385
02386 p->callwaiting = callwaiting_enable;
02387 }
02388
02389 static void my_cancel_cidspill(void *pvt)
02390 {
02391 struct dahdi_pvt *p = pvt;
02392
02393 ast_free(p->cidspill);
02394 p->cidspill = NULL;
02395 restore_conference(p);
02396 }
02397
02398 static int my_confmute(void *pvt, int mute)
02399 {
02400 struct dahdi_pvt *p = pvt;
02401 return dahdi_confmute(p, mute);
02402 }
02403
02404 static void my_set_pulsedial(void *pvt, int flag)
02405 {
02406 struct dahdi_pvt *p = pvt;
02407 p->pulsedial = flag;
02408 }
02409
02410 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02411 {
02412 struct dahdi_pvt *p = pvt;
02413
02414 p->owner = new_owner;
02415 }
02416
02417 static const char *my_get_orig_dialstring(void *pvt)
02418 {
02419 struct dahdi_pvt *p = pvt;
02420
02421 return p->dialstring;
02422 }
02423
02424 static void my_increase_ss_count(void)
02425 {
02426 ast_mutex_lock(&ss_thread_lock);
02427 ss_thread_count++;
02428 ast_mutex_unlock(&ss_thread_lock);
02429 }
02430
02431 static void my_decrease_ss_count(void)
02432 {
02433 ast_mutex_lock(&ss_thread_lock);
02434 ss_thread_count--;
02435 ast_cond_signal(&ss_thread_complete);
02436 ast_mutex_unlock(&ss_thread_lock);
02437 }
02438
02439 static void my_all_subchannels_hungup(void *pvt)
02440 {
02441 struct dahdi_pvt *p = pvt;
02442 int res, law;
02443
02444 p->faxhandled = 0;
02445 p->didtdd = 0;
02446
02447 if (p->dsp) {
02448 ast_dsp_free(p->dsp);
02449 p->dsp = NULL;
02450 }
02451
02452 p->law = p->law_default;
02453 law = p->law_default;
02454 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02455 if (res < 0)
02456 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02457
02458 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02459
02460 #if 1
02461 {
02462 int i;
02463 p->owner = NULL;
02464
02465 for (i = 0; i < 3; i++) {
02466 p->subs[i].owner = NULL;
02467 }
02468 }
02469 #endif
02470
02471 reset_conf(p);
02472 if (num_restart_pending == 0) {
02473 restart_monitor();
02474 }
02475 }
02476
02477 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02478
02479 static int my_conf_del(void *pvt, enum analog_sub sub)
02480 {
02481 struct dahdi_pvt *p = pvt;
02482 int x = analogsub_to_dahdisub(sub);
02483
02484 return conf_del(p, &p->subs[x], x);
02485 }
02486
02487 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02488
02489 static int my_conf_add(void *pvt, enum analog_sub sub)
02490 {
02491 struct dahdi_pvt *p = pvt;
02492 int x = analogsub_to_dahdisub(sub);
02493
02494 return conf_add(p, &p->subs[x], x, 0);
02495 }
02496
02497 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02498
02499 static int my_complete_conference_update(void *pvt, int needconference)
02500 {
02501 struct dahdi_pvt *p = pvt;
02502 int needconf = needconference;
02503 int x;
02504 int useslavenative;
02505 struct dahdi_pvt *slave = NULL;
02506
02507 useslavenative = isslavenative(p, &slave);
02508
02509
02510
02511 for (x = 0; x < MAX_SLAVES; x++) {
02512 if (p->slaves[x]) {
02513 if (useslavenative)
02514 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02515 else {
02516 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02517 needconf++;
02518 }
02519 }
02520 }
02521
02522 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02523 if (useslavenative)
02524 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02525 else {
02526 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02527 needconf++;
02528 }
02529 }
02530
02531 if (p->master) {
02532 if (isslavenative(p->master, NULL)) {
02533 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02534 } else {
02535 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02536 }
02537 }
02538 if (!needconf) {
02539
02540
02541 p->confno = -1;
02542 }
02543
02544 return 0;
02545 }
02546
02547 static int check_for_conference(struct dahdi_pvt *p);
02548
02549 static int my_check_for_conference(void *pvt)
02550 {
02551 struct dahdi_pvt *p = pvt;
02552 return check_for_conference(p);
02553 }
02554
02555 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)
02556 {
02557 struct dahdi_pvt *p = pvt;
02558 int da, db;
02559 int tchan;
02560 int tinthreeway;
02561
02562 da = analogsub_to_dahdisub(a);
02563 db = analogsub_to_dahdisub(b);
02564
02565 tchan = p->subs[da].chan;
02566 p->subs[da].chan = p->subs[db].chan;
02567 p->subs[db].chan = tchan;
02568
02569 tinthreeway = p->subs[da].inthreeway;
02570 p->subs[da].inthreeway = p->subs[db].inthreeway;
02571 p->subs[db].inthreeway = tinthreeway;
02572
02573 p->subs[da].owner = ast_a;
02574 p->subs[db].owner = ast_b;
02575
02576 if (ast_a)
02577 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02578 if (ast_b)
02579 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02580
02581 wakeup_sub(p, a);
02582 wakeup_sub(p, b);
02583
02584 return;
02585 }
02586
02587 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02588
02589 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02590 {
02591 struct dahdi_pvt *p = pvt;
02592 int dsub = analogsub_to_dahdisub(sub);
02593
02594 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02595 }
02596
02597 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02598 static int dahdi_setlaw(int dfd, int law)
02599 {
02600 int res;
02601 res = ioctl(dfd, DAHDI_SETLAW, &law);
02602 if (res)
02603 return res;
02604 return 0;
02605 }
02606 #endif
02607
02608 #if defined(HAVE_PRI)
02609 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)
02610 {
02611 struct dahdi_pvt *p = pvt;
02612 int audio;
02613 int newlaw = -1;
02614
02615 switch (p->sig) {
02616 case SIG_PRI_LIB_HANDLE_CASES:
02617 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02618
02619 break;
02620 }
02621
02622 default:
02623
02624 audio = 1;
02625 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02626 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02627 p->channel, audio, strerror(errno));
02628 }
02629 break;
02630 }
02631
02632 if (law != SIG_PRI_DEFLAW) {
02633 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02634 }
02635
02636 ast_copy_string(p->exten, exten, sizeof(p->exten));
02637
02638 switch (law) {
02639 case SIG_PRI_DEFLAW:
02640 newlaw = 0;
02641 break;
02642 case SIG_PRI_ALAW:
02643 newlaw = DAHDI_LAW_ALAW;
02644 break;
02645 case SIG_PRI_ULAW:
02646 newlaw = DAHDI_LAW_MULAW;
02647 break;
02648 }
02649 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02650 }
02651 #endif
02652
02653 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02654
02655 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665 static void my_pri_ss7_open_media(void *p)
02666 {
02667 struct dahdi_pvt *pvt = p;
02668 int res;
02669 int dfd;
02670 int set_val;
02671
02672 dfd = pvt->subs[SUB_REAL].dfd;
02673
02674
02675 set_val = 1;
02676 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02677 if (res < 0) {
02678 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02679 pvt->channel, strerror(errno));
02680 }
02681
02682
02683 res = dahdi_setlaw(dfd, pvt->law);
02684 if (res < 0) {
02685 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02686 }
02687
02688
02689 if (pvt->digital) {
02690 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02691 } else {
02692 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02693 pvt->law);
02694 }
02695 if (res < 0) {
02696 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02697 }
02698
02699 if (pvt->dsp_features && pvt->dsp) {
02700 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02701 pvt->dsp_features = 0;
02702 }
02703 }
02704 #endif
02705
02706 #if defined(HAVE_PRI)
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719 static void my_pri_dial_digits(void *p, const char *dial_string)
02720 {
02721 struct dahdi_dialoperation zo = {
02722 .op = DAHDI_DIAL_OP_APPEND,
02723 };
02724 struct dahdi_pvt *pvt = p;
02725 int res;
02726
02727 snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
02728 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
02729 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
02730 if (res) {
02731 ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
02732 pvt->channel, dial_string, strerror(errno));
02733 } else {
02734 pvt->dialing = 1;
02735 }
02736 }
02737 #endif
02738
02739 static int unalloc_sub(struct dahdi_pvt *p, int x);
02740
02741 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02742 {
02743 struct dahdi_pvt *p = pvt;
02744
02745 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02746 }
02747
02748 static int alloc_sub(struct dahdi_pvt *p, int x);
02749
02750 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02751 {
02752 struct dahdi_pvt *p = pvt;
02753
02754 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02755 }
02756
02757 static int has_voicemail(struct dahdi_pvt *p);
02758
02759 static int my_has_voicemail(void *pvt)
02760 {
02761 struct dahdi_pvt *p = pvt;
02762
02763 return has_voicemail(p);
02764 }
02765
02766 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02767 {
02768 struct dahdi_pvt *p = pvt;
02769 int index;
02770
02771 index = analogsub_to_dahdisub(sub);
02772
02773 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02774 }
02775
02776 static enum analog_event dahdievent_to_analogevent(int event)
02777 {
02778 enum analog_event res;
02779
02780 switch (event) {
02781 case DAHDI_EVENT_ONHOOK:
02782 res = ANALOG_EVENT_ONHOOK;
02783 break;
02784 case DAHDI_EVENT_RINGOFFHOOK:
02785 res = ANALOG_EVENT_RINGOFFHOOK;
02786 break;
02787 case DAHDI_EVENT_WINKFLASH:
02788 res = ANALOG_EVENT_WINKFLASH;
02789 break;
02790 case DAHDI_EVENT_ALARM:
02791 res = ANALOG_EVENT_ALARM;
02792 break;
02793 case DAHDI_EVENT_NOALARM:
02794 res = ANALOG_EVENT_NOALARM;
02795 break;
02796 case DAHDI_EVENT_DIALCOMPLETE:
02797 res = ANALOG_EVENT_DIALCOMPLETE;
02798 break;
02799 case DAHDI_EVENT_RINGERON:
02800 res = ANALOG_EVENT_RINGERON;
02801 break;
02802 case DAHDI_EVENT_RINGEROFF:
02803 res = ANALOG_EVENT_RINGEROFF;
02804 break;
02805 case DAHDI_EVENT_HOOKCOMPLETE:
02806 res = ANALOG_EVENT_HOOKCOMPLETE;
02807 break;
02808 case DAHDI_EVENT_PULSE_START:
02809 res = ANALOG_EVENT_PULSE_START;
02810 break;
02811 case DAHDI_EVENT_POLARITY:
02812 res = ANALOG_EVENT_POLARITY;
02813 break;
02814 case DAHDI_EVENT_RINGBEGIN:
02815 res = ANALOG_EVENT_RINGBEGIN;
02816 break;
02817 case DAHDI_EVENT_EC_DISABLED:
02818 res = ANALOG_EVENT_EC_DISABLED;
02819 break;
02820 case DAHDI_EVENT_REMOVED:
02821 res = ANALOG_EVENT_REMOVED;
02822 break;
02823 case DAHDI_EVENT_NEONMWI_ACTIVE:
02824 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02825 break;
02826 case DAHDI_EVENT_NEONMWI_INACTIVE:
02827 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02828 break;
02829 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02830 case DAHDI_EVENT_TX_CED_DETECTED:
02831 res = ANALOG_EVENT_TX_CED_DETECTED;
02832 break;
02833 case DAHDI_EVENT_RX_CED_DETECTED:
02834 res = ANALOG_EVENT_RX_CED_DETECTED;
02835 break;
02836 case DAHDI_EVENT_EC_NLP_DISABLED:
02837 res = ANALOG_EVENT_EC_NLP_DISABLED;
02838 break;
02839 case DAHDI_EVENT_EC_NLP_ENABLED:
02840 res = ANALOG_EVENT_EC_NLP_ENABLED;
02841 break;
02842 #endif
02843 case DAHDI_EVENT_PULSEDIGIT:
02844 res = ANALOG_EVENT_PULSEDIGIT;
02845 break;
02846 case DAHDI_EVENT_DTMFDOWN:
02847 res = ANALOG_EVENT_DTMFDOWN;
02848 break;
02849 case DAHDI_EVENT_DTMFUP:
02850 res = ANALOG_EVENT_DTMFUP;
02851 break;
02852 default:
02853 switch(event & 0xFFFF0000) {
02854 case DAHDI_EVENT_PULSEDIGIT:
02855 case DAHDI_EVENT_DTMFDOWN:
02856 case DAHDI_EVENT_DTMFUP:
02857
02858
02859
02860
02861 return event;
02862 }
02863
02864 res = ANALOG_EVENT_ERROR;
02865 break;
02866 }
02867
02868 return res;
02869 }
02870
02871 static inline int dahdi_wait_event(int fd);
02872
02873 static int my_wait_event(void *pvt)
02874 {
02875 struct dahdi_pvt *p = pvt;
02876
02877 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02878 }
02879
02880 static int my_get_event(void *pvt)
02881 {
02882 struct dahdi_pvt *p = pvt;
02883 int res;
02884
02885 if (p->fake_event) {
02886 res = p->fake_event;
02887 p->fake_event = 0;
02888 } else
02889 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02890
02891 return dahdievent_to_analogevent(res);
02892 }
02893
02894 static int my_is_off_hook(void *pvt)
02895 {
02896 struct dahdi_pvt *p = pvt;
02897 int res;
02898 struct dahdi_params par;
02899
02900 memset(&par, 0, sizeof(par));
02901
02902 if (p->subs[SUB_REAL].dfd > -1)
02903 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02904 else {
02905
02906 res = 0;
02907 par.rxisoffhook = 0;
02908 }
02909 if (res) {
02910 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02911 }
02912
02913 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02914
02915
02916
02917 return (par.rxbits > -1) || par.rxisoffhook;
02918 }
02919
02920 return par.rxisoffhook;
02921 }
02922
02923 static void dahdi_enable_ec(struct dahdi_pvt *p);
02924 static void dahdi_disable_ec(struct dahdi_pvt *p);
02925
02926 static int my_set_echocanceller(void *pvt, int enable)
02927 {
02928 struct dahdi_pvt *p = pvt;
02929
02930 if (enable)
02931 dahdi_enable_ec(p);
02932 else
02933 dahdi_disable_ec(p);
02934
02935 return 0;
02936 }
02937
02938 static int dahdi_ring_phone(struct dahdi_pvt *p);
02939
02940 static int my_ring(void *pvt)
02941 {
02942 struct dahdi_pvt *p = pvt;
02943
02944 return dahdi_ring_phone(p);
02945 }
02946
02947 static int my_flash(void *pvt)
02948 {
02949 struct dahdi_pvt *p = pvt;
02950 int func = DAHDI_FLASH;
02951 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02952 }
02953
02954 static inline int dahdi_set_hook(int fd, int hs);
02955
02956 static int my_off_hook(void *pvt)
02957 {
02958 struct dahdi_pvt *p = pvt;
02959 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02960 }
02961
02962 static void my_set_needringing(void *pvt, int value)
02963 {
02964 struct dahdi_pvt *p = pvt;
02965 p->subs[SUB_REAL].needringing = value;
02966 }
02967
02968 static void my_set_polarity(void *pvt, int value)
02969 {
02970 struct dahdi_pvt *p = pvt;
02971
02972 if (p->channel == CHAN_PSEUDO) {
02973 return;
02974 }
02975 p->polarity = value;
02976 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02977 }
02978
02979 static void my_start_polarityswitch(void *pvt)
02980 {
02981 struct dahdi_pvt *p = pvt;
02982
02983 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02984 my_set_polarity(pvt, 0);
02985 }
02986 }
02987
02988 static void my_answer_polarityswitch(void *pvt)
02989 {
02990 struct dahdi_pvt *p = pvt;
02991
02992 if (!p->answeronpolarityswitch) {
02993 return;
02994 }
02995
02996 my_set_polarity(pvt, 1);
02997 }
02998
02999 static void my_hangup_polarityswitch(void *pvt)
03000 {
03001 struct dahdi_pvt *p = pvt;
03002
03003 if (!p->hanguponpolarityswitch) {
03004 return;
03005 }
03006
03007 if (p->answeronpolarityswitch) {
03008 my_set_polarity(pvt, 0);
03009 } else {
03010 my_set_polarity(pvt, 1);
03011 }
03012 }
03013
03014 static int my_start(void *pvt)
03015 {
03016 struct dahdi_pvt *p = pvt;
03017 int x = DAHDI_START;
03018
03019 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03020 }
03021
03022 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
03023 {
03024 int index = analogsub_to_dahdisub(sub);
03025 int res;
03026 struct dahdi_pvt *p = pvt;
03027 struct dahdi_dialoperation ddop;
03028
03029 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
03030 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
03031 return -1;
03032 }
03033
03034 if (sub != ANALOG_SUB_REAL) {
03035 ast_log(LOG_ERROR, "Trying to dial_digits '%s' on channel %d subchannel %d\n",
03036 dop->dialstr, p->channel, sub);
03037 return -1;
03038 }
03039
03040 ddop.op = DAHDI_DIAL_OP_REPLACE;
03041 ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
03042
03043 ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
03044
03045 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
03046 if (res == -1) {
03047 ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
03048 }
03049
03050 return res;
03051 }
03052
03053 static void dahdi_train_ec(struct dahdi_pvt *p);
03054
03055 static int my_train_echocanceller(void *pvt)
03056 {
03057 struct dahdi_pvt *p = pvt;
03058
03059 dahdi_train_ec(p);
03060
03061 return 0;
03062 }
03063
03064 static int my_is_dialing(void *pvt, enum analog_sub sub)
03065 {
03066 struct dahdi_pvt *p = pvt;
03067 int index;
03068 int x;
03069
03070 index = analogsub_to_dahdisub(sub);
03071
03072 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
03073 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
03074 return -1;
03075 }
03076
03077 return x;
03078 }
03079
03080 static int my_on_hook(void *pvt)
03081 {
03082 struct dahdi_pvt *p = pvt;
03083 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
03084 }
03085
03086 #if defined(HAVE_PRI)
03087 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
03088 {
03089 struct dahdi_pvt *old_chan = chan_old;
03090 struct dahdi_pvt *new_chan = chan_new;
03091
03092 new_chan->owner = old_chan->owner;
03093 old_chan->owner = NULL;
03094 if (new_chan->owner) {
03095 new_chan->owner->tech_pvt = new_chan;
03096 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
03097 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
03098 old_chan->subs[SUB_REAL].owner = NULL;
03099 }
03100
03101 new_chan->dsp = old_chan->dsp;
03102 new_chan->dsp_features = old_chan->dsp_features;
03103 old_chan->dsp = NULL;
03104 old_chan->dsp_features = 0;
03105
03106
03107 new_chan->dialing = old_chan->dialing;
03108 new_chan->digital = old_chan->digital;
03109 new_chan->outgoing = old_chan->outgoing;
03110 old_chan->dialing = 0;
03111 old_chan->digital = 0;
03112 old_chan->outgoing = 0;
03113
03114
03115 new_chan->law = old_chan->law;
03116 strcpy(new_chan->dialstring, old_chan->dialstring);
03117 }
03118 #endif
03119
03120 #if defined(HAVE_PRI)
03121 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
03122 {
03123 switch (tone) {
03124 case SIG_PRI_TONE_RINGTONE:
03125 return DAHDI_TONE_RINGTONE;
03126 case SIG_PRI_TONE_STUTTER:
03127 return DAHDI_TONE_STUTTER;
03128 case SIG_PRI_TONE_CONGESTION:
03129 return DAHDI_TONE_CONGESTION;
03130 case SIG_PRI_TONE_DIALTONE:
03131 return DAHDI_TONE_DIALTONE;
03132 case SIG_PRI_TONE_DIALRECALL:
03133 return DAHDI_TONE_DIALRECALL;
03134 case SIG_PRI_TONE_INFO:
03135 return DAHDI_TONE_INFO;
03136 case SIG_PRI_TONE_BUSY:
03137 return DAHDI_TONE_BUSY;
03138 default:
03139 return -1;
03140 }
03141 }
03142 #endif
03143
03144 #if defined(HAVE_PRI)
03145 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
03146 {
03147 int x;
03148
03149 ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03150 switch (x) {
03151 case DAHDI_EVENT_NONE:
03152 break;
03153 case DAHDI_EVENT_ALARM:
03154 case DAHDI_EVENT_NOALARM:
03155 if (sig_pri_is_alarm_ignored(pri)) {
03156 break;
03157 }
03158
03159 default:
03160 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n",
03161 event2str(x), x, pri->span);
03162 break;
03163 }
03164
03165 switch (x) {
03166 case DAHDI_EVENT_ALARM:
03167 pri_event_alarm(pri, index, 0);
03168 break;
03169 case DAHDI_EVENT_NOALARM:
03170 pri_event_noalarm(pri, index, 0);
03171 break;
03172 default:
03173 break;
03174 }
03175 }
03176 #endif
03177
03178 #if defined(HAVE_PRI)
03179 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03180 {
03181 struct dahdi_pvt *p = pvt;
03182
03183 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03184 }
03185 #endif
03186
03187 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03199 {
03200 struct dahdi_pvt *p = pvt;
03201
03202 ast_copy_string(p->cid_num,
03203 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03204 sizeof(p->cid_num));
03205 ast_copy_string(p->cid_name,
03206 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03207 sizeof(p->cid_name));
03208 ast_copy_string(p->cid_subaddr,
03209 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03210 sizeof(p->cid_subaddr));
03211 p->cid_ton = caller->id.number.plan;
03212 p->callingpres = ast_party_id_presentation(&caller->id);
03213 if (caller->id.tag) {
03214 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03215 }
03216 ast_copy_string(p->cid_ani,
03217 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03218 sizeof(p->cid_ani));
03219 p->cid_ani2 = caller->ani2;
03220 }
03221 #endif
03222
03223 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234 static void my_set_dnid(void *pvt, const char *dnid)
03235 {
03236 struct dahdi_pvt *p = pvt;
03237
03238 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03239 }
03240 #endif
03241
03242 #if defined(HAVE_PRI)
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253 static void my_set_rdnis(void *pvt, const char *rdnis)
03254 {
03255 struct dahdi_pvt *p = pvt;
03256
03257 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03258 }
03259 #endif
03260
03261 #if defined(HAVE_PRI)
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03287 {
03288 char *dial;
03289 struct dahdi_pvt *pvt;
03290 AST_DECLARE_APP_ARGS(args,
03291 AST_APP_ARG(tech);
03292 AST_APP_ARG(group);
03293
03294
03295
03296 );
03297
03298 pvt = priv;
03299 dial = ast_strdupa(pvt->dialstring);
03300 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03301 if (!args.tech) {
03302 ast_copy_string(buf, pvt->dialstring, buf_size);
03303 return;
03304 }
03305 if (!args.group) {
03306
03307 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03308 return;
03309 }
03310 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03311
03312
03313 ast_copy_string(buf, pvt->dialstring, buf_size);
03314 return;
03315 }
03316
03317 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03318 }
03319 #endif
03320
03321 #if defined(HAVE_PRI)
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03334 {
03335 unsigned idx;
03336 unsigned num_b_chans;
03337 unsigned in_use;
03338 unsigned in_alarm;
03339 enum ast_device_state new_state;
03340
03341
03342 num_b_chans = 0;
03343 in_use = 0;
03344 in_alarm = 1;
03345 for (idx = pri->numchans; idx--;) {
03346 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03347
03348 ++num_b_chans;
03349 if (!sig_pri_is_chan_available(pri->pvts[idx])) {
03350 ++in_use;
03351 }
03352 if (!pri->pvts[idx]->inalarm) {
03353
03354 in_alarm = 0;
03355 }
03356 }
03357 }
03358
03359
03360 if (in_alarm) {
03361 new_state = AST_DEVICE_UNAVAILABLE;
03362 } else {
03363 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03364 }
03365 if (pri->congestion_devstate != new_state) {
03366 pri->congestion_devstate = new_state;
03367 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03368 }
03369 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03370
03371 if (in_alarm) {
03372 new_state = AST_DEVICE_UNAVAILABLE;
03373 } else if (!in_use) {
03374 new_state = AST_DEVICE_NOT_INUSE;
03375 } else if (!pri->user_busy_threshold) {
03376 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03377 } else {
03378 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03379 : AST_DEVICE_BUSY;
03380 }
03381 if (pri->threshold_devstate != new_state) {
03382 pri->threshold_devstate = new_state;
03383 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03384 }
03385 #endif
03386 }
03387 #endif
03388
03389 #if defined(HAVE_PRI)
03390
03391
03392
03393
03394
03395
03396
03397 static void my_module_ref(void)
03398 {
03399 ast_module_ref(ast_module_info->self);
03400 }
03401 #endif
03402
03403 #if defined(HAVE_PRI)
03404
03405
03406
03407
03408
03409
03410
03411 static void my_module_unref(void)
03412 {
03413 ast_module_unref(ast_module_info->self);
03414 }
03415 #endif
03416
03417 #if defined(HAVE_PRI)
03418 #if defined(HAVE_PRI_CALL_WAITING)
03419 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03420 #endif
03421 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03422
03423 static struct sig_pri_callback dahdi_pri_callbacks =
03424 {
03425 .handle_dchan_exception = my_handle_dchan_exception,
03426 .play_tone = my_pri_play_tone,
03427 .set_echocanceller = my_set_echocanceller,
03428 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03429 .lock_private = my_lock_private,
03430 .unlock_private = my_unlock_private,
03431 .new_ast_channel = my_new_pri_ast_channel,
03432 .fixup_chans = my_pri_fixup_chans,
03433 .set_alarm = my_set_alarm,
03434 .set_dialing = my_set_dialing,
03435 .set_outgoing = my_set_outgoing,
03436 .set_digital = my_set_digital,
03437 .set_callerid = my_set_callerid,
03438 .set_dnid = my_set_dnid,
03439 .set_rdnis = my_set_rdnis,
03440 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03441 #if defined(HAVE_PRI_CALL_WAITING)
03442 .init_config = my_pri_init_config,
03443 #endif
03444 .get_orig_dialstring = my_get_orig_dialstring,
03445 .make_cc_dialstring = my_pri_make_cc_dialstring,
03446 .update_span_devstate = dahdi_pri_update_span_devstate,
03447 .module_ref = my_module_ref,
03448 .module_unref = my_module_unref,
03449 .dial_digits = my_pri_dial_digits,
03450 .open_media = my_pri_ss7_open_media,
03451 .ami_channel_event = my_ami_channel_event,
03452 };
03453 #endif
03454
03455 #if defined(HAVE_SS7)
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03467 {
03468 int event;
03469
03470 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03471 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03472 linkset->span, which);
03473 return;
03474 }
03475 switch (event) {
03476 case DAHDI_EVENT_NONE:
03477 break;
03478 case DAHDI_EVENT_ALARM:
03479 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03480 event2str(event), event, linkset->span, which);
03481 sig_ss7_link_alarm(linkset, which);
03482 break;
03483 case DAHDI_EVENT_NOALARM:
03484 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03485 event2str(event), event, linkset->span, which);
03486 sig_ss7_link_noalarm(linkset, which);
03487 break;
03488 default:
03489 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03490 event2str(event), event, linkset->span, which);
03491 break;
03492 }
03493 }
03494 #endif
03495
03496 #if defined(HAVE_SS7)
03497 static void my_ss7_set_loopback(void *pvt, int enable)
03498 {
03499 struct dahdi_pvt *p = pvt;
03500
03501 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03502 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03503 strerror(errno));
03504 }
03505 }
03506 #endif
03507
03508 #if defined(HAVE_SS7)
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523 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)
03524 {
03525 struct dahdi_pvt *p = pvt;
03526 int audio;
03527 int newlaw;
03528
03529
03530 audio = 1;
03531 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03532 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03533 p->channel, audio, strerror(errno));
03534
03535 if (law != SIG_SS7_DEFLAW) {
03536 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03537 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03538 }
03539
03540 ast_copy_string(p->exten, exten, sizeof(p->exten));
03541
03542 newlaw = -1;
03543 switch (law) {
03544 case SIG_SS7_DEFLAW:
03545 newlaw = 0;
03546 break;
03547 case SIG_SS7_ALAW:
03548 newlaw = DAHDI_LAW_ALAW;
03549 break;
03550 case SIG_SS7_ULAW:
03551 newlaw = DAHDI_LAW_MULAW;
03552 break;
03553 }
03554 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03555 }
03556 #endif
03557
03558 #if defined(HAVE_SS7)
03559 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03560 {
03561 switch (tone) {
03562 case SIG_SS7_TONE_RINGTONE:
03563 return DAHDI_TONE_RINGTONE;
03564 case SIG_SS7_TONE_STUTTER:
03565 return DAHDI_TONE_STUTTER;
03566 case SIG_SS7_TONE_CONGESTION:
03567 return DAHDI_TONE_CONGESTION;
03568 case SIG_SS7_TONE_DIALTONE:
03569 return DAHDI_TONE_DIALTONE;
03570 case SIG_SS7_TONE_DIALRECALL:
03571 return DAHDI_TONE_DIALRECALL;
03572 case SIG_SS7_TONE_INFO:
03573 return DAHDI_TONE_INFO;
03574 case SIG_SS7_TONE_BUSY:
03575 return DAHDI_TONE_BUSY;
03576 default:
03577 return -1;
03578 }
03579 }
03580 #endif
03581
03582 #if defined(HAVE_SS7)
03583 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03584 {
03585 struct dahdi_pvt *p = pvt;
03586
03587 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03588 }
03589 #endif
03590
03591 #if defined(HAVE_SS7)
03592 static struct sig_ss7_callback dahdi_ss7_callbacks =
03593 {
03594 .lock_private = my_lock_private,
03595 .unlock_private = my_unlock_private,
03596
03597 .set_echocanceller = my_set_echocanceller,
03598 .set_loopback = my_ss7_set_loopback,
03599
03600 .new_ast_channel = my_new_ss7_ast_channel,
03601 .play_tone = my_ss7_play_tone,
03602
03603 .handle_link_exception = my_handle_link_exception,
03604 .set_alarm = my_set_alarm,
03605 .set_dialing = my_set_dialing,
03606 .set_outgoing = my_set_outgoing,
03607 .set_digital = my_set_digital,
03608 .set_inservice = my_set_inservice,
03609 .set_locallyblocked = my_set_locallyblocked,
03610 .set_remotelyblocked = my_set_remotelyblocked,
03611 .set_callerid = my_set_callerid,
03612 .set_dnid = my_set_dnid,
03613 .open_media = my_pri_ss7_open_media,
03614 };
03615 #endif
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635 static void notify_message(char *mailbox_full, int thereornot)
03636 {
03637 char s[sizeof(mwimonitornotify) + 80];
03638 struct ast_event *event;
03639 char *mailbox, *context;
03640
03641
03642 context = mailbox = ast_strdupa(mailbox_full);
03643 strsep(&context, "@");
03644 if (ast_strlen_zero(context))
03645 context = "default";
03646
03647 if (!(event = ast_event_new(AST_EVENT_MWI,
03648 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03649 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03650 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03651 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03652 AST_EVENT_IE_END))) {
03653 return;
03654 }
03655
03656 ast_event_queue_and_cache(event);
03657
03658 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03659 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03660 ast_safe_system(s);
03661 }
03662 }
03663
03664 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03665 {
03666 struct dahdi_pvt *p = pvt;
03667
03668 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03669 return;
03670
03671 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03672 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03673 notify_message(p->mailbox, 1);
03674 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03675 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03676 notify_message(p->mailbox, 0);
03677 }
03678
03679
03680 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03681 ast_hangup(chan);
03682 return;
03683 }
03684 }
03685
03686 static int my_have_progressdetect(void *pvt)
03687 {
03688 struct dahdi_pvt *p = pvt;
03689
03690 if ((p->callprogress & CALLPROGRESS_PROGRESS)
03691 && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
03692 return 1;
03693 } else {
03694
03695 return 0;
03696 }
03697 }
03698
03699 static struct analog_callback dahdi_analog_callbacks =
03700 {
03701 .play_tone = my_play_tone,
03702 .get_event = my_get_event,
03703 .wait_event = my_wait_event,
03704 .is_off_hook = my_is_off_hook,
03705 .set_echocanceller = my_set_echocanceller,
03706 .ring = my_ring,
03707 .flash = my_flash,
03708 .off_hook = my_off_hook,
03709 .dial_digits = my_dial_digits,
03710 .train_echocanceller = my_train_echocanceller,
03711 .on_hook = my_on_hook,
03712 .is_dialing = my_is_dialing,
03713 .allocate_sub = my_allocate_sub,
03714 .unallocate_sub = my_unallocate_sub,
03715 .swap_subs = my_swap_subchannels,
03716 .has_voicemail = my_has_voicemail,
03717 .check_for_conference = my_check_for_conference,
03718 .conf_add = my_conf_add,
03719 .conf_del = my_conf_del,
03720 .complete_conference_update = my_complete_conference_update,
03721 .start = my_start,
03722 .all_subchannels_hungup = my_all_subchannels_hungup,
03723 .lock_private = my_lock_private,
03724 .unlock_private = my_unlock_private,
03725 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03726 .handle_dtmf = my_handle_dtmf,
03727 .wink = my_wink,
03728 .new_ast_channel = my_new_analog_ast_channel,
03729 .dsp_set_digitmode = my_dsp_set_digitmode,
03730 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03731 .send_callerid = my_send_callerid,
03732 .callwait = my_callwait,
03733 .stop_callwait = my_stop_callwait,
03734 .get_callerid = my_get_callerid,
03735 .start_cid_detect = my_start_cid_detect,
03736 .stop_cid_detect = my_stop_cid_detect,
03737 .handle_notify_message = my_handle_notify_message,
03738 .increase_ss_count = my_increase_ss_count,
03739 .decrease_ss_count = my_decrease_ss_count,
03740 .distinctive_ring = my_distinctive_ring,
03741 .set_linear_mode = my_set_linear_mode,
03742 .set_inthreeway = my_set_inthreeway,
03743 .get_and_handle_alarms = my_get_and_handle_alarms,
03744 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03745 .get_sub_fd = my_get_sub_fd,
03746 .set_cadence = my_set_cadence,
03747 .set_alarm = my_set_alarm,
03748 .set_dialing = my_set_dialing,
03749 .set_outgoing = my_set_outgoing,
03750 .set_ringtimeout = my_set_ringtimeout,
03751 .set_waitingfordt = my_set_waitingfordt,
03752 .check_waitingfordt = my_check_waitingfordt,
03753 .set_confirmanswer = my_set_confirmanswer,
03754 .check_confirmanswer = my_check_confirmanswer,
03755 .set_callwaiting = my_set_callwaiting,
03756 .cancel_cidspill = my_cancel_cidspill,
03757 .confmute = my_confmute,
03758 .set_pulsedial = my_set_pulsedial,
03759 .set_new_owner = my_set_new_owner,
03760 .get_orig_dialstring = my_get_orig_dialstring,
03761 .set_needringing = my_set_needringing,
03762 .set_polarity = my_set_polarity,
03763 .start_polarityswitch = my_start_polarityswitch,
03764 .answer_polarityswitch = my_answer_polarityswitch,
03765 .hangup_polarityswitch = my_hangup_polarityswitch,
03766 .have_progressdetect = my_have_progressdetect,
03767 };
03768
03769
03770 static struct dahdi_pvt *round_robin[32];
03771
03772 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03773 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03774 {
03775 int res;
03776 if (p->subs[SUB_REAL].owner == ast)
03777 res = 0;
03778 else if (p->subs[SUB_CALLWAIT].owner == ast)
03779 res = 1;
03780 else if (p->subs[SUB_THREEWAY].owner == ast)
03781 res = 2;
03782 else {
03783 res = -1;
03784 if (!nullok)
03785 ast_log(LOG_WARNING,
03786 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03787 ast ? ast->name : "", p->channel, fname, line);
03788 }
03789 return res;
03790 }
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03808 {
03809 for (;;) {
03810 if (!pvt->subs[sub_idx].owner) {
03811
03812 break;
03813 }
03814 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03815
03816 break;
03817 }
03818
03819 DEADLOCK_AVOIDANCE(&pvt->lock);
03820 }
03821 }
03822
03823 static void wakeup_sub(struct dahdi_pvt *p, int a)
03824 {
03825 dahdi_lock_sub_owner(p, a);
03826 if (p->subs[a].owner) {
03827 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03828 ast_channel_unlock(p->subs[a].owner);
03829 }
03830 }
03831
03832 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03833 {
03834 for (;;) {
03835 if (p->owner) {
03836 if (ast_channel_trylock(p->owner)) {
03837 DEADLOCK_AVOIDANCE(&p->lock);
03838 } else {
03839 ast_queue_frame(p->owner, f);
03840 ast_channel_unlock(p->owner);
03841 break;
03842 }
03843 } else
03844 break;
03845 }
03846 }
03847
03848 static void handle_clear_alarms(struct dahdi_pvt *p)
03849 {
03850 #if defined(HAVE_PRI)
03851 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
03852 return;
03853 }
03854 #endif
03855
03856 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03857 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03858 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03859 }
03860 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03861 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03862 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03863 }
03864 }
03865
03866 #ifdef HAVE_OPENR2
03867
03868 static int dahdi_r2_answer(struct dahdi_pvt *p)
03869 {
03870 int res = 0;
03871
03872
03873
03874 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03875 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03876 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03877 if (!double_answer) {
03878
03879
03880 res = openr2_chan_answer_call(p->r2chan);
03881 } else if (wants_double_answer) {
03882 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03883 } else {
03884 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03885 }
03886 #else
03887 res = openr2_chan_answer_call(p->r2chan);
03888 #endif
03889 return res;
03890 }
03891
03892
03893
03894
03895 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03896 {
03897 openr2_calling_party_category_t cat;
03898 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03899 struct dahdi_pvt *p = c->tech_pvt;
03900 if (ast_strlen_zero(catstr)) {
03901 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03902 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03903 return p->mfcr2_category;
03904 }
03905 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03906 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03907 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03908 return p->mfcr2_category;
03909 }
03910 ast_debug(1, "Using category %s\n", catstr);
03911 return cat;
03912 }
03913
03914 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03915 {
03916 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03917 ast_mutex_lock(&p->lock);
03918 if (p->mfcr2call) {
03919 ast_mutex_unlock(&p->lock);
03920
03921
03922
03923
03924
03925 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03926 return;
03927 }
03928 p->mfcr2call = 1;
03929
03930 p->cid_name[0] = '\0';
03931 p->cid_num[0] = '\0';
03932 p->cid_subaddr[0] = '\0';
03933 p->rdnis[0] = '\0';
03934 p->exten[0] = '\0';
03935 p->mfcr2_ani_index = '\0';
03936 p->mfcr2_dnis_index = '\0';
03937 p->mfcr2_dnis_matched = 0;
03938 p->mfcr2_answer_pending = 0;
03939 p->mfcr2_call_accepted = 0;
03940 ast_mutex_unlock(&p->lock);
03941 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03942 }
03943
03944 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03945 {
03946 int res;
03947 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03948 ast_mutex_lock(&p->lock);
03949 p->inalarm = alarm ? 1 : 0;
03950 if (p->inalarm) {
03951 res = get_alarms(p);
03952 handle_alarms(p, res);
03953 } else {
03954 handle_clear_alarms(p);
03955 }
03956 ast_mutex_unlock(&p->lock);
03957 }
03958
03959 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03960 {
03961 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03962 }
03963
03964 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03965 {
03966 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03967 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03968 if (p->owner) {
03969 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03970 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03971 }
03972 ast_mutex_lock(&p->lock);
03973 p->mfcr2call = 0;
03974 ast_mutex_unlock(&p->lock);
03975 }
03976
03977 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03978 {
03979 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03980 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03981 p->channel, openr2_proto_get_disconnect_string(cause));
03982
03983 openr2_chan_set_idle(p->r2chan);
03984 ast_mutex_lock(&p->lock);
03985 p->mfcr2call = 0;
03986 ast_mutex_unlock(&p->lock);
03987 }
03988 }
03989
03990 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03991 {
03992 struct dahdi_pvt *p;
03993 struct ast_channel *c;
03994 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03995 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03996 openr2_proto_get_category_string(category));
03997 p = openr2_chan_get_client_data(r2chan);
03998
03999 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
04000 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
04001 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
04002 return;
04003 }
04004 ast_mutex_lock(&p->lock);
04005 p->mfcr2_recvd_category = category;
04006
04007 if (!p->use_callerid) {
04008 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
04009 p->cid_num[0] = 0;
04010 p->cid_name[0] = 0;
04011 }
04012
04013 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
04014 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
04015 p->exten[0] = 's';
04016 p->exten[1] = 0;
04017 }
04018 ast_mutex_unlock(&p->lock);
04019 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04020 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
04021 p->channel, p->exten, p->context);
04022 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
04023 return;
04024 }
04025 if (!p->mfcr2_accept_on_offer) {
04026
04027 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04028 if (c) {
04029
04030
04031
04032 return;
04033 }
04034 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04035 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04036 } else if (p->mfcr2_charge_calls) {
04037 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
04038 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
04039 } else {
04040 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
04041 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
04042 }
04043 }
04044
04045 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
04046 {
04047 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04048 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
04049 ast_mutex_lock(&p->lock);
04050 p->mfcr2call = 0;
04051 ast_mutex_unlock(&p->lock);
04052 }
04053
04054 static void dahdi_enable_ec(struct dahdi_pvt *p);
04055 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
04056 {
04057 struct dahdi_pvt *p = NULL;
04058 struct ast_channel *c = NULL;
04059 p = openr2_chan_get_client_data(r2chan);
04060 dahdi_enable_ec(p);
04061 p->mfcr2_call_accepted = 1;
04062
04063 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
04064 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
04065
04066
04067
04068
04069 if (!p->mfcr2_accept_on_offer) {
04070 openr2_chan_disable_read(r2chan);
04071 if (p->mfcr2_answer_pending) {
04072 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
04073 dahdi_r2_answer(p);
04074 }
04075 return;
04076 }
04077 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
04078 if (c) {
04079
04080
04081 openr2_chan_disable_read(r2chan);
04082 return;
04083 }
04084 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
04085
04086 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
04087 return;
04088 }
04089
04090 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
04091 p->subs[SUB_REAL].needringing = 1;
04092 p->dialing = 0;
04093
04094 openr2_chan_disable_read(r2chan);
04095 }
04096
04097 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
04098 {
04099 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04100 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
04101 p->subs[SUB_REAL].needanswer = 1;
04102 }
04103
04104 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
04105 {
04106
04107 }
04108
04109 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
04110 {
04111 switch (cause) {
04112 case OR2_CAUSE_BUSY_NUMBER:
04113 return AST_CAUSE_BUSY;
04114 case OR2_CAUSE_NETWORK_CONGESTION:
04115 return AST_CAUSE_CONGESTION;
04116 case OR2_CAUSE_OUT_OF_ORDER:
04117 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04118 case OR2_CAUSE_UNALLOCATED_NUMBER:
04119 return AST_CAUSE_UNREGISTERED;
04120 case OR2_CAUSE_NO_ANSWER:
04121 return AST_CAUSE_NO_ANSWER;
04122 case OR2_CAUSE_NORMAL_CLEARING:
04123 return AST_CAUSE_NORMAL_CLEARING;
04124 case OR2_CAUSE_UNSPECIFIED:
04125 default:
04126 return AST_CAUSE_NOTDEFINED;
04127 }
04128 }
04129
04130 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
04131 {
04132 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04133 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
04134 ast_mutex_lock(&p->lock);
04135 if (!p->owner) {
04136 ast_mutex_unlock(&p->lock);
04137
04138 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
04139 return;
04140 }
04141
04142
04143 if (p->owner->_state == AST_STATE_UP) {
04144 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04145 ast_mutex_unlock(&p->lock);
04146 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
04147
04148 switch (cause) {
04149 case OR2_CAUSE_BUSY_NUMBER:
04150 p->subs[SUB_REAL].needbusy = 1;
04151 break;
04152 case OR2_CAUSE_NETWORK_CONGESTION:
04153 case OR2_CAUSE_OUT_OF_ORDER:
04154 case OR2_CAUSE_UNALLOCATED_NUMBER:
04155 case OR2_CAUSE_NO_ANSWER:
04156 case OR2_CAUSE_UNSPECIFIED:
04157 case OR2_CAUSE_NORMAL_CLEARING:
04158 p->subs[SUB_REAL].needcongestion = 1;
04159 break;
04160 default:
04161 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04162 }
04163 ast_mutex_unlock(&p->lock);
04164 } else {
04165 ast_mutex_unlock(&p->lock);
04166
04167
04168 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
04169 }
04170 }
04171
04172 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
04173 {
04174 switch (level) {
04175 case OR2_LOG_NOTICE:
04176 ast_verbose("%s", logmessage);
04177 break;
04178 case OR2_LOG_WARNING:
04179 ast_log(LOG_WARNING, "%s", logmessage);
04180 break;
04181 case OR2_LOG_ERROR:
04182 ast_log(LOG_ERROR, "%s", logmessage);
04183 break;
04184 case OR2_LOG_STACK_TRACE:
04185 case OR2_LOG_MF_TRACE:
04186 case OR2_LOG_CAS_TRACE:
04187 case OR2_LOG_DEBUG:
04188 case OR2_LOG_EX_DEBUG:
04189 ast_log(LOG_DEBUG, "%s", logmessage);
04190 break;
04191 default:
04192 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04193 ast_log(LOG_DEBUG, "%s", logmessage);
04194 break;
04195 }
04196 }
04197
04198 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04199 {
04200 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04201 ast_mutex_lock(&p->lock);
04202 p->remotelyblocked = 1;
04203 ast_mutex_unlock(&p->lock);
04204 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04205 }
04206
04207 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04208 {
04209 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04210 ast_mutex_lock(&p->lock);
04211 p->remotelyblocked = 0;
04212 ast_mutex_unlock(&p->lock);
04213 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04214 }
04215
04216 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04217 __attribute__((format (printf, 3, 0)));
04218 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04219 {
04220 #define CONTEXT_TAG "Context - "
04221 char logmsg[256];
04222 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04223 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04224 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04225 dahdi_r2_write_log(level, completemsg);
04226 #undef CONTEXT_TAG
04227 }
04228
04229 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04230 __attribute__((format (printf, 3, 0)));
04231 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04232 {
04233 #define CHAN_TAG "Chan "
04234 char logmsg[256];
04235 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04236 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04237 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04238 dahdi_r2_write_log(level, completemsg);
04239 }
04240
04241 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04242 {
04243 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04244
04245 if (p->immediate) {
04246 return 0;
04247 }
04248 p->exten[p->mfcr2_dnis_index] = digit;
04249 p->rdnis[p->mfcr2_dnis_index] = digit;
04250 p->mfcr2_dnis_index++;
04251 p->exten[p->mfcr2_dnis_index] = 0;
04252 p->rdnis[p->mfcr2_dnis_index] = 0;
04253
04254 if ((p->mfcr2_dnis_matched ||
04255 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04256 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04257 return 0;
04258 }
04259
04260 return 1;
04261 }
04262
04263 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04264 {
04265 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04266 p->cid_num[p->mfcr2_ani_index] = digit;
04267 p->cid_name[p->mfcr2_ani_index] = digit;
04268 p->mfcr2_ani_index++;
04269 p->cid_num[p->mfcr2_ani_index] = 0;
04270 p->cid_name[p->mfcr2_ani_index] = 0;
04271 }
04272
04273 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04274 {
04275 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04276 }
04277
04278 static openr2_event_interface_t dahdi_r2_event_iface = {
04279 .on_call_init = dahdi_r2_on_call_init,
04280 .on_call_offered = dahdi_r2_on_call_offered,
04281 .on_call_accepted = dahdi_r2_on_call_accepted,
04282 .on_call_answered = dahdi_r2_on_call_answered,
04283 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04284 .on_call_end = dahdi_r2_on_call_end,
04285 .on_call_read = dahdi_r2_on_call_read,
04286 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04287 .on_os_error = dahdi_r2_on_os_error,
04288 .on_protocol_error = dahdi_r2_on_protocol_error,
04289 .on_line_blocked = dahdi_r2_on_line_blocked,
04290 .on_line_idle = dahdi_r2_on_line_idle,
04291
04292 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04293 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04294 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04295
04296 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04297 };
04298
04299 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04300 {
04301 return AST_ALAW(sample);
04302 }
04303
04304 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04305 {
04306 return AST_LIN2A(sample);
04307 }
04308
04309 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04310 dahdi_r2_alaw_to_linear,
04311 dahdi_r2_linear_to_alaw
04312 };
04313
04314 #endif
04315
04316 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04317 {
04318 int tchan;
04319 int tinthreeway;
04320 struct ast_channel *towner;
04321
04322 ast_debug(1, "Swapping %d and %d\n", a, b);
04323
04324 tchan = p->subs[a].chan;
04325 towner = p->subs[a].owner;
04326 tinthreeway = p->subs[a].inthreeway;
04327
04328 p->subs[a].chan = p->subs[b].chan;
04329 p->subs[a].owner = p->subs[b].owner;
04330 p->subs[a].inthreeway = p->subs[b].inthreeway;
04331
04332 p->subs[b].chan = tchan;
04333 p->subs[b].owner = towner;
04334 p->subs[b].inthreeway = tinthreeway;
04335
04336 if (p->subs[a].owner)
04337 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04338 if (p->subs[b].owner)
04339 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04340 wakeup_sub(p, a);
04341 wakeup_sub(p, b);
04342 }
04343
04344 static int dahdi_open(char *fn)
04345 {
04346 int fd;
04347 int isnum;
04348 int chan = 0;
04349 int bs;
04350 int x;
04351 isnum = 1;
04352 for (x = 0; x < strlen(fn); x++) {
04353 if (!isdigit(fn[x])) {
04354 isnum = 0;
04355 break;
04356 }
04357 }
04358 if (isnum) {
04359 chan = atoi(fn);
04360 if (chan < 1) {
04361 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04362 return -1;
04363 }
04364 fn = "/dev/dahdi/channel";
04365 }
04366 fd = open(fn, O_RDWR | O_NONBLOCK);
04367 if (fd < 0) {
04368 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04369 return -1;
04370 }
04371 if (chan) {
04372 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04373 x = errno;
04374 close(fd);
04375 errno = x;
04376 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04377 return -1;
04378 }
04379 }
04380 bs = READ_SIZE;
04381 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04382 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04383 x = errno;
04384 close(fd);
04385 errno = x;
04386 return -1;
04387 }
04388 return fd;
04389 }
04390
04391 static void dahdi_close(int fd)
04392 {
04393 if (fd > 0)
04394 close(fd);
04395 }
04396
04397 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04398 {
04399 dahdi_close(chan_pvt->subs[sub_num].dfd);
04400 chan_pvt->subs[sub_num].dfd = -1;
04401 }
04402
04403 #if defined(HAVE_PRI)
04404 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04405 {
04406 dahdi_close(pri->pri.fds[fd_num]);
04407 pri->pri.fds[fd_num] = -1;
04408 }
04409 #endif
04410
04411 #if defined(HAVE_SS7)
04412 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04413 {
04414 dahdi_close(ss7->ss7.fds[fd_num]);
04415 ss7->ss7.fds[fd_num] = -1;
04416 }
04417 #endif
04418
04419 static int dahdi_setlinear(int dfd, int linear)
04420 {
04421 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04422 }
04423
04424
04425 static int alloc_sub(struct dahdi_pvt *p, int x)
04426 {
04427 struct dahdi_bufferinfo bi;
04428 int res;
04429 if (p->subs[x].dfd >= 0) {
04430 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04431 return -1;
04432 }
04433
04434 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04435 if (p->subs[x].dfd <= -1) {
04436 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04437 return -1;
04438 }
04439
04440 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04441 if (!res) {
04442 bi.txbufpolicy = p->buf_policy;
04443 bi.rxbufpolicy = p->buf_policy;
04444 bi.numbufs = p->buf_no;
04445 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04446 if (res < 0) {
04447 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04448 }
04449 } else
04450 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04451
04452 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04453 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04454 dahdi_close_sub(p, x);
04455 p->subs[x].dfd = -1;
04456 return -1;
04457 }
04458 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04459 return 0;
04460 }
04461
04462 static int unalloc_sub(struct dahdi_pvt *p, int x)
04463 {
04464 if (!x) {
04465 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04466 return -1;
04467 }
04468 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04469 dahdi_close_sub(p, x);
04470 p->subs[x].linear = 0;
04471 p->subs[x].chan = 0;
04472 p->subs[x].owner = NULL;
04473 p->subs[x].inthreeway = 0;
04474 p->polarity = POLARITY_IDLE;
04475 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04476 return 0;
04477 }
04478
04479 static int digit_to_dtmfindex(char digit)
04480 {
04481 if (isdigit(digit))
04482 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04483 else if (digit >= 'A' && digit <= 'D')
04484 return DAHDI_TONE_DTMF_A + (digit - 'A');
04485 else if (digit >= 'a' && digit <= 'd')
04486 return DAHDI_TONE_DTMF_A + (digit - 'a');
04487 else if (digit == '*')
04488 return DAHDI_TONE_DTMF_s;
04489 else if (digit == '#')
04490 return DAHDI_TONE_DTMF_p;
04491 else
04492 return -1;
04493 }
04494
04495 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04496 {
04497 struct dahdi_pvt *pvt;
04498 int idx;
04499 int dtmf = -1;
04500 int res;
04501
04502 pvt = chan->tech_pvt;
04503
04504 ast_mutex_lock(&pvt->lock);
04505
04506 idx = dahdi_get_index(chan, pvt, 0);
04507
04508 if ((idx != SUB_REAL) || !pvt->owner)
04509 goto out;
04510
04511 #ifdef HAVE_PRI
04512 switch (pvt->sig) {
04513 case SIG_PRI_LIB_HANDLE_CASES:
04514 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04515 if (!res)
04516 goto out;
04517 break;
04518 default:
04519 break;
04520 }
04521 #endif
04522 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04523 goto out;
04524
04525 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04526 struct dahdi_dialoperation zo = {
04527 .op = DAHDI_DIAL_OP_APPEND,
04528 };
04529
04530 zo.dialstr[0] = 'T';
04531 zo.dialstr[1] = digit;
04532 zo.dialstr[2] = '\0';
04533 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04534 ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
04535 chan->name, digit, strerror(errno));
04536 else
04537 pvt->dialing = 1;
04538 } else {
04539 ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
04540 chan->name, digit);
04541 pvt->dialing = 1;
04542 pvt->begindigit = digit;
04543 }
04544
04545 out:
04546 ast_mutex_unlock(&pvt->lock);
04547
04548 return 0;
04549 }
04550
04551 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04552 {
04553 struct dahdi_pvt *pvt;
04554 int res = 0;
04555 int idx;
04556 int x;
04557
04558 pvt = chan->tech_pvt;
04559
04560 ast_mutex_lock(&pvt->lock);
04561
04562 idx = dahdi_get_index(chan, pvt, 0);
04563
04564 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04565 goto out;
04566
04567 #ifdef HAVE_PRI
04568
04569 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04570 goto out;
04571 }
04572 #endif
04573
04574 if (pvt->begindigit) {
04575 x = -1;
04576 ast_debug(1, "Channel %s ending VLDTMF digit '%c'\n",
04577 chan->name, digit);
04578 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04579 pvt->dialing = 0;
04580 pvt->begindigit = 0;
04581 }
04582
04583 out:
04584 ast_mutex_unlock(&pvt->lock);
04585
04586 return res;
04587 }
04588
04589 static const char * const events[] = {
04590 "No event",
04591 "On hook",
04592 "Ring/Answered",
04593 "Wink/Flash",
04594 "Alarm",
04595 "No more alarm",
04596 "HDLC Abort",
04597 "HDLC Overrun",
04598 "HDLC Bad FCS",
04599 "Dial Complete",
04600 "Ringer On",
04601 "Ringer Off",
04602 "Hook Transition Complete",
04603 "Bits Changed",
04604 "Pulse Start",
04605 "Timer Expired",
04606 "Timer Ping",
04607 "Polarity Reversal",
04608 "Ring Begin",
04609 };
04610
04611 static struct {
04612 int alarm;
04613 char *name;
04614 } alarms[] = {
04615 { DAHDI_ALARM_RED, "Red Alarm" },
04616 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04617 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04618 { DAHDI_ALARM_RECOVER, "Recovering" },
04619 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04620 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04621 { DAHDI_ALARM_NONE, "None" },
04622 };
04623
04624 static char *alarm2str(int alm)
04625 {
04626 int x;
04627 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04628 if (alarms[x].alarm & alm)
04629 return alarms[x].name;
04630 }
04631 return alm ? "Unknown Alarm" : "No Alarm";
04632 }
04633
04634 static const char *event2str(int event)
04635 {
04636 static char buf[256];
04637 if ((event < (ARRAY_LEN(events))) && (event > -1))
04638 return events[event];
04639 sprintf(buf, "Event %d", event);
04640 return buf;
04641 }
04642
04643 static char *dahdi_sig2str(int sig)
04644 {
04645 static char buf[256];
04646 switch (sig) {
04647 case SIG_EM:
04648 return "E & M Immediate";
04649 case SIG_EMWINK:
04650 return "E & M Wink";
04651 case SIG_EM_E1:
04652 return "E & M E1";
04653 case SIG_FEATD:
04654 return "Feature Group D (DTMF)";
04655 case SIG_FEATDMF:
04656 return "Feature Group D (MF)";
04657 case SIG_FEATDMF_TA:
04658 return "Feature Groud D (MF) Tandem Access";
04659 case SIG_FEATB:
04660 return "Feature Group B (MF)";
04661 case SIG_E911:
04662 return "E911 (MF)";
04663 case SIG_FGC_CAMA:
04664 return "FGC/CAMA (Dialpulse)";
04665 case SIG_FGC_CAMAMF:
04666 return "FGC/CAMA (MF)";
04667 case SIG_FXSLS:
04668 return "FXS Loopstart";
04669 case SIG_FXSGS:
04670 return "FXS Groundstart";
04671 case SIG_FXSKS:
04672 return "FXS Kewlstart";
04673 case SIG_FXOLS:
04674 return "FXO Loopstart";
04675 case SIG_FXOGS:
04676 return "FXO Groundstart";
04677 case SIG_FXOKS:
04678 return "FXO Kewlstart";
04679 case SIG_PRI:
04680 return "ISDN PRI";
04681 case SIG_BRI:
04682 return "ISDN BRI Point to Point";
04683 case SIG_BRI_PTMP:
04684 return "ISDN BRI Point to MultiPoint";
04685 case SIG_SS7:
04686 return "SS7";
04687 case SIG_MFCR2:
04688 return "MFC/R2";
04689 case SIG_SF:
04690 return "SF (Tone) Immediate";
04691 case SIG_SFWINK:
04692 return "SF (Tone) Wink";
04693 case SIG_SF_FEATD:
04694 return "SF (Tone) with Feature Group D (DTMF)";
04695 case SIG_SF_FEATDMF:
04696 return "SF (Tone) with Feature Group D (MF)";
04697 case SIG_SF_FEATB:
04698 return "SF (Tone) with Feature Group B (MF)";
04699 case 0:
04700 return "Pseudo";
04701 default:
04702 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04703 return buf;
04704 }
04705 }
04706
04707 #define sig2str dahdi_sig2str
04708
04709 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04710 {
04711
04712
04713 struct dahdi_confinfo zi;
04714
04715 memset(&zi, 0, sizeof(zi));
04716 zi.chan = 0;
04717
04718 if (slavechannel > 0) {
04719
04720 zi.confmode = DAHDI_CONF_DIGITALMON;
04721 zi.confno = slavechannel;
04722 } else {
04723 if (!idx) {
04724
04725 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04726 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04727 } else
04728 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04729 zi.confno = p->confno;
04730 }
04731 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04732 return 0;
04733 if (c->dfd < 0)
04734 return 0;
04735 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04736 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04737 return -1;
04738 }
04739 if (slavechannel < 1) {
04740 p->confno = zi.confno;
04741 }
04742 c->curconf = zi;
04743 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04744 return 0;
04745 }
04746
04747 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04748 {
04749
04750 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04751 return 1;
04752
04753 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04754 return 1;
04755 return 0;
04756 }
04757
04758 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04759 {
04760 struct dahdi_confinfo zi;
04761 if (
04762 (c->dfd < 0) ||
04763
04764 !isourconf(p, c)
04765
04766 ) return 0;
04767 memset(&zi, 0, sizeof(zi));
04768 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04769 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04770 return -1;
04771 }
04772 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04773 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04774 return 0;
04775 }
04776
04777 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04778 {
04779 int x;
04780 int useslavenative;
04781 struct dahdi_pvt *slave = NULL;
04782
04783 useslavenative = 1;
04784
04785 for (x = 0; x < 3; x++) {
04786
04787
04788 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04789 useslavenative = 0;
04790 }
04791
04792
04793 if (useslavenative) {
04794 for (x = 0; x < MAX_SLAVES; x++) {
04795 if (p->slaves[x]) {
04796 if (slave) {
04797
04798
04799 slave = NULL;
04800 useslavenative = 0;
04801 break;
04802 } else {
04803
04804 slave = p->slaves[x];
04805 }
04806 }
04807 }
04808 }
04809
04810 if (!slave)
04811 useslavenative = 0;
04812 else if (slave->law != p->law) {
04813 useslavenative = 0;
04814 slave = NULL;
04815 }
04816 if (out)
04817 *out = slave;
04818 return useslavenative;
04819 }
04820
04821 static int reset_conf(struct dahdi_pvt *p)
04822 {
04823 p->confno = -1;
04824 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04825 if (p->subs[SUB_REAL].dfd > -1) {
04826 struct dahdi_confinfo zi;
04827
04828 memset(&zi, 0, sizeof(zi));
04829 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04830 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04831 }
04832 return 0;
04833 }
04834
04835 static int update_conf(struct dahdi_pvt *p)
04836 {
04837 int needconf = 0;
04838 int x;
04839 int useslavenative;
04840 struct dahdi_pvt *slave = NULL;
04841
04842 useslavenative = isslavenative(p, &slave);
04843
04844 for (x = 0; x < 3; x++) {
04845
04846 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04847 conf_add(p, &p->subs[x], x, 0);
04848 needconf++;
04849 } else {
04850 conf_del(p, &p->subs[x], x);
04851 }
04852 }
04853
04854
04855 for (x = 0; x < MAX_SLAVES; x++) {
04856 if (p->slaves[x]) {
04857 if (useslavenative)
04858 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04859 else {
04860 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04861 needconf++;
04862 }
04863 }
04864 }
04865
04866 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04867 if (useslavenative)
04868 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04869 else {
04870 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04871 needconf++;
04872 }
04873 }
04874
04875 if (p->master) {
04876 if (isslavenative(p->master, NULL)) {
04877 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04878 } else {
04879 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04880 }
04881 }
04882 if (!needconf) {
04883
04884
04885 p->confno = -1;
04886 }
04887 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04888 return 0;
04889 }
04890
04891 static void dahdi_enable_ec(struct dahdi_pvt *p)
04892 {
04893 int res;
04894 if (!p)
04895 return;
04896 if (p->echocanon) {
04897 ast_debug(1, "Echo cancellation already on\n");
04898 return;
04899 }
04900 if (p->digital) {
04901 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04902 return;
04903 }
04904 if (p->echocancel.head.tap_length) {
04905 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04906 switch (p->sig) {
04907 #if defined(HAVE_PRI)
04908 case SIG_PRI_LIB_HANDLE_CASES:
04909 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04910
04911
04912
04913
04914 return;
04915 }
04916
04917 #endif
04918 #if defined(HAVE_SS7)
04919 case SIG_SS7:
04920 #endif
04921 {
04922 int x = 1;
04923
04924 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04925 if (res)
04926 ast_log(LOG_WARNING,
04927 "Unable to enable audio mode on channel %d (%s)\n",
04928 p->channel, strerror(errno));
04929 }
04930 break;
04931 default:
04932 break;
04933 }
04934 #endif
04935 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04936 if (res) {
04937 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04938 } else {
04939 p->echocanon = 1;
04940 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04941 }
04942 } else
04943 ast_debug(1, "No echo cancellation requested\n");
04944 }
04945
04946 static void dahdi_train_ec(struct dahdi_pvt *p)
04947 {
04948 int x;
04949 int res;
04950
04951 if (p && p->echocanon && p->echotraining) {
04952 x = p->echotraining;
04953 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04954 if (res)
04955 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04956 else
04957 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04958 } else {
04959 ast_debug(1, "No echo training requested\n");
04960 }
04961 }
04962
04963 static void dahdi_disable_ec(struct dahdi_pvt *p)
04964 {
04965 int res;
04966
04967 if (p->echocanon) {
04968 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04969
04970 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04971
04972 if (res)
04973 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04974 else
04975 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04976 }
04977
04978 p->echocanon = 0;
04979 }
04980
04981
04982 static int drc_sample(int sample, float drc)
04983 {
04984 float neg;
04985 float shallow, steep;
04986 float max = SHRT_MAX;
04987
04988 neg = (sample < 0 ? -1 : 1);
04989 steep = drc*sample;
04990 shallow = neg*(max-max/drc)+(float)sample/drc;
04991 if (abs(steep) < abs(shallow)) {
04992 sample = steep;
04993 }
04994 else {
04995 sample = shallow;
04996 }
04997
04998 return sample;
04999 }
05000
05001
05002 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
05003 {
05004 int j;
05005 int k;
05006
05007 float linear_gain = pow(10.0, gain / 20.0);
05008
05009 switch (law) {
05010 case DAHDI_LAW_ALAW:
05011 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05012 if (gain || drc) {
05013 k = AST_ALAW(j);
05014 if (drc) {
05015 k = drc_sample(k, drc);
05016 }
05017 k = (float)k*linear_gain;
05018 if (k > 32767) k = 32767;
05019 if (k < -32767) k = -32767;
05020 g->txgain[j] = AST_LIN2A(k);
05021 } else {
05022 g->txgain[j] = j;
05023 }
05024 }
05025 break;
05026 case DAHDI_LAW_MULAW:
05027 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
05028 if (gain || drc) {
05029 k = AST_MULAW(j);
05030 if (drc) {
05031 k = drc_sample(k, drc);
05032 }
05033 k = (float)k*linear_gain;
05034 if (k > 32767) k = 32767;
05035 if (k < -32767) k = -32767;
05036 g->txgain[j] = AST_LIN2MU(k);
05037
05038 } else {
05039 g->txgain[j] = j;
05040 }
05041 }
05042 break;
05043 }
05044 }
05045
05046 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
05047 {
05048 int j;
05049 int k;
05050 float linear_gain = pow(10.0, gain / 20.0);
05051
05052 switch (law) {
05053 case DAHDI_LAW_ALAW:
05054 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05055 if (gain || drc) {
05056 k = AST_ALAW(j);
05057 if (drc) {
05058 k = drc_sample(k, drc);
05059 }
05060 k = (float)k*linear_gain;
05061 if (k > 32767) k = 32767;
05062 if (k < -32767) k = -32767;
05063 g->rxgain[j] = AST_LIN2A(k);
05064 } else {
05065 g->rxgain[j] = j;
05066 }
05067 }
05068 break;
05069 case DAHDI_LAW_MULAW:
05070 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
05071 if (gain || drc) {
05072 k = AST_MULAW(j);
05073 if (drc) {
05074 k = drc_sample(k, drc);
05075 }
05076 k = (float)k*linear_gain;
05077 if (k > 32767) k = 32767;
05078 if (k < -32767) k = -32767;
05079 g->rxgain[j] = AST_LIN2MU(k);
05080 } else {
05081 g->rxgain[j] = j;
05082 }
05083 }
05084 break;
05085 }
05086 }
05087
05088 static int set_actual_txgain(int fd, float gain, float drc, int law)
05089 {
05090 struct dahdi_gains g;
05091 int res;
05092
05093 memset(&g, 0, sizeof(g));
05094 res = ioctl(fd, DAHDI_GETGAINS, &g);
05095 if (res) {
05096 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05097 return res;
05098 }
05099
05100 fill_txgain(&g, gain, drc, law);
05101
05102 return ioctl(fd, DAHDI_SETGAINS, &g);
05103 }
05104
05105 static int set_actual_rxgain(int fd, float gain, float drc, int law)
05106 {
05107 struct dahdi_gains g;
05108 int res;
05109
05110 memset(&g, 0, sizeof(g));
05111 res = ioctl(fd, DAHDI_GETGAINS, &g);
05112 if (res) {
05113 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
05114 return res;
05115 }
05116
05117 fill_rxgain(&g, gain, drc, law);
05118
05119 return ioctl(fd, DAHDI_SETGAINS, &g);
05120 }
05121
05122 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
05123 {
05124 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
05125 }
05126
05127 static int bump_gains(struct dahdi_pvt *p)
05128 {
05129 int res;
05130
05131
05132 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05133 if (res) {
05134 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
05135 return -1;
05136 }
05137
05138 return 0;
05139 }
05140
05141 static int restore_gains(struct dahdi_pvt *p)
05142 {
05143 int res;
05144
05145 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05146 if (res) {
05147 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05148 return -1;
05149 }
05150
05151 return 0;
05152 }
05153
05154 static inline int dahdi_set_hook(int fd, int hs)
05155 {
05156 int x, res;
05157
05158 x = hs;
05159 res = ioctl(fd, DAHDI_HOOK, &x);
05160
05161 if (res < 0) {
05162 if (errno == EINPROGRESS)
05163 return 0;
05164 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05165
05166 }
05167
05168 return res;
05169 }
05170
05171 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05172 {
05173 int x, res;
05174
05175 x = muted;
05176 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05177 switch (p->sig) {
05178 #if defined(HAVE_PRI)
05179 case SIG_PRI_LIB_HANDLE_CASES:
05180 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05181
05182 break;
05183 }
05184
05185 #endif
05186 #if defined(HAVE_SS7)
05187 case SIG_SS7:
05188 #endif
05189 {
05190 int y = 1;
05191
05192 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05193 if (res)
05194 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05195 p->channel, strerror(errno));
05196 }
05197 break;
05198 default:
05199 break;
05200 }
05201 #endif
05202 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05203 if (res < 0)
05204 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05205 return res;
05206 }
05207
05208 static int save_conference(struct dahdi_pvt *p)
05209 {
05210 struct dahdi_confinfo c;
05211 int res;
05212 if (p->saveconf.confmode) {
05213 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05214 return -1;
05215 }
05216 p->saveconf.chan = 0;
05217 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05218 if (res) {
05219 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05220 p->saveconf.confmode = 0;
05221 return -1;
05222 }
05223 memset(&c, 0, sizeof(c));
05224 c.confmode = DAHDI_CONF_NORMAL;
05225 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05226 if (res) {
05227 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05228 return -1;
05229 }
05230 ast_debug(1, "Disabled conferencing\n");
05231 return 0;
05232 }
05233
05234 static int restore_conference(struct dahdi_pvt *p)
05235 {
05236 int res;
05237 if (p->saveconf.confmode) {
05238 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05239 p->saveconf.confmode = 0;
05240 if (res) {
05241 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05242 return -1;
05243 }
05244 ast_debug(1, "Restored conferencing\n");
05245 }
05246 return 0;
05247 }
05248
05249 static int send_cwcidspill(struct dahdi_pvt *p)
05250 {
05251 p->callwaitcas = 0;
05252 p->cidcwexpire = 0;
05253 p->cid_suppress_expire = 0;
05254 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05255 return -1;
05256 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05257
05258 p->cidlen += READ_SIZE * 4;
05259 p->cidpos = 0;
05260 send_callerid(p);
05261 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05262 return 0;
05263 }
05264
05265 static int has_voicemail(struct dahdi_pvt *p)
05266 {
05267 int new_msgs;
05268 struct ast_event *event;
05269 char *mailbox, *context;
05270
05271 mailbox = context = ast_strdupa(p->mailbox);
05272 strsep(&context, "@");
05273 if (ast_strlen_zero(context))
05274 context = "default";
05275
05276 event = ast_event_get_cached(AST_EVENT_MWI,
05277 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05278 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05279 AST_EVENT_IE_END);
05280
05281 if (event) {
05282 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05283 ast_event_destroy(event);
05284 } else
05285 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05286
05287 return new_msgs;
05288 }
05289
05290
05291
05292 static int send_callerid(struct dahdi_pvt *p)
05293 {
05294
05295 int res;
05296
05297 if (p->subs[SUB_REAL].linear) {
05298 p->subs[SUB_REAL].linear = 0;
05299 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05300 }
05301 while (p->cidpos < p->cidlen) {
05302 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05303 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05304 if (res < 0) {
05305 if (errno == EAGAIN)
05306 return 0;
05307 else {
05308 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05309 return -1;
05310 }
05311 }
05312 if (!res)
05313 return 0;
05314 p->cidpos += res;
05315 }
05316 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05317 ast_free(p->cidspill);
05318 p->cidspill = NULL;
05319 if (p->callwaitcas) {
05320
05321 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05322 p->cid_suppress_expire = p->cidcwexpire;
05323 } else
05324 restore_conference(p);
05325 return 0;
05326 }
05327
05328 static int dahdi_callwait(struct ast_channel *ast)
05329 {
05330 struct dahdi_pvt *p = ast->tech_pvt;
05331 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05332 if (p->cidspill) {
05333 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05334 ast_free(p->cidspill);
05335 }
05336
05337
05338
05339
05340
05341 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05342 return -1;
05343 save_conference(p);
05344
05345 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05346 if (!p->callwaitrings && p->callwaitingcallerid) {
05347 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05348 p->callwaitcas = 1;
05349 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05350 } else {
05351 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05352 p->callwaitcas = 0;
05353 p->cidlen = 2400 + READ_SIZE * 4;
05354 }
05355 p->cidpos = 0;
05356 send_callerid(p);
05357
05358 return 0;
05359 }
05360
05361 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05362 {
05363 struct dahdi_pvt *p = ast->tech_pvt;
05364 int x, res, mysig;
05365 char dest[256];
05366
05367 ast_mutex_lock(&p->lock);
05368 ast_copy_string(dest, rdest, sizeof(dest));
05369 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05370 if ((ast->_state == AST_STATE_BUSY)) {
05371 p->subs[SUB_REAL].needbusy = 1;
05372 ast_mutex_unlock(&p->lock);
05373 return 0;
05374 }
05375 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05376 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05377 ast_mutex_unlock(&p->lock);
05378 return -1;
05379 }
05380 p->waitingfordt.tv_sec = 0;
05381 p->dialednone = 0;
05382 if ((p->radio || (p->oprmode < 0)))
05383 {
05384
05385 ast_setstate(ast, AST_STATE_UP);
05386 ast_mutex_unlock(&p->lock);
05387 return 0;
05388 }
05389 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05390 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05391 if (res)
05392 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05393 p->outgoing = 1;
05394
05395 if (IS_DIGITAL(ast->transfercapability)){
05396 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05397 } else {
05398 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05399 }
05400
05401 #ifdef HAVE_PRI
05402 if (dahdi_sig_pri_lib_handles(p->sig)) {
05403 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05404 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05405 ast_mutex_unlock(&p->lock);
05406 return res;
05407 }
05408 #endif
05409
05410 #if defined(HAVE_SS7)
05411 if (p->sig == SIG_SS7) {
05412 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05413 ast_mutex_unlock(&p->lock);
05414 return res;
05415 }
05416 #endif
05417
05418
05419 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05420 p->callwaitrings = 0;
05421 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05422 ast_mutex_unlock(&p->lock);
05423 return res;
05424 }
05425
05426 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05427 switch (mysig) {
05428 case 0:
05429
05430 ast_setstate(ast, AST_STATE_UP);
05431 break;
05432 case SIG_MFCR2:
05433 break;
05434 default:
05435 ast_debug(1, "not yet implemented\n");
05436 ast_mutex_unlock(&p->lock);
05437 return -1;
05438 }
05439
05440 #ifdef HAVE_OPENR2
05441 if (p->mfcr2) {
05442 openr2_calling_party_category_t chancat;
05443 int callres = 0;
05444 char *c, *l;
05445
05446
05447 p->dialdest[0] = '\0';
05448
05449 c = strchr(dest, '/');
05450 if (c) {
05451 c++;
05452 } else {
05453 c = "";
05454 }
05455 if (!p->hidecallerid) {
05456 l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
05457 } else {
05458 l = NULL;
05459 }
05460 if (strlen(c) < p->stripmsd) {
05461 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05462 ast_mutex_unlock(&p->lock);
05463 return -1;
05464 }
05465 p->dialing = 1;
05466 chancat = dahdi_r2_get_channel_category(ast);
05467 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05468 if (-1 == callres) {
05469 ast_mutex_unlock(&p->lock);
05470 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05471 return -1;
05472 }
05473 p->mfcr2_call_accepted = 0;
05474 p->mfcr2_progress = 0;
05475 ast_setstate(ast, AST_STATE_DIALING);
05476 }
05477 #endif
05478 ast_mutex_unlock(&p->lock);
05479 return 0;
05480 }
05481
05482
05483
05484
05485
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05498 {
05499 struct dahdi_pvt *cur;
05500
05501 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05502
05503
05504 for (cur = iflist; cur; cur = cur->next) {
05505 if (pvt->channel < cur->channel) {
05506
05507 pvt->prev = cur->prev;
05508 pvt->next = cur;
05509 if (cur->prev) {
05510
05511 cur->prev->next = pvt;
05512 } else {
05513
05514 iflist = pvt;
05515 }
05516 cur->prev = pvt;
05517 return;
05518 }
05519 }
05520
05521
05522 pvt->prev = ifend;
05523 pvt->next = NULL;
05524 if (ifend) {
05525 ifend->next = pvt;
05526 }
05527 ifend = pvt;
05528 if (!iflist) {
05529
05530 iflist = pvt;
05531 }
05532 }
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05548 {
05549
05550 if (pvt->prev) {
05551 pvt->prev->next = pvt->next;
05552 } else if (iflist == pvt) {
05553
05554 iflist = pvt->next;
05555 }
05556
05557
05558 if (pvt->next) {
05559 pvt->next->prev = pvt->prev;
05560 } else if (ifend == pvt) {
05561
05562 ifend = pvt->prev;
05563 }
05564
05565
05566 pvt->which_iflist = DAHDI_IFLIST_NONE;
05567 pvt->prev = NULL;
05568 pvt->next = NULL;
05569 }
05570
05571 #if defined(HAVE_PRI)
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05589 {
05590 struct dahdi_pvt *cur;
05591
05592 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05593
05594
05595 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05596 if (pvt->channel < cur->channel) {
05597
05598 pvt->prev = cur->prev;
05599 pvt->next = cur;
05600 if (cur->prev) {
05601
05602 cur->prev->next = pvt;
05603 } else {
05604
05605 pri->no_b_chan_iflist = pvt;
05606 }
05607 cur->prev = pvt;
05608 return;
05609 }
05610 }
05611
05612
05613 pvt->prev = pri->no_b_chan_end;
05614 pvt->next = NULL;
05615 if (pri->no_b_chan_end) {
05616 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05617 }
05618 pri->no_b_chan_end = pvt;
05619 if (!pri->no_b_chan_iflist) {
05620
05621 pri->no_b_chan_iflist = pvt;
05622 }
05623 }
05624 #endif
05625
05626 #if defined(HAVE_PRI)
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05642 {
05643
05644 if (pvt->prev) {
05645 pvt->prev->next = pvt->next;
05646 } else if (pri->no_b_chan_iflist == pvt) {
05647
05648 pri->no_b_chan_iflist = pvt->next;
05649 }
05650
05651
05652 if (pvt->next) {
05653 pvt->next->prev = pvt->prev;
05654 } else if (pri->no_b_chan_end == pvt) {
05655
05656 pri->no_b_chan_end = pvt->prev;
05657 }
05658
05659
05660 pvt->which_iflist = DAHDI_IFLIST_NONE;
05661 pvt->prev = NULL;
05662 pvt->next = NULL;
05663 }
05664 #endif
05665
05666 #if defined(HAVE_PRI)
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05677 {
05678 unsigned idx;
05679 struct sig_pri_span *pri;
05680
05681 pri = pvt->pri;
05682 if (!pri) {
05683
05684 return;
05685 }
05686 ast_mutex_lock(&pri->lock);
05687 for (idx = 0; idx < pri->numchans; ++idx) {
05688 if (pri->pvts[idx] == pvt->sig_pvt) {
05689 pri->pvts[idx] = NULL;
05690 ast_mutex_unlock(&pri->lock);
05691 return;
05692 }
05693 }
05694 ast_mutex_unlock(&pri->lock);
05695 }
05696 #endif
05697
05698 #if defined(HAVE_SS7)
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05709 {
05710 unsigned idx;
05711 struct sig_ss7_linkset *ss7;
05712
05713 ss7 = pvt->ss7;
05714 if (!ss7) {
05715
05716 return;
05717 }
05718 ast_mutex_lock(&ss7->lock);
05719 for (idx = 0; idx < ss7->numchans; ++idx) {
05720 if (ss7->pvts[idx] == pvt->sig_pvt) {
05721 ss7->pvts[idx] = NULL;
05722 ast_mutex_unlock(&ss7->lock);
05723 return;
05724 }
05725 }
05726 ast_mutex_unlock(&ss7->lock);
05727 }
05728 #endif
05729
05730 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05731 {
05732 if (cur->next && cur->next->span == cur->span) {
05733 return cur->next;
05734 } else if (cur->prev && cur->prev->span == cur->span) {
05735 return cur->prev;
05736 }
05737
05738 return NULL;
05739 }
05740
05741 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05742 {
05743 struct dahdi_pvt *p = pvt;
05744
05745 if (p->manages_span_alarms) {
05746 struct dahdi_pvt *next = find_next_iface_in_span(p);
05747 if (next) {
05748 next->manages_span_alarms = 1;
05749 }
05750 }
05751
05752
05753 #if defined(HAVE_PRI)
05754 dahdi_unlink_pri_pvt(p);
05755 #endif
05756 #if defined(HAVE_SS7)
05757 dahdi_unlink_ss7_pvt(p);
05758 #endif
05759 switch (pvt->which_iflist) {
05760 case DAHDI_IFLIST_NONE:
05761 break;
05762 case DAHDI_IFLIST_MAIN:
05763 dahdi_iflist_extract(p);
05764 break;
05765 #if defined(HAVE_PRI)
05766 case DAHDI_IFLIST_NO_B_CHAN:
05767 if (p->pri) {
05768 dahdi_nobch_extract(p->pri, p);
05769 }
05770 break;
05771 #endif
05772 }
05773
05774 if (p->sig_pvt) {
05775 if (analog_lib_handles(p->sig, 0, 0)) {
05776 analog_delete(p->sig_pvt);
05777 }
05778 switch (p->sig) {
05779 #if defined(HAVE_PRI)
05780 case SIG_PRI_LIB_HANDLE_CASES:
05781 sig_pri_chan_delete(p->sig_pvt);
05782 break;
05783 #endif
05784 #if defined(HAVE_SS7)
05785 case SIG_SS7:
05786 sig_ss7_chan_delete(p->sig_pvt);
05787 break;
05788 #endif
05789 default:
05790 break;
05791 }
05792 }
05793 ast_free(p->cidspill);
05794 if (p->use_smdi)
05795 ast_smdi_interface_unref(p->smdi_iface);
05796 if (p->mwi_event_sub)
05797 ast_event_unsubscribe(p->mwi_event_sub);
05798 if (p->vars) {
05799 ast_variables_destroy(p->vars);
05800 }
05801 if (p->cc_params) {
05802 ast_cc_config_params_destroy(p->cc_params);
05803 }
05804 ast_mutex_destroy(&p->lock);
05805 dahdi_close_sub(p, SUB_REAL);
05806 if (p->owner)
05807 p->owner->tech_pvt = NULL;
05808 ast_free(p);
05809 }
05810
05811 static void destroy_channel(struct dahdi_pvt *cur, int now)
05812 {
05813 int i;
05814
05815 if (!now) {
05816
05817 if (cur->owner) {
05818 return;
05819 }
05820 for (i = 0; i < 3; i++) {
05821 if (cur->subs[i].owner) {
05822 return;
05823 }
05824 }
05825 }
05826 destroy_dahdi_pvt(cur);
05827 }
05828
05829 static void destroy_all_channels(void)
05830 {
05831 int chan;
05832 #if defined(HAVE_PRI)
05833 unsigned span;
05834 struct sig_pri_span *pri;
05835 #endif
05836 struct dahdi_pvt *p;
05837
05838 while (num_restart_pending) {
05839 usleep(1);
05840 }
05841
05842 ast_mutex_lock(&iflock);
05843
05844 while (iflist) {
05845 p = iflist;
05846
05847 chan = p->channel;
05848 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05849 {
05850 char db_chan_name[20];
05851 char db_answer[5];
05852 char state;
05853 int why = -1;
05854
05855 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05856 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05857 sscanf(db_answer, "%1c:%30d", &state, &why);
05858 }
05859 if (!why) {
05860
05861 ast_db_del(db_chan_name, SRVST_DBKEY);
05862 }
05863 }
05864 #endif
05865
05866 destroy_dahdi_pvt(p);
05867 ast_verb(3, "Unregistered channel %d\n", chan);
05868 }
05869 ifcount = 0;
05870 ast_mutex_unlock(&iflock);
05871
05872 #if defined(HAVE_PRI)
05873
05874 for (span = 0; span < NUM_SPANS; ++span) {
05875 if (!pris[span].dchannels[0]) {
05876 break;
05877 }
05878 pri = &pris[span].pri;
05879 ast_mutex_lock(&pri->lock);
05880 while (pri->no_b_chan_iflist) {
05881 p = pri->no_b_chan_iflist;
05882
05883
05884 destroy_dahdi_pvt(p);
05885 }
05886 ast_mutex_unlock(&pri->lock);
05887 }
05888 #endif
05889 }
05890
05891 #if defined(HAVE_PRI)
05892 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05893
05894 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05895 {
05896
05897 struct dahdi_pvt *p;
05898
05899 if (ast_strlen_zero(digits)) {
05900 ast_debug(1, "No digit string sent to application!\n");
05901 return -1;
05902 }
05903
05904 p = (struct dahdi_pvt *)chan->tech_pvt;
05905
05906 if (!p) {
05907 ast_debug(1, "Unable to find technology private\n");
05908 return -1;
05909 }
05910
05911 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05912
05913 return 0;
05914 }
05915 #endif
05916
05917 #if defined(HAVE_PRI)
05918 #if defined(HAVE_PRI_PROG_W_CAUSE)
05919 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05920
05921 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05922 {
05923
05924 struct dahdi_pvt *pvt;
05925 char *parse;
05926 int res;
05927 AST_DECLARE_APP_ARGS(args,
05928 AST_APP_ARG(destination);
05929 AST_APP_ARG(original);
05930 AST_APP_ARG(reason);
05931 );
05932
05933 if (ast_strlen_zero(data)) {
05934 ast_log(LOG_DEBUG, "No data sent to application!\n");
05935 return -1;
05936 }
05937 if (chan->tech != &dahdi_tech) {
05938 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05939 return -1;
05940 }
05941 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05942 if (!pvt) {
05943 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05944 return -1;
05945 }
05946 switch (pvt->sig) {
05947 case SIG_PRI_LIB_HANDLE_CASES:
05948 break;
05949 default:
05950 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05951 chan->name);
05952 return -1;
05953 }
05954
05955 parse = ast_strdupa(data);
05956 AST_STANDARD_APP_ARGS(args, parse);
05957
05958 if (ast_strlen_zero(args.destination)) {
05959 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05960 return -1;
05961 }
05962
05963 if (ast_strlen_zero(args.original)) {
05964 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05965 args.original = NULL;
05966 }
05967
05968 if (ast_strlen_zero(args.reason)) {
05969 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05970 args.reason = NULL;
05971 }
05972
05973 res = pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state,
05974 args.destination, args.original, args.reason);
05975 if (!res) {
05976
05977
05978
05979
05980 ast_safe_sleep(chan, 5000);
05981 }
05982
05983 return -1;
05984 }
05985 #endif
05986 #endif
05987
05988 #if defined(HAVE_OPENR2)
05989 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05990
05991 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05992 {
05993
05994 openr2_call_mode_t accept_mode;
05995 int res, timeout, maxloops;
05996 struct ast_frame *f;
05997 struct dahdi_pvt *p;
05998 char *parse;
05999 AST_DECLARE_APP_ARGS(args,
06000 AST_APP_ARG(charge);
06001 );
06002
06003 if (ast_strlen_zero(data)) {
06004 ast_log(LOG_DEBUG, "No data sent to application!\n");
06005 return -1;
06006 }
06007
06008 if (chan->tech != &dahdi_tech) {
06009 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
06010 return -1;
06011 }
06012
06013 p = (struct dahdi_pvt *)chan->tech_pvt;
06014 if (!p) {
06015 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
06016 return -1;
06017 }
06018
06019 parse = ast_strdupa(data);
06020 AST_STANDARD_APP_ARGS(args, parse);
06021
06022 if (ast_strlen_zero(args.charge)) {
06023 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
06024 return -1;
06025 }
06026
06027 ast_mutex_lock(&p->lock);
06028 if (!p->mfcr2 || !p->mfcr2call) {
06029 ast_mutex_unlock(&p->lock);
06030 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
06031 return -1;
06032 }
06033
06034 if (p->mfcr2_call_accepted) {
06035 ast_mutex_unlock(&p->lock);
06036 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
06037 return 0;
06038 }
06039 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
06040 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
06041 ast_mutex_unlock(&p->lock);
06042 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06043 return -1;
06044 }
06045 ast_mutex_unlock(&p->lock);
06046
06047 res = 0;
06048 timeout = 100;
06049 maxloops = 50;
06050
06051 while (maxloops > 0) {
06052 maxloops--;
06053 if (ast_check_hangup(chan)) {
06054 break;
06055 }
06056 res = ast_waitfor(chan, timeout);
06057 if (res < 0) {
06058 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
06059 res = -1;
06060 break;
06061 }
06062 if (res == 0) {
06063 continue;
06064 }
06065 f = ast_read(chan);
06066 if (!f) {
06067 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
06068 res = -1;
06069 break;
06070 }
06071 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
06072 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
06073 ast_frfree(f);
06074 res = -1;
06075 break;
06076 }
06077 ast_frfree(f);
06078 ast_mutex_lock(&p->lock);
06079 if (p->mfcr2_call_accepted) {
06080 ast_mutex_unlock(&p->lock);
06081 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
06082 break;
06083 }
06084 ast_mutex_unlock(&p->lock);
06085 }
06086 if (res == -1) {
06087 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
06088 }
06089 return res;
06090 }
06091
06092 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
06093 {
06094 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
06095 switch (cause) {
06096 case AST_CAUSE_USER_BUSY:
06097 case AST_CAUSE_CALL_REJECTED:
06098 case AST_CAUSE_INTERWORKING:
06099 r2cause = OR2_CAUSE_BUSY_NUMBER;
06100 break;
06101
06102 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06103 case AST_CAUSE_SWITCH_CONGESTION:
06104 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
06105 break;
06106
06107 case AST_CAUSE_UNALLOCATED:
06108 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
06109 break;
06110
06111 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
06112 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
06113 r2cause = OR2_CAUSE_OUT_OF_ORDER;
06114 break;
06115
06116 case AST_CAUSE_NO_ANSWER:
06117 case AST_CAUSE_NO_USER_RESPONSE:
06118 r2cause = OR2_CAUSE_NO_ANSWER;
06119 break;
06120
06121 default:
06122 r2cause = OR2_CAUSE_NORMAL_CLEARING;
06123 break;
06124 }
06125 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
06126 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
06127 return r2cause;
06128 }
06129 #endif
06130
06131 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
06132 {
06133 if (p->bufferoverrideinuse) {
06134
06135 struct dahdi_bufferinfo bi = {
06136 .txbufpolicy = p->buf_policy,
06137 .rxbufpolicy = p->buf_policy,
06138 .bufsize = p->bufsize,
06139 .numbufs = p->buf_no
06140 };
06141 int bpres;
06142
06143 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06144 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
06145 }
06146 p->bufferoverrideinuse = 0;
06147 return bpres;
06148 }
06149
06150 return -1;
06151 }
06152
06153 static int dahdi_hangup(struct ast_channel *ast)
06154 {
06155 int res = 0;
06156 int idx,x;
06157 int law;
06158
06159 struct dahdi_pvt *p = ast->tech_pvt;
06160 struct dahdi_params par;
06161
06162 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06163 if (!ast->tech_pvt) {
06164 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06165 return 0;
06166 }
06167
06168 ast_mutex_lock(&p->lock);
06169 p->exten[0] = '\0';
06170 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06171 dahdi_confmute(p, 0);
06172 restore_gains(p);
06173 p->ignoredtmf = 0;
06174 p->waitingfordt.tv_sec = 0;
06175
06176 res = analog_hangup(p->sig_pvt, ast);
06177 revert_fax_buffers(p, ast);
06178
06179 goto hangup_out;
06180 } else {
06181 p->cid_num[0] = '\0';
06182 p->cid_name[0] = '\0';
06183 p->cid_subaddr[0] = '\0';
06184 }
06185
06186 #if defined(HAVE_PRI)
06187 if (dahdi_sig_pri_lib_handles(p->sig)) {
06188 x = 1;
06189 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06190
06191 dahdi_confmute(p, 0);
06192 p->muting = 0;
06193 restore_gains(p);
06194 if (p->dsp) {
06195 ast_dsp_free(p->dsp);
06196 p->dsp = NULL;
06197 }
06198 p->ignoredtmf = 0;
06199
06200
06201 p->subs[SUB_REAL].owner = NULL;
06202 p->subs[SUB_REAL].needbusy = 0;
06203 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06204
06205 p->owner = NULL;
06206 p->cid_tag[0] = '\0';
06207 p->ringt = 0;
06208 p->distinctivering = 0;
06209 p->confirmanswer = 0;
06210 p->outgoing = 0;
06211 p->digital = 0;
06212 p->faxhandled = 0;
06213 p->pulsedial = 0;
06214
06215 revert_fax_buffers(p, ast);
06216
06217 p->law = p->law_default;
06218 law = p->law_default;
06219 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06220 if (res < 0) {
06221 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06222 p->channel, strerror(errno));
06223 }
06224
06225 sig_pri_hangup(p->sig_pvt, ast);
06226
06227 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06228 dahdi_disable_ec(p);
06229
06230 x = 0;
06231 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06232 p->didtdd = 0;
06233
06234 p->rdnis[0] = '\0';
06235 update_conf(p);
06236 reset_conf(p);
06237
06238
06239 x = 0;
06240 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06241
06242 if (num_restart_pending == 0) {
06243 restart_monitor();
06244 }
06245 goto hangup_out;
06246 }
06247 #endif
06248
06249 #if defined(HAVE_SS7)
06250 if (p->sig == SIG_SS7) {
06251 x = 1;
06252 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06253
06254 dahdi_confmute(p, 0);
06255 p->muting = 0;
06256 restore_gains(p);
06257 if (p->dsp) {
06258 ast_dsp_free(p->dsp);
06259 p->dsp = NULL;
06260 }
06261 p->ignoredtmf = 0;
06262
06263
06264 p->subs[SUB_REAL].owner = NULL;
06265 p->subs[SUB_REAL].needbusy = 0;
06266 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06267
06268 p->owner = NULL;
06269 p->ringt = 0;
06270 p->distinctivering = 0;
06271 p->confirmanswer = 0;
06272 p->outgoing = 0;
06273 p->digital = 0;
06274 p->faxhandled = 0;
06275 p->pulsedial = 0;
06276
06277 revert_fax_buffers(p, ast);
06278
06279 p->law = p->law_default;
06280 law = p->law_default;
06281 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06282 if (res < 0) {
06283 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n",
06284 p->channel, strerror(errno));
06285 }
06286
06287 sig_ss7_hangup(p->sig_pvt, ast);
06288
06289 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06290 dahdi_disable_ec(p);
06291
06292 x = 0;
06293 ast_channel_setoption(ast, AST_OPTION_TDD, &x, sizeof(char), 0);
06294 p->didtdd = 0;
06295
06296 update_conf(p);
06297 reset_conf(p);
06298
06299
06300 x = 0;
06301 ast_channel_setoption(ast, AST_OPTION_AUDIO_MODE, &x, sizeof(char), 0);
06302
06303 if (num_restart_pending == 0) {
06304 restart_monitor();
06305 }
06306 goto hangup_out;
06307 }
06308 #endif
06309
06310 idx = dahdi_get_index(ast, p, 1);
06311
06312 dahdi_confmute(p, 0);
06313 p->muting = 0;
06314 restore_gains(p);
06315 if (p->origcid_num) {
06316 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06317 ast_free(p->origcid_num);
06318 p->origcid_num = NULL;
06319 }
06320 if (p->origcid_name) {
06321 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06322 ast_free(p->origcid_name);
06323 p->origcid_name = NULL;
06324 }
06325 if (p->dsp)
06326 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06327
06328 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06329 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06330 p->ignoredtmf = 0;
06331
06332 if (idx > -1) {
06333
06334 p->subs[idx].owner = NULL;
06335 p->subs[idx].needanswer = 0;
06336 p->subs[idx].needflash = 0;
06337 p->subs[idx].needringing = 0;
06338 p->subs[idx].needbusy = 0;
06339 p->subs[idx].needcongestion = 0;
06340 p->subs[idx].linear = 0;
06341 p->polarity = POLARITY_IDLE;
06342 dahdi_setlinear(p->subs[idx].dfd, 0);
06343 if (idx == SUB_REAL) {
06344 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06345 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06346 if (p->subs[SUB_CALLWAIT].inthreeway) {
06347
06348 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06349
06350 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06351 unalloc_sub(p, SUB_CALLWAIT);
06352 p->owner = NULL;
06353 } else {
06354
06355 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06356 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06357 unalloc_sub(p, SUB_THREEWAY);
06358 if (p->subs[SUB_REAL].inthreeway) {
06359
06360
06361 ast_debug(1, "Call was complete, setting owner to former third call\n");
06362 p->owner = p->subs[SUB_REAL].owner;
06363 } else {
06364
06365 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06366 p->owner = NULL;
06367 }
06368 p->subs[SUB_REAL].inthreeway = 0;
06369 }
06370 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06371
06372 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06373 unalloc_sub(p, SUB_CALLWAIT);
06374 p->owner = p->subs[SUB_REAL].owner;
06375 if (p->owner->_state != AST_STATE_UP)
06376 p->subs[SUB_REAL].needanswer = 1;
06377 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06378 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06379 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06380 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06381 unalloc_sub(p, SUB_THREEWAY);
06382 if (p->subs[SUB_REAL].inthreeway) {
06383
06384
06385 ast_debug(1, "Call was complete, setting owner to former third call\n");
06386 p->owner = p->subs[SUB_REAL].owner;
06387 } else {
06388
06389 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06390 p->owner = NULL;
06391 }
06392 p->subs[SUB_REAL].inthreeway = 0;
06393 }
06394 } else if (idx == SUB_CALLWAIT) {
06395
06396 if (p->subs[SUB_CALLWAIT].inthreeway) {
06397
06398
06399 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06400 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06401 S_OR(p->mohsuggest, NULL),
06402 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06403 }
06404 p->subs[SUB_THREEWAY].inthreeway = 0;
06405
06406 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06407 unalloc_sub(p, SUB_THREEWAY);
06408 } else
06409 unalloc_sub(p, SUB_CALLWAIT);
06410 } else if (idx == SUB_THREEWAY) {
06411 if (p->subs[SUB_CALLWAIT].inthreeway) {
06412
06413
06414 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06415 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06416 S_OR(p->mohsuggest, NULL),
06417 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06418 }
06419 p->subs[SUB_CALLWAIT].inthreeway = 0;
06420 }
06421 p->subs[SUB_REAL].inthreeway = 0;
06422
06423
06424 unalloc_sub(p, SUB_THREEWAY);
06425 } else {
06426
06427 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06428 }
06429 }
06430
06431 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06432 p->owner = NULL;
06433 p->ringt = 0;
06434 p->distinctivering = 0;
06435 p->confirmanswer = 0;
06436 p->outgoing = 0;
06437 p->digital = 0;
06438 p->faxhandled = 0;
06439 p->pulsedial = 0;
06440 if (p->dsp) {
06441 ast_dsp_free(p->dsp);
06442 p->dsp = NULL;
06443 }
06444
06445 revert_fax_buffers(p, ast);
06446
06447 p->law = p->law_default;
06448 law = p->law_default;
06449 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06450 if (res < 0)
06451 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06452
06453 #ifdef HAVE_OPENR2
06454 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06455 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06456
06457 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06458 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06459 } else {
06460 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06461 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06462 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06463 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06464 dahdi_r2_disconnect_call(p, r2cause);
06465 }
06466 } else if (p->mfcr2call) {
06467 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06468
06469
06470
06471
06472 p->mfcr2call = 0;
06473 }
06474 #endif
06475 switch (p->sig) {
06476 case SIG_SS7:
06477 case SIG_MFCR2:
06478 case SIG_PRI_LIB_HANDLE_CASES:
06479 case 0:
06480 break;
06481 default:
06482 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06483 break;
06484 }
06485 if (res < 0) {
06486 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06487 }
06488 switch (p->sig) {
06489 case SIG_FXOGS:
06490 case SIG_FXOLS:
06491 case SIG_FXOKS:
06492 memset(&par, 0, sizeof(par));
06493 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06494 if (!res) {
06495 struct analog_pvt *analog_p = p->sig_pvt;
06496 #if 0
06497 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06498 #endif
06499
06500 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06501 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06502 else
06503 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06504 analog_p->fxsoffhookstate = par.rxisoffhook;
06505 }
06506 break;
06507 case SIG_FXSGS:
06508 case SIG_FXSLS:
06509 case SIG_FXSKS:
06510
06511
06512 if (ast->_state != AST_STATE_RESERVED) {
06513 time(&p->guardtime);
06514 p->guardtime += 2;
06515 }
06516 break;
06517 default:
06518 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06519 break;
06520 }
06521 if (p->sig)
06522 dahdi_disable_ec(p);
06523 x = 0;
06524 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06525 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06526 p->didtdd = 0;
06527 p->callwaitcas = 0;
06528 p->callwaiting = p->permcallwaiting;
06529 p->hidecallerid = p->permhidecallerid;
06530 p->waitingfordt.tv_sec = 0;
06531 p->dialing = 0;
06532 p->rdnis[0] = '\0';
06533 update_conf(p);
06534 reset_conf(p);
06535
06536 switch (p->sig) {
06537 case SIG_PRI_LIB_HANDLE_CASES:
06538 case SIG_SS7:
06539 x = 0;
06540 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06541 break;
06542 default:
06543 break;
06544 }
06545 if (num_restart_pending == 0)
06546 restart_monitor();
06547 }
06548
06549 p->callwaitingrepeat = 0;
06550 p->cidcwexpire = 0;
06551 p->cid_suppress_expire = 0;
06552 p->oprmode = 0;
06553 hangup_out:
06554 ast->tech_pvt = NULL;
06555 ast_free(p->cidspill);
06556 p->cidspill = NULL;
06557
06558 ast_mutex_unlock(&p->lock);
06559 ast_verb(3, "Hungup '%s'\n", ast->name);
06560
06561 ast_mutex_lock(&iflock);
06562 if (p->restartpending) {
06563 num_restart_pending--;
06564 }
06565
06566 if (p->destroy) {
06567 destroy_channel(p, 0);
06568 }
06569 ast_mutex_unlock(&iflock);
06570
06571 ast_module_unref(ast_module_info->self);
06572 return 0;
06573 }
06574
06575 static int dahdi_answer(struct ast_channel *ast)
06576 {
06577 struct dahdi_pvt *p = ast->tech_pvt;
06578 int res = 0;
06579 int idx;
06580 ast_setstate(ast, AST_STATE_UP);
06581 ast_mutex_lock(&p->lock);
06582 idx = dahdi_get_index(ast, p, 0);
06583 if (idx < 0)
06584 idx = SUB_REAL;
06585
06586 if ((p->radio || (p->oprmode < 0))) {
06587 ast_mutex_unlock(&p->lock);
06588 return 0;
06589 }
06590
06591 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06592 res = analog_answer(p->sig_pvt, ast);
06593 ast_mutex_unlock(&p->lock);
06594 return res;
06595 }
06596
06597 switch (p->sig) {
06598 #if defined(HAVE_PRI)
06599 case SIG_PRI_LIB_HANDLE_CASES:
06600 res = sig_pri_answer(p->sig_pvt, ast);
06601 break;
06602 #endif
06603 #if defined(HAVE_SS7)
06604 case SIG_SS7:
06605 res = sig_ss7_answer(p->sig_pvt, ast);
06606 break;
06607 #endif
06608 #ifdef HAVE_OPENR2
06609 case SIG_MFCR2:
06610 if (!p->mfcr2_call_accepted) {
06611
06612
06613 p->mfcr2_answer_pending = 1;
06614 if (p->mfcr2_charge_calls) {
06615 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06616 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06617 } else {
06618 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06619 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06620 }
06621 } else {
06622 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06623 dahdi_r2_answer(p);
06624 }
06625 break;
06626 #endif
06627 case 0:
06628 ast_mutex_unlock(&p->lock);
06629 return 0;
06630 default:
06631 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06632 res = -1;
06633 break;
06634 }
06635 ast_mutex_unlock(&p->lock);
06636 return res;
06637 }
06638
06639 static void disable_dtmf_detect(struct dahdi_pvt *p)
06640 {
06641 int val = 0;
06642
06643 p->ignoredtmf = 1;
06644
06645 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06646
06647 if (!p->hardwaredtmf && p->dsp) {
06648 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06649 ast_dsp_set_features(p->dsp, p->dsp_features);
06650 }
06651 }
06652
06653 static void enable_dtmf_detect(struct dahdi_pvt *p)
06654 {
06655 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06656
06657 if (p->channel == CHAN_PSEUDO)
06658 return;
06659
06660 p->ignoredtmf = 0;
06661
06662 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06663
06664 if (!p->hardwaredtmf && p->dsp) {
06665 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06666 ast_dsp_set_features(p->dsp, p->dsp_features);
06667 }
06668 }
06669
06670 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06671 {
06672 char *cp;
06673 struct dahdi_pvt *p = chan->tech_pvt;
06674
06675
06676 if (!p || !data || (*datalen < 1)) {
06677 errno = EINVAL;
06678 return -1;
06679 }
06680
06681 switch (option) {
06682 case AST_OPTION_DIGIT_DETECT:
06683 cp = (char *) data;
06684 *cp = p->ignoredtmf ? 0 : 1;
06685 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06686 break;
06687 case AST_OPTION_FAX_DETECT:
06688 cp = (char *) data;
06689 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06690 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06691 break;
06692 case AST_OPTION_CC_AGENT_TYPE:
06693 #if defined(HAVE_PRI)
06694 #if defined(HAVE_PRI_CCSS)
06695 if (dahdi_sig_pri_lib_handles(p->sig)) {
06696 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06697 break;
06698 }
06699 #endif
06700 #endif
06701 return -1;
06702 default:
06703 return -1;
06704 }
06705
06706 errno = 0;
06707
06708 return 0;
06709 }
06710
06711 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06712 {
06713 char *cp;
06714 signed char *scp;
06715 int x;
06716 int idx;
06717 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06718 struct oprmode *oprmode;
06719
06720
06721
06722 if (!p || !data || (datalen < 1)) {
06723 errno = EINVAL;
06724 return -1;
06725 }
06726
06727 switch (option) {
06728 case AST_OPTION_TXGAIN:
06729 scp = (signed char *) data;
06730 idx = dahdi_get_index(chan, p, 0);
06731 if (idx < 0) {
06732 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06733 return -1;
06734 }
06735 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06736 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06737 case AST_OPTION_RXGAIN:
06738 scp = (signed char *) data;
06739 idx = dahdi_get_index(chan, p, 0);
06740 if (idx < 0) {
06741 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06742 return -1;
06743 }
06744 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06745 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06746 case AST_OPTION_TONE_VERIFY:
06747 if (!p->dsp)
06748 break;
06749 cp = (char *) data;
06750 switch (*cp) {
06751 case 1:
06752 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06753 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06754 break;
06755 case 2:
06756 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06757 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06758 break;
06759 default:
06760 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06761 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06762 break;
06763 }
06764 break;
06765 case AST_OPTION_TDD:
06766
06767 cp = (char *) data;
06768 p->mate = 0;
06769 if (!*cp) {
06770 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06771 if (p->tdd)
06772 tdd_free(p->tdd);
06773 p->tdd = 0;
06774 break;
06775 }
06776 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06777 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06778 dahdi_disable_ec(p);
06779
06780 if (!p->didtdd) {
06781 unsigned char mybuf[41000];
06782 unsigned char *buf;
06783 int size, res, fd, len;
06784 struct pollfd fds[1];
06785
06786 buf = mybuf;
06787 memset(buf, 0x7f, sizeof(mybuf));
06788 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06789 len = 40000;
06790 idx = dahdi_get_index(chan, p, 0);
06791 if (idx < 0) {
06792 ast_log(LOG_WARNING, "No index in TDD?\n");
06793 return -1;
06794 }
06795 fd = p->subs[idx].dfd;
06796 while (len) {
06797 if (ast_check_hangup(chan))
06798 return -1;
06799 size = len;
06800 if (size > READ_SIZE)
06801 size = READ_SIZE;
06802 fds[0].fd = fd;
06803 fds[0].events = POLLPRI | POLLOUT;
06804 fds[0].revents = 0;
06805 res = poll(fds, 1, -1);
06806 if (!res) {
06807 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06808 continue;
06809 }
06810
06811 if (fds[0].revents & POLLPRI)
06812 return -1;
06813 if (!(fds[0].revents & POLLOUT)) {
06814 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06815 continue;
06816 }
06817 res = write(fd, buf, size);
06818 if (res != size) {
06819 if (res == -1) return -1;
06820 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06821 break;
06822 }
06823 len -= size;
06824 buf += size;
06825 }
06826 p->didtdd = 1;
06827 }
06828 if (*cp == 2) {
06829 if (p->tdd)
06830 tdd_free(p->tdd);
06831 p->tdd = 0;
06832 p->mate = 1;
06833 break;
06834 }
06835 if (!p->tdd) {
06836 p->tdd = tdd_new();
06837 }
06838 break;
06839 case AST_OPTION_RELAXDTMF:
06840 if (!p->dsp)
06841 break;
06842 cp = (char *) data;
06843 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06844 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06845 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06846 break;
06847 case AST_OPTION_AUDIO_MODE:
06848 #if defined(HAVE_PRI)
06849 if (dahdi_sig_pri_lib_handles(p->sig)
06850 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06851
06852 break;
06853 }
06854 #endif
06855
06856 cp = (char *) data;
06857 if (!*cp) {
06858 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06859 x = 0;
06860 dahdi_disable_ec(p);
06861 } else {
06862 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06863 x = 1;
06864 }
06865 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06866 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06867 break;
06868 case AST_OPTION_OPRMODE:
06869 oprmode = (struct oprmode *) data;
06870
06871 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06872 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06873 chan->tech->type, oprmode->peer->tech->type);
06874 errno = EINVAL;
06875 return -1;
06876 }
06877 pp = oprmode->peer->tech_pvt;
06878 p->oprmode = pp->oprmode = 0;
06879
06880 p->oprpeer = pp;
06881 pp->oprpeer = p;
06882
06883 if (oprmode->mode)
06884 {
06885 pp->oprmode = oprmode->mode;
06886 p->oprmode = -oprmode->mode;
06887 }
06888 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06889 oprmode->mode, chan->name,oprmode->peer->name);
06890 break;
06891 case AST_OPTION_ECHOCAN:
06892 cp = (char *) data;
06893 if (*cp) {
06894 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06895 dahdi_enable_ec(p);
06896 } else {
06897 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06898 dahdi_disable_ec(p);
06899 }
06900 break;
06901 case AST_OPTION_DIGIT_DETECT:
06902 cp = (char *) data;
06903 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06904 if (*cp) {
06905 enable_dtmf_detect(p);
06906 } else {
06907 disable_dtmf_detect(p);
06908 }
06909 break;
06910 case AST_OPTION_FAX_DETECT:
06911 cp = (char *) data;
06912 if (p->dsp) {
06913 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06914 if (*cp) {
06915 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06916 } else {
06917 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06918 }
06919 ast_dsp_set_features(p->dsp, p->dsp_features);
06920 }
06921 break;
06922 default:
06923 return -1;
06924 }
06925 errno = 0;
06926
06927 return 0;
06928 }
06929
06930 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06931 {
06932 struct dahdi_pvt *p = chan->tech_pvt;
06933 int res = 0;
06934
06935 if (!p) {
06936
06937 *buf = '\0';
06938 return -1;
06939 }
06940
06941 if (!strcasecmp(data, "rxgain")) {
06942 ast_mutex_lock(&p->lock);
06943 snprintf(buf, len, "%f", p->rxgain);
06944 ast_mutex_unlock(&p->lock);
06945 } else if (!strcasecmp(data, "txgain")) {
06946 ast_mutex_lock(&p->lock);
06947 snprintf(buf, len, "%f", p->txgain);
06948 ast_mutex_unlock(&p->lock);
06949 } else if (!strcasecmp(data, "dahdi_channel")) {
06950 ast_mutex_lock(&p->lock);
06951 snprintf(buf, len, "%d", p->channel);
06952 ast_mutex_unlock(&p->lock);
06953 } else if (!strcasecmp(data, "dahdi_span")) {
06954 ast_mutex_lock(&p->lock);
06955 snprintf(buf, len, "%d", p->span);
06956 ast_mutex_unlock(&p->lock);
06957 } else if (!strcasecmp(data, "dahdi_type")) {
06958 ast_mutex_lock(&p->lock);
06959 switch (p->sig) {
06960 #if defined(HAVE_OPENR2)
06961 case SIG_MFCR2:
06962 ast_copy_string(buf, "mfc/r2", len);
06963 break;
06964 #endif
06965 #if defined(HAVE_PRI)
06966 case SIG_PRI_LIB_HANDLE_CASES:
06967 ast_copy_string(buf, "pri", len);
06968 break;
06969 #endif
06970 case 0:
06971 ast_copy_string(buf, "pseudo", len);
06972 break;
06973 #if defined(HAVE_SS7)
06974 case SIG_SS7:
06975 ast_copy_string(buf, "ss7", len);
06976 break;
06977 #endif
06978 default:
06979
06980 ast_copy_string(buf, "analog", len);
06981 break;
06982 }
06983 ast_mutex_unlock(&p->lock);
06984 #if defined(HAVE_PRI)
06985 #if defined(HAVE_PRI_REVERSE_CHARGE)
06986 } else if (!strcasecmp(data, "reversecharge")) {
06987 ast_mutex_lock(&p->lock);
06988 switch (p->sig) {
06989 case SIG_PRI_LIB_HANDLE_CASES:
06990 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06991 break;
06992 default:
06993 *buf = '\0';
06994 res = -1;
06995 break;
06996 }
06997 ast_mutex_unlock(&p->lock);
06998 #endif
06999 #if defined(HAVE_PRI_SETUP_KEYPAD)
07000 } else if (!strcasecmp(data, "keypad_digits")) {
07001 ast_mutex_lock(&p->lock);
07002 switch (p->sig) {
07003 case SIG_PRI_LIB_HANDLE_CASES:
07004 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
07005 len);
07006 break;
07007 default:
07008 *buf = '\0';
07009 res = -1;
07010 break;
07011 }
07012 ast_mutex_unlock(&p->lock);
07013 #endif
07014 } else if (!strcasecmp(data, "no_media_path")) {
07015 ast_mutex_lock(&p->lock);
07016 switch (p->sig) {
07017 case SIG_PRI_LIB_HANDLE_CASES:
07018
07019
07020
07021
07022 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
07023 break;
07024 default:
07025 *buf = '\0';
07026 res = -1;
07027 break;
07028 }
07029 ast_mutex_unlock(&p->lock);
07030 #endif
07031 } else {
07032 *buf = '\0';
07033 res = -1;
07034 }
07035
07036 return res;
07037 }
07038
07039
07040 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
07041 {
07042 int res;
07043 char policy_str[21] = "";
07044
07045 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
07046 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
07047 return 1;
07048 }
07049 if (*num_buffers < 0) {
07050 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
07051 return -1;
07052 }
07053 if (!strcasecmp(policy_str, "full")) {
07054 *policy = DAHDI_POLICY_WHEN_FULL;
07055 } else if (!strcasecmp(policy_str, "immediate")) {
07056 *policy = DAHDI_POLICY_IMMEDIATE;
07057 #if defined(HAVE_DAHDI_HALF_FULL)
07058 } else if (!strcasecmp(policy_str, "half")) {
07059 *policy = DAHDI_POLICY_HALF_FULL;
07060 #endif
07061 } else {
07062 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
07063 return -1;
07064 }
07065
07066 return 0;
07067 }
07068
07069 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
07070 {
07071 struct dahdi_pvt *p = chan->tech_pvt;
07072 int res = 0;
07073
07074 if (!p) {
07075
07076 return -1;
07077 }
07078
07079 if (!strcasecmp(data, "buffers")) {
07080 int num_bufs, policy;
07081
07082 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
07083 struct dahdi_bufferinfo bi = {
07084 .txbufpolicy = policy,
07085 .rxbufpolicy = policy,
07086 .bufsize = p->bufsize,
07087 .numbufs = num_bufs,
07088 };
07089 int bpres;
07090
07091 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07092 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
07093 } else {
07094 p->bufferoverrideinuse = 1;
07095 }
07096 } else {
07097 res = -1;
07098 }
07099 } else if (!strcasecmp(data, "echocan_mode")) {
07100 if (!strcasecmp(value, "on")) {
07101 ast_mutex_lock(&p->lock);
07102 dahdi_enable_ec(p);
07103 ast_mutex_unlock(&p->lock);
07104 } else if (!strcasecmp(value, "off")) {
07105 ast_mutex_lock(&p->lock);
07106 dahdi_disable_ec(p);
07107 ast_mutex_unlock(&p->lock);
07108 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07109 } else if (!strcasecmp(value, "fax")) {
07110 int blah = 1;
07111
07112 ast_mutex_lock(&p->lock);
07113 if (!p->echocanon) {
07114 dahdi_enable_ec(p);
07115 }
07116 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07117 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
07118 }
07119 ast_mutex_unlock(&p->lock);
07120 } else if (!strcasecmp(value, "voice")) {
07121 int blah = 0;
07122
07123 ast_mutex_lock(&p->lock);
07124 if (!p->echocanon) {
07125 dahdi_enable_ec(p);
07126 }
07127 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
07128 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
07129 }
07130 ast_mutex_unlock(&p->lock);
07131 #endif
07132 } else {
07133 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
07134 res = -1;
07135 }
07136 } else {
07137 res = -1;
07138 }
07139
07140 return res;
07141 }
07142
07143 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
07144 {
07145
07146 int x;
07147 int hasslaves;
07148 if (!master)
07149 return;
07150 if (needlock) {
07151 ast_mutex_lock(&master->lock);
07152 if (slave) {
07153 while (ast_mutex_trylock(&slave->lock)) {
07154 DEADLOCK_AVOIDANCE(&master->lock);
07155 }
07156 }
07157 }
07158 hasslaves = 0;
07159 for (x = 0; x < MAX_SLAVES; x++) {
07160 if (master->slaves[x]) {
07161 if (!slave || (master->slaves[x] == slave)) {
07162
07163 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
07164 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
07165 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
07166 master->slaves[x]->master = NULL;
07167 master->slaves[x] = NULL;
07168 } else
07169 hasslaves = 1;
07170 }
07171 if (!hasslaves)
07172 master->inconference = 0;
07173 }
07174 if (!slave) {
07175 if (master->master) {
07176
07177 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
07178 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
07179 hasslaves = 0;
07180 for (x = 0; x < MAX_SLAVES; x++) {
07181 if (master->master->slaves[x] == master)
07182 master->master->slaves[x] = NULL;
07183 else if (master->master->slaves[x])
07184 hasslaves = 1;
07185 }
07186 if (!hasslaves)
07187 master->master->inconference = 0;
07188 }
07189 master->master = NULL;
07190 }
07191 update_conf(master);
07192 if (needlock) {
07193 if (slave)
07194 ast_mutex_unlock(&slave->lock);
07195 ast_mutex_unlock(&master->lock);
07196 }
07197 }
07198
07199 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
07200 int x;
07201 if (!slave || !master) {
07202 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
07203 return;
07204 }
07205 for (x = 0; x < MAX_SLAVES; x++) {
07206 if (!master->slaves[x]) {
07207 master->slaves[x] = slave;
07208 break;
07209 }
07210 }
07211 if (x >= MAX_SLAVES) {
07212 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
07213 master->slaves[MAX_SLAVES - 1] = slave;
07214 }
07215 if (slave->master)
07216 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
07217 slave->master = master;
07218
07219 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
07220 }
07221
07222 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)
07223 {
07224 struct ast_channel *who;
07225 struct dahdi_pvt *p0, *p1, *op0, *op1;
07226 struct dahdi_pvt *master = NULL, *slave = NULL;
07227 struct ast_frame *f;
07228 int inconf = 0;
07229 int nothingok = 1;
07230 int ofd0, ofd1;
07231 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07232 int os0 = -1, os1 = -1;
07233 int priority = 0;
07234 struct ast_channel *oc0, *oc1;
07235 enum ast_bridge_result res;
07236 #ifdef PRI_2BCT
07237 int triedtopribridge = 0;
07238 q931_call *q931c0;
07239 q931_call *q931c1;
07240 #endif
07241
07242
07243
07244
07245
07246
07247 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07248 return AST_BRIDGE_FAILED_NOWARN;
07249
07250 ast_channel_lock(c0);
07251 while (ast_channel_trylock(c1)) {
07252 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07253 }
07254
07255 p0 = c0->tech_pvt;
07256 p1 = c1->tech_pvt;
07257
07258 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07259 ast_channel_unlock(c0);
07260 ast_channel_unlock(c1);
07261 return AST_BRIDGE_FAILED_NOWARN;
07262 }
07263
07264 oi0 = dahdi_get_index(c0, p0, 0);
07265 oi1 = dahdi_get_index(c1, p1, 0);
07266 if ((oi0 < 0) || (oi1 < 0)) {
07267 ast_channel_unlock(c0);
07268 ast_channel_unlock(c1);
07269 return AST_BRIDGE_FAILED;
07270 }
07271
07272 op0 = p0 = c0->tech_pvt;
07273 op1 = p1 = c1->tech_pvt;
07274 ofd0 = c0->fds[0];
07275 ofd1 = c1->fds[0];
07276 oc0 = p0->owner;
07277 oc1 = p1->owner;
07278
07279 if (ast_mutex_trylock(&p0->lock)) {
07280
07281 ast_channel_unlock(c0);
07282 ast_channel_unlock(c1);
07283 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07284 return AST_BRIDGE_RETRY;
07285 }
07286 if (ast_mutex_trylock(&p1->lock)) {
07287
07288 ast_mutex_unlock(&p0->lock);
07289 ast_channel_unlock(c0);
07290 ast_channel_unlock(c1);
07291 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07292 return AST_BRIDGE_RETRY;
07293 }
07294
07295 if ((p0->callwaiting && p0->callwaitingcallerid)
07296 || (p1->callwaiting && p1->callwaitingcallerid)) {
07297
07298
07299
07300
07301
07302
07303
07304
07305
07306 ast_mutex_unlock(&p0->lock);
07307 ast_mutex_unlock(&p1->lock);
07308 ast_channel_unlock(c0);
07309 ast_channel_unlock(c1);
07310 return AST_BRIDGE_FAILED_NOWARN;
07311 }
07312
07313 #if defined(HAVE_PRI)
07314 if ((dahdi_sig_pri_lib_handles(p0->sig)
07315 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07316 || (dahdi_sig_pri_lib_handles(p1->sig)
07317 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07318
07319
07320
07321
07322 ast_mutex_unlock(&p0->lock);
07323 ast_mutex_unlock(&p1->lock);
07324 ast_channel_unlock(c0);
07325 ast_channel_unlock(c1);
07326 return AST_BRIDGE_FAILED_NOWARN;
07327 }
07328 #endif
07329
07330 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07331 if (p0->owner && p1->owner) {
07332
07333 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07334 master = p0;
07335 slave = p1;
07336 inconf = 1;
07337 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07338 master = p1;
07339 slave = p0;
07340 inconf = 1;
07341 } else {
07342 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07343 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07344 p0->channel,
07345 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07346 p0->subs[SUB_REAL].inthreeway, p0->channel,
07347 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07348 p1->subs[SUB_REAL].inthreeway);
07349 }
07350 nothingok = 0;
07351 }
07352 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07353 if (p1->subs[SUB_THREEWAY].inthreeway) {
07354 master = p1;
07355 slave = p0;
07356 nothingok = 0;
07357 }
07358 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07359 if (p0->subs[SUB_THREEWAY].inthreeway) {
07360 master = p0;
07361 slave = p1;
07362 nothingok = 0;
07363 }
07364 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07365
07366
07367 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07368 master = p1;
07369 slave = p0;
07370 nothingok = 0;
07371 }
07372 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07373
07374 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07375 master = p0;
07376 slave = p1;
07377 nothingok = 0;
07378 }
07379 }
07380 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07381 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07382 if (master && slave) {
07383
07384
07385
07386 if ((oi1 == SUB_THREEWAY) &&
07387 p1->subs[SUB_THREEWAY].inthreeway &&
07388 p1->subs[SUB_REAL].owner &&
07389 p1->subs[SUB_REAL].inthreeway &&
07390 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07391 ast_debug(1,
07392 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07393 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07394 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07395 os1 = p1->subs[SUB_REAL].owner->_state;
07396 } else {
07397 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07398 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07399 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07400 }
07401 if ((oi0 == SUB_THREEWAY) &&
07402 p0->subs[SUB_THREEWAY].inthreeway &&
07403 p0->subs[SUB_REAL].owner &&
07404 p0->subs[SUB_REAL].inthreeway &&
07405 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07406 ast_debug(1,
07407 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07408 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07409 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07410 os0 = p0->subs[SUB_REAL].owner->_state;
07411 } else {
07412 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07413 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07414 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07415 }
07416 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07417 if (!p0->echocanbridged || !p1->echocanbridged) {
07418
07419 dahdi_disable_ec(p0);
07420 dahdi_disable_ec(p1);
07421 }
07422 }
07423 dahdi_link(slave, master);
07424 master->inconference = inconf;
07425 } else if (!nothingok)
07426 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07427
07428 update_conf(p0);
07429 update_conf(p1);
07430 t0 = p0->subs[SUB_REAL].inthreeway;
07431 t1 = p1->subs[SUB_REAL].inthreeway;
07432
07433 ast_mutex_unlock(&p0->lock);
07434 ast_mutex_unlock(&p1->lock);
07435
07436 ast_channel_unlock(c0);
07437 ast_channel_unlock(c1);
07438
07439
07440 if ((!master || !slave) && !nothingok) {
07441 dahdi_enable_ec(p0);
07442 dahdi_enable_ec(p1);
07443 return AST_BRIDGE_FAILED;
07444 }
07445
07446 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07447
07448 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07449 disable_dtmf_detect(op0);
07450
07451 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07452 disable_dtmf_detect(op1);
07453
07454 for (;;) {
07455 struct ast_channel *c0_priority[2] = {c0, c1};
07456 struct ast_channel *c1_priority[2] = {c1, c0};
07457
07458
07459
07460
07461 ast_channel_lock(c0);
07462 while (ast_channel_trylock(c1)) {
07463 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07464 }
07465
07466 p0 = c0->tech_pvt;
07467 p1 = c1->tech_pvt;
07468
07469 if (op0 == p0)
07470 i0 = dahdi_get_index(c0, p0, 1);
07471 if (op1 == p1)
07472 i1 = dahdi_get_index(c1, p1, 1);
07473
07474 ast_channel_unlock(c0);
07475 ast_channel_unlock(c1);
07476
07477 if (!timeoutms ||
07478 (op0 != p0) ||
07479 (op1 != p1) ||
07480 (ofd0 != c0->fds[0]) ||
07481 (ofd1 != c1->fds[0]) ||
07482 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07483 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07484 (oc0 != p0->owner) ||
07485 (oc1 != p1->owner) ||
07486 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07487 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07488 (oi0 != i0) ||
07489 (oi1 != i1)) {
07490 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07491 op0->channel, oi0, op1->channel, oi1);
07492 res = AST_BRIDGE_RETRY;
07493 goto return_from_bridge;
07494 }
07495
07496 #ifdef PRI_2BCT
07497 if (!triedtopribridge) {
07498 triedtopribridge = 1;
07499 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07500 ast_mutex_lock(&p0->pri->lock);
07501 switch (p0->sig) {
07502 case SIG_PRI_LIB_HANDLE_CASES:
07503 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07504 break;
07505 default:
07506 q931c0 = NULL;
07507 break;
07508 }
07509 switch (p1->sig) {
07510 case SIG_PRI_LIB_HANDLE_CASES:
07511 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07512 break;
07513 default:
07514 q931c1 = NULL;
07515 break;
07516 }
07517 if (q931c0 && q931c1) {
07518 pri_channel_bridge(q931c0, q931c1);
07519 }
07520 ast_mutex_unlock(&p0->pri->lock);
07521 }
07522 }
07523 #endif
07524
07525 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07526 if (!who) {
07527 ast_debug(1, "Ooh, empty read...\n");
07528 continue;
07529 }
07530 f = ast_read(who);
07531 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07532 *fo = f;
07533 *rc = who;
07534 res = AST_BRIDGE_COMPLETE;
07535 goto return_from_bridge;
07536 }
07537 if (f->frametype == AST_FRAME_DTMF) {
07538 if ((who == c0) && p0->pulsedial) {
07539 ast_write(c1, f);
07540 } else if ((who == c1) && p1->pulsedial) {
07541 ast_write(c0, f);
07542 } else {
07543 *fo = f;
07544 *rc = who;
07545 res = AST_BRIDGE_COMPLETE;
07546 goto return_from_bridge;
07547 }
07548 }
07549 ast_frfree(f);
07550
07551
07552 priority = !priority;
07553 }
07554
07555 return_from_bridge:
07556 if (op0 == p0)
07557 dahdi_enable_ec(p0);
07558
07559 if (op1 == p1)
07560 dahdi_enable_ec(p1);
07561
07562 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07563 enable_dtmf_detect(op0);
07564
07565 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07566 enable_dtmf_detect(op1);
07567
07568 dahdi_unlink(slave, master, 1);
07569
07570 return res;
07571 }
07572
07573 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07574 {
07575 struct dahdi_pvt *p = newchan->tech_pvt;
07576 int x;
07577
07578 ast_mutex_lock(&p->lock);
07579
07580 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07581 if (p->owner == oldchan) {
07582 p->owner = newchan;
07583 }
07584 for (x = 0; x < 3; x++) {
07585 if (p->subs[x].owner == oldchan) {
07586 if (!x) {
07587 dahdi_unlink(NULL, p, 0);
07588 }
07589 p->subs[x].owner = newchan;
07590 }
07591 }
07592 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07593 analog_fixup(oldchan, newchan, p->sig_pvt);
07594 #if defined(HAVE_PRI)
07595 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07596 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07597 #endif
07598 #if defined(HAVE_SS7)
07599 } else if (p->sig == SIG_SS7) {
07600 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07601 #endif
07602 }
07603 update_conf(p);
07604
07605 ast_mutex_unlock(&p->lock);
07606
07607 if (newchan->_state == AST_STATE_RINGING) {
07608 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07609 }
07610 return 0;
07611 }
07612
07613 static int dahdi_ring_phone(struct dahdi_pvt *p)
07614 {
07615 int x;
07616 int res;
07617
07618 x = 0;
07619 x = DAHDI_ONHOOK;
07620 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07621 do {
07622 x = DAHDI_RING;
07623 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07624 if (res) {
07625 switch (errno) {
07626 case EBUSY:
07627 case EINTR:
07628
07629 usleep(10000);
07630 continue;
07631 case EINPROGRESS:
07632 res = 0;
07633 break;
07634 default:
07635 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07636 res = 0;
07637 }
07638 }
07639 } while (res);
07640 return res;
07641 }
07642
07643 static void *analog_ss_thread(void *data);
07644
07645 static int attempt_transfer(struct dahdi_pvt *p)
07646 {
07647
07648
07649
07650 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07651
07652
07653 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07654 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07655 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07656 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07657 }
07658 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07659 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07660 }
07661 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07662 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07663 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07664 return -1;
07665 }
07666
07667 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07668 unalloc_sub(p, SUB_THREEWAY);
07669 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07670 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07671 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07672 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07673 }
07674 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07675 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07676 }
07677 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07678 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07679 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07680 return -1;
07681 }
07682
07683 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07684 ast_channel_unlock(p->subs[SUB_REAL].owner);
07685 unalloc_sub(p, SUB_THREEWAY);
07686
07687 return 1;
07688 } else {
07689 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07690 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07691 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07692 return -1;
07693 }
07694 return 0;
07695 }
07696
07697 static int check_for_conference(struct dahdi_pvt *p)
07698 {
07699 struct dahdi_confinfo ci;
07700
07701 if (p->master || (p->confno > -1))
07702 return 0;
07703 memset(&ci, 0, sizeof(ci));
07704 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07705 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07706 return 0;
07707 }
07708
07709
07710
07711 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07712 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07713 return 1;
07714 }
07715 return 0;
07716 }
07717
07718
07719
07720
07721
07722
07723 static int get_alarms(struct dahdi_pvt *p)
07724 {
07725 int res;
07726 struct dahdi_spaninfo zi;
07727 struct dahdi_params params;
07728
07729 memset(&zi, 0, sizeof(zi));
07730 zi.spanno = p->span;
07731
07732 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07733 if (zi.alarms != DAHDI_ALARM_NONE)
07734 return zi.alarms;
07735 } else {
07736 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07737 return 0;
07738 }
07739
07740
07741 memset(¶ms, 0, sizeof(params));
07742 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07743 return params.chan_alarms;
07744
07745 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07746
07747 return DAHDI_ALARM_NONE;
07748 }
07749
07750 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07751 {
07752 struct dahdi_pvt *p = ast->tech_pvt;
07753 struct ast_frame *f = *dest;
07754
07755 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07756 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07757 f->subclass.integer, f->subclass.integer, ast->name);
07758
07759 if (p->confirmanswer) {
07760 if (f->frametype == AST_FRAME_DTMF_END) {
07761 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07762
07763
07764 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07765 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07766
07767 p->confirmanswer = 0;
07768 } else {
07769 p->subs[idx].f.frametype = AST_FRAME_NULL;
07770 p->subs[idx].f.subclass.integer = 0;
07771 }
07772 *dest = &p->subs[idx].f;
07773 } else if (p->callwaitcas) {
07774 if (f->frametype == AST_FRAME_DTMF_END) {
07775 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07776 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07777 ast_free(p->cidspill);
07778 p->cidspill = NULL;
07779 send_cwcidspill(p);
07780 }
07781 p->callwaitcas = 0;
07782 }
07783 p->subs[idx].f.frametype = AST_FRAME_NULL;
07784 p->subs[idx].f.subclass.integer = 0;
07785 *dest = &p->subs[idx].f;
07786 } else if (f->subclass.integer == 'f') {
07787 if (f->frametype == AST_FRAME_DTMF_END) {
07788
07789 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07790
07791 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07792 struct dahdi_bufferinfo bi = {
07793 .txbufpolicy = p->faxbuf_policy,
07794 .bufsize = p->bufsize,
07795 .numbufs = p->faxbuf_no
07796 };
07797 int res;
07798
07799 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07800 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07801 } else {
07802 p->bufferoverrideinuse = 1;
07803 }
07804 }
07805 p->faxhandled = 1;
07806 if (p->dsp) {
07807 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07808 ast_dsp_set_features(p->dsp, p->dsp_features);
07809 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07810 }
07811 if (strcmp(ast->exten, "fax")) {
07812 const char *target_context = S_OR(ast->macrocontext, ast->context);
07813
07814
07815
07816
07817
07818 ast_mutex_unlock(&p->lock);
07819 ast_channel_unlock(ast);
07820 if (ast_exists_extension(ast, target_context, "fax", 1,
07821 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07822 ast_channel_lock(ast);
07823 ast_mutex_lock(&p->lock);
07824 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07825
07826 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07827 if (ast_async_goto(ast, target_context, "fax", 1))
07828 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07829 } else {
07830 ast_channel_lock(ast);
07831 ast_mutex_lock(&p->lock);
07832 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07833 }
07834 } else {
07835 ast_debug(1, "Already in a fax extension, not redirecting\n");
07836 }
07837 } else {
07838 ast_debug(1, "Fax already handled\n");
07839 }
07840 dahdi_confmute(p, 0);
07841 }
07842 p->subs[idx].f.frametype = AST_FRAME_NULL;
07843 p->subs[idx].f.subclass.integer = 0;
07844 *dest = &p->subs[idx].f;
07845 }
07846 }
07847
07848 static void handle_alarms(struct dahdi_pvt *p, int alms)
07849 {
07850 const char *alarm_str;
07851
07852 #if defined(HAVE_PRI)
07853 if (dahdi_sig_pri_lib_handles(p->sig) && sig_pri_is_alarm_ignored(p->pri)) {
07854 return;
07855 }
07856 #endif
07857
07858 alarm_str = alarm2str(alms);
07859 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07860 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07861 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07862 "Alarm: %s\r\n"
07863 "Channel: %d\r\n",
07864 alarm_str, p->channel);
07865 }
07866
07867 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07868 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07869 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07870 "Alarm: %s\r\n"
07871 "Span: %d\r\n",
07872 alarm_str, p->span);
07873 }
07874 }
07875
07876 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07877 {
07878 int res, x;
07879 int idx, mysig;
07880 char *c;
07881 struct dahdi_pvt *p = ast->tech_pvt;
07882 pthread_t threadid;
07883 struct ast_channel *chan;
07884 struct ast_frame *f;
07885
07886 idx = dahdi_get_index(ast, p, 0);
07887 if (idx < 0) {
07888 return &ast_null_frame;
07889 }
07890 mysig = p->sig;
07891 if (p->outsigmod > -1)
07892 mysig = p->outsigmod;
07893 p->subs[idx].f.frametype = AST_FRAME_NULL;
07894 p->subs[idx].f.subclass.integer = 0;
07895 p->subs[idx].f.datalen = 0;
07896 p->subs[idx].f.samples = 0;
07897 p->subs[idx].f.mallocd = 0;
07898 p->subs[idx].f.offset = 0;
07899 p->subs[idx].f.src = "dahdi_handle_event";
07900 p->subs[idx].f.data.ptr = NULL;
07901 f = &p->subs[idx].f;
07902
07903 if (p->fake_event) {
07904 res = p->fake_event;
07905 p->fake_event = 0;
07906 } else
07907 res = dahdi_get_event(p->subs[idx].dfd);
07908
07909 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07910
07911 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07912 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07913 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07914 #if defined(HAVE_PRI)
07915 if (dahdi_sig_pri_lib_handles(p->sig)
07916 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07917 && p->pri
07918 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07919
07920 } else
07921 #endif
07922 {
07923
07924 dahdi_confmute(p, 0);
07925 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07926 p->subs[idx].f.subclass.integer = res & 0xff;
07927 dahdi_handle_dtmf(ast, idx, &f);
07928 }
07929 return f;
07930 }
07931
07932 if (res & DAHDI_EVENT_DTMFDOWN) {
07933 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07934 #if defined(HAVE_PRI)
07935 if (dahdi_sig_pri_lib_handles(p->sig)
07936 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
07937 && p->pri
07938 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07939
07940 } else
07941 #endif
07942 {
07943
07944 dahdi_confmute(p, 1);
07945 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07946 p->subs[idx].f.subclass.integer = res & 0xff;
07947 dahdi_handle_dtmf(ast, idx, &f);
07948 }
07949 return &p->subs[idx].f;
07950 }
07951
07952 switch (res) {
07953 case DAHDI_EVENT_EC_DISABLED:
07954 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07955 p->echocanon = 0;
07956 break;
07957 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07958 case DAHDI_EVENT_TX_CED_DETECTED:
07959 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07960 break;
07961 case DAHDI_EVENT_RX_CED_DETECTED:
07962 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07963 break;
07964 case DAHDI_EVENT_EC_NLP_DISABLED:
07965 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07966 break;
07967 case DAHDI_EVENT_EC_NLP_ENABLED:
07968 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07969 break;
07970 #endif
07971 case DAHDI_EVENT_BITSCHANGED:
07972 #ifdef HAVE_OPENR2
07973 if (p->sig != SIG_MFCR2) {
07974 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07975 } else {
07976 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07977 openr2_chan_handle_cas(p->r2chan);
07978 }
07979 #else
07980 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07981 #endif
07982 break;
07983 case DAHDI_EVENT_PULSE_START:
07984
07985 if (!ast->pbx)
07986 tone_zone_play_tone(p->subs[idx].dfd, -1);
07987 break;
07988 case DAHDI_EVENT_DIALCOMPLETE:
07989
07990 #if defined(HAVE_PRI)
07991 if (dahdi_sig_pri_lib_handles(p->sig)) {
07992 if (p->inalarm) {
07993 break;
07994 }
07995 if (ioctl(p->subs[idx].dfd, DAHDI_DIALING, &x) == -1) {
07996 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n", ast->name,
07997 strerror(errno));
07998 return NULL;
07999 }
08000 if (x) {
08001
08002 break;
08003 }
08004
08005
08006
08007
08008 sig_pri_dial_complete(p->sig_pvt, ast);
08009 break;
08010 }
08011 #endif
08012 #ifdef HAVE_OPENR2
08013 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
08014
08015
08016 break;
08017 }
08018 #endif
08019 if (p->inalarm) break;
08020 if ((p->radio || (p->oprmode < 0))) break;
08021 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
08022 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
08023 return NULL;
08024 }
08025 if (!x) {
08026 dahdi_enable_ec(p);
08027 if (p->echobreak) {
08028 dahdi_train_ec(p);
08029 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
08030 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08031 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08032 p->echobreak = 0;
08033 } else {
08034 p->dialing = 0;
08035 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
08036
08037 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
08038 ast_setstate(ast, AST_STATE_UP);
08039 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08040 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08041 break;
08042 } else {
08043
08044 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
08045 }
08046 }
08047 if (ast->_state == AST_STATE_DIALING) {
08048 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
08049 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
08050 } else if (p->confirmanswer || (!p->dialednone
08051 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
08052 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
08053 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
08054 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
08055 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
08056 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
08057 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
08058 || (mysig == SIG_SF_FEATB)))) {
08059 ast_setstate(ast, AST_STATE_RINGING);
08060 } else if (!p->answeronpolarityswitch) {
08061 ast_setstate(ast, AST_STATE_UP);
08062 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08063 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08064
08065 p->polarity = POLARITY_REV;
08066 } else {
08067
08068 p->polarity = POLARITY_IDLE;
08069 }
08070 }
08071 }
08072 }
08073 break;
08074 case DAHDI_EVENT_ALARM:
08075 switch (p->sig) {
08076 #if defined(HAVE_PRI)
08077 case SIG_PRI_LIB_HANDLE_CASES:
08078 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
08079 break;
08080 #endif
08081 #if defined(HAVE_SS7)
08082 case SIG_SS7:
08083 sig_ss7_set_alarm(p->sig_pvt, 1);
08084 break;
08085 #endif
08086 default:
08087 p->inalarm = 1;
08088 break;
08089 }
08090 res = get_alarms(p);
08091 handle_alarms(p, res);
08092 #ifdef HAVE_PRI
08093 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
08094
08095 } else {
08096 break;
08097 }
08098 #endif
08099 #if defined(HAVE_SS7)
08100 if (p->sig == SIG_SS7)
08101 break;
08102 #endif
08103 #ifdef HAVE_OPENR2
08104 if (p->sig == SIG_MFCR2)
08105 break;
08106 #endif
08107 case DAHDI_EVENT_ONHOOK:
08108 if (p->radio) {
08109 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08110 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08111 break;
08112 }
08113 if (p->oprmode < 0)
08114 {
08115 if (p->oprmode != -1) break;
08116 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08117 {
08118
08119 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08120 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
08121 save_conference(p->oprpeer);
08122 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08123 }
08124 break;
08125 }
08126 switch (p->sig) {
08127 case SIG_FXOLS:
08128 case SIG_FXOGS:
08129 case SIG_FXOKS:
08130
08131 if (idx == SUB_REAL) {
08132
08133 if (p->subs[SUB_CALLWAIT].owner) {
08134
08135 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
08136 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
08137 unalloc_sub(p, SUB_CALLWAIT);
08138 #if 0
08139 p->subs[idx].needanswer = 0;
08140 p->subs[idx].needringing = 0;
08141 #endif
08142 p->callwaitingrepeat = 0;
08143 p->cidcwexpire = 0;
08144 p->cid_suppress_expire = 0;
08145 p->owner = NULL;
08146
08147 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
08148 p->dialing = 1;
08149 dahdi_ring_phone(p);
08150 } else if (p->subs[SUB_THREEWAY].owner) {
08151 unsigned int mssinceflash;
08152
08153
08154 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
08155
08156 DLA_UNLOCK(&p->lock);
08157 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08158
08159
08160
08161 DLA_LOCK(&p->lock);
08162 if (p->owner != ast) {
08163 ast_log(LOG_WARNING, "This isn't good...\n");
08164 return NULL;
08165 }
08166 }
08167 if (!p->subs[SUB_THREEWAY].owner) {
08168 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
08169 return NULL;
08170 }
08171 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
08172 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
08173 if (mssinceflash < MIN_MS_SINCE_FLASH) {
08174
08175
08176 if (p->subs[SUB_THREEWAY].owner)
08177 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
08178 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08179 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
08180 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08181 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
08182 if (p->transfer) {
08183
08184 p->subs[SUB_REAL].inthreeway = 0;
08185 p->subs[SUB_THREEWAY].inthreeway = 0;
08186
08187 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
08188 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08189
08190 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08191 p->owner = NULL;
08192
08193 dahdi_ring_phone(p);
08194 } else {
08195 if ((res = attempt_transfer(p)) < 0) {
08196 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08197 if (p->subs[SUB_THREEWAY].owner)
08198 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08199 } else if (res) {
08200
08201 if (p->subs[SUB_THREEWAY].owner)
08202 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08203 break;
08204 }
08205 }
08206 } else {
08207 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08208 if (p->subs[SUB_THREEWAY].owner)
08209 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08210 }
08211 } else {
08212 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
08213
08214 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08215 p->owner = NULL;
08216
08217 dahdi_ring_phone(p);
08218 }
08219 }
08220 } else {
08221 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
08222 }
08223
08224 default:
08225 dahdi_disable_ec(p);
08226 return NULL;
08227 }
08228 break;
08229 case DAHDI_EVENT_RINGOFFHOOK:
08230 if (p->inalarm) break;
08231 if (p->oprmode < 0)
08232 {
08233 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
08234 {
08235
08236 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08237 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
08238 restore_conference(p->oprpeer);
08239 }
08240 break;
08241 }
08242 if (p->radio)
08243 {
08244 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08245 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08246 break;
08247 }
08248
08249
08250 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
08251 c = strchr(p->dialdest, '/');
08252 if (c)
08253 c++;
08254 else
08255 c = p->dialdest;
08256 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08257 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08258 if (strlen(p->dop.dialstr) > 4) {
08259 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08260 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08261 p->echorest[sizeof(p->echorest) - 1] = '\0';
08262 p->echobreak = 1;
08263 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08264 } else
08265 p->echobreak = 0;
08266 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08267 int saveerr = errno;
08268
08269 x = DAHDI_ONHOOK;
08270 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08271 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08272 return NULL;
08273 }
08274 p->dialing = 1;
08275 return &p->subs[idx].f;
08276 }
08277 switch (p->sig) {
08278 case SIG_FXOLS:
08279 case SIG_FXOGS:
08280 case SIG_FXOKS:
08281 switch (ast->_state) {
08282 case AST_STATE_RINGING:
08283 dahdi_enable_ec(p);
08284 dahdi_train_ec(p);
08285 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08286 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08287
08288 p->subs[SUB_REAL].needringing = 0;
08289 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08290 ast_debug(1, "channel %d answered\n", p->channel);
08291
08292
08293 ast_free(p->cidspill);
08294 p->cidspill = NULL;
08295 restore_conference(p);
08296
08297 p->dialing = 0;
08298 p->callwaitcas = 0;
08299 if (p->confirmanswer) {
08300
08301 p->subs[idx].f.frametype = AST_FRAME_NULL;
08302 p->subs[idx].f.subclass.integer = 0;
08303 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08304
08305 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08306 if (res < 0) {
08307 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08308 p->dop.dialstr[0] = '\0';
08309 return NULL;
08310 } else {
08311 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08312 p->subs[idx].f.frametype = AST_FRAME_NULL;
08313 p->subs[idx].f.subclass.integer = 0;
08314 p->dialing = 1;
08315 }
08316 p->dop.dialstr[0] = '\0';
08317 ast_setstate(ast, AST_STATE_DIALING);
08318 } else
08319 ast_setstate(ast, AST_STATE_UP);
08320 return &p->subs[idx].f;
08321 case AST_STATE_DOWN:
08322 ast_setstate(ast, AST_STATE_RING);
08323 ast->rings = 1;
08324 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08325 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08326 ast_debug(1, "channel %d picked up\n", p->channel);
08327 return &p->subs[idx].f;
08328 case AST_STATE_UP:
08329
08330 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08331
08332 if (ast_bridged_channel(p->owner))
08333 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08334 p->subs[idx].needunhold = 1;
08335 break;
08336 case AST_STATE_RESERVED:
08337
08338 if (has_voicemail(p))
08339 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08340 else
08341 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08342 break;
08343 default:
08344 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08345 }
08346 break;
08347 case SIG_FXSLS:
08348 case SIG_FXSGS:
08349 case SIG_FXSKS:
08350 if (ast->_state == AST_STATE_RING) {
08351 p->ringt = p->ringt_base;
08352 }
08353
08354
08355
08356 ast_debug(1, "Setting IDLE polarity due "
08357 "to ring. Old polarity was %d\n",
08358 p->polarity);
08359 p->polarity = POLARITY_IDLE;
08360
08361
08362 case SIG_EM:
08363 case SIG_EM_E1:
08364 case SIG_EMWINK:
08365 case SIG_FEATD:
08366 case SIG_FEATDMF:
08367 case SIG_FEATDMF_TA:
08368 case SIG_E911:
08369 case SIG_FGC_CAMA:
08370 case SIG_FGC_CAMAMF:
08371 case SIG_FEATB:
08372 case SIG_SF:
08373 case SIG_SFWINK:
08374 case SIG_SF_FEATD:
08375 case SIG_SF_FEATDMF:
08376 case SIG_SF_FEATB:
08377 if (ast->_state == AST_STATE_PRERING)
08378 ast_setstate(ast, AST_STATE_RING);
08379 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08380 ast_debug(1, "Ring detected\n");
08381 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08382 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08383 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08384 ast_debug(1, "Line answered\n");
08385 if (p->confirmanswer) {
08386 p->subs[idx].f.frametype = AST_FRAME_NULL;
08387 p->subs[idx].f.subclass.integer = 0;
08388 } else {
08389 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08390 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08391 ast_setstate(ast, AST_STATE_UP);
08392 }
08393 } else if (ast->_state != AST_STATE_RING)
08394 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08395 break;
08396 default:
08397 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08398 }
08399 break;
08400 case DAHDI_EVENT_RINGBEGIN:
08401 switch (p->sig) {
08402 case SIG_FXSLS:
08403 case SIG_FXSGS:
08404 case SIG_FXSKS:
08405 if (ast->_state == AST_STATE_RING) {
08406 p->ringt = p->ringt_base;
08407 }
08408 break;
08409 }
08410 break;
08411 case DAHDI_EVENT_RINGERON:
08412 break;
08413 case DAHDI_EVENT_NOALARM:
08414 switch (p->sig) {
08415 #if defined(HAVE_PRI)
08416 case SIG_PRI_LIB_HANDLE_CASES:
08417 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08418 break;
08419 #endif
08420 #if defined(HAVE_SS7)
08421 case SIG_SS7:
08422 sig_ss7_set_alarm(p->sig_pvt, 0);
08423 break;
08424 #endif
08425 default:
08426 p->inalarm = 0;
08427 break;
08428 }
08429 handle_clear_alarms(p);
08430 break;
08431 case DAHDI_EVENT_WINKFLASH:
08432 if (p->inalarm) break;
08433 if (p->radio) break;
08434 if (p->oprmode < 0) break;
08435 if (p->oprmode > 1)
08436 {
08437 struct dahdi_params par;
08438
08439 memset(&par, 0, sizeof(par));
08440 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08441 {
08442 if (!par.rxisoffhook)
08443 {
08444
08445 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08446 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08447 save_conference(p);
08448 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08449 }
08450 }
08451 break;
08452 }
08453
08454 p->flashtime = ast_tvnow();
08455 switch (mysig) {
08456 case SIG_FXOLS:
08457 case SIG_FXOGS:
08458 case SIG_FXOKS:
08459 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08460 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08461
08462
08463 ast_free(p->cidspill);
08464 p->cidspill = NULL;
08465 restore_conference(p);
08466 p->callwaitcas = 0;
08467
08468 if (idx != SUB_REAL) {
08469 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08470 goto winkflashdone;
08471 }
08472
08473 if (p->subs[SUB_CALLWAIT].owner) {
08474
08475 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08476 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08477 p->owner = p->subs[SUB_REAL].owner;
08478 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08479 if (p->owner->_state == AST_STATE_RINGING) {
08480 ast_setstate(p->owner, AST_STATE_UP);
08481 p->subs[SUB_REAL].needanswer = 1;
08482 }
08483 p->callwaitingrepeat = 0;
08484 p->cidcwexpire = 0;
08485 p->cid_suppress_expire = 0;
08486
08487 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08488 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08489 S_OR(p->mohsuggest, NULL),
08490 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08491 }
08492 p->subs[SUB_CALLWAIT].needhold = 1;
08493 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08494 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08495 S_OR(p->mohsuggest, NULL),
08496 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08497 }
08498 p->subs[SUB_REAL].needunhold = 1;
08499 } else if (!p->subs[SUB_THREEWAY].owner) {
08500 if (!p->threewaycalling) {
08501
08502 p->subs[SUB_REAL].needflash = 1;
08503 goto winkflashdone;
08504 } else if (!check_for_conference(p)) {
08505 char cid_num[256];
08506 char cid_name[256];
08507
08508 cid_num[0] = 0;
08509 cid_name[0] = 0;
08510 if (p->dahditrcallerid && p->owner) {
08511 if (p->owner->caller.id.number.valid
08512 && p->owner->caller.id.number.str) {
08513 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08514 sizeof(cid_num));
08515 }
08516 if (p->owner->caller.id.name.valid
08517 && p->owner->caller.id.name.str) {
08518 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08519 sizeof(cid_name));
08520 }
08521 }
08522
08523
08524 if (!((ast->pbx) ||
08525 (ast->_state == AST_STATE_UP) ||
08526 (ast->_state == AST_STATE_RING))) {
08527 ast_debug(1, "Flash when call not up or ringing\n");
08528 goto winkflashdone;
08529 }
08530 if (alloc_sub(p, SUB_THREEWAY)) {
08531 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08532 goto winkflashdone;
08533 }
08534
08535
08536
08537
08538
08539
08540
08541 ast_mutex_unlock(&p->lock);
08542 ast_channel_unlock(ast);
08543 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08544 ast_channel_lock(ast);
08545 ast_mutex_lock(&p->lock);
08546 if (p->dahditrcallerid) {
08547 if (!p->origcid_num)
08548 p->origcid_num = ast_strdup(p->cid_num);
08549 if (!p->origcid_name)
08550 p->origcid_name = ast_strdup(p->cid_name);
08551 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08552 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08553 }
08554
08555 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08556
08557 dahdi_disable_ec(p);
08558 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08559 if (res)
08560 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08561 p->owner = chan;
08562 if (!chan) {
08563 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08564 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08565 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08566 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08567 dahdi_enable_ec(p);
08568 ast_hangup(chan);
08569 } else {
08570 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08571
08572
08573 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08574 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08575 S_OR(p->mohsuggest, NULL),
08576 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08577 }
08578 p->subs[SUB_THREEWAY].needhold = 1;
08579 }
08580 }
08581 } else {
08582
08583 if (p->subs[SUB_THREEWAY].inthreeway) {
08584
08585 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08586
08587 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08588
08589 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08590 p->owner = p->subs[SUB_REAL].owner;
08591 }
08592
08593 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08594 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08595 p->subs[SUB_REAL].inthreeway = 0;
08596 p->subs[SUB_THREEWAY].inthreeway = 0;
08597 } else {
08598
08599 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08600 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08601 int otherindex = SUB_THREEWAY;
08602
08603 ast_verb(3, "Building conference call with %s and %s\n",
08604 p->subs[SUB_THREEWAY].owner->name,
08605 p->subs[SUB_REAL].owner->name);
08606
08607 p->subs[SUB_THREEWAY].inthreeway = 1;
08608 p->subs[SUB_REAL].inthreeway = 1;
08609 if (ast->_state == AST_STATE_UP) {
08610 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08611 otherindex = SUB_REAL;
08612 }
08613 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08614 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08615 p->subs[otherindex].needunhold = 1;
08616 p->owner = p->subs[SUB_REAL].owner;
08617 } else {
08618 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08619 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08620 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08621 p->owner = p->subs[SUB_REAL].owner;
08622 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08623 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08624 p->subs[SUB_REAL].needunhold = 1;
08625 dahdi_enable_ec(p);
08626 }
08627 }
08628 }
08629 winkflashdone:
08630 update_conf(p);
08631 break;
08632 case SIG_EM:
08633 case SIG_EM_E1:
08634 case SIG_FEATD:
08635 case SIG_SF:
08636 case SIG_SFWINK:
08637 case SIG_SF_FEATD:
08638 case SIG_FXSLS:
08639 case SIG_FXSGS:
08640 if (p->dialing)
08641 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08642 else
08643 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08644 break;
08645 case SIG_FEATDMF_TA:
08646 switch (p->whichwink) {
08647 case 0:
08648 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08649 S_COR(p->owner->caller.ani.number.valid,
08650 p->owner->caller.ani.number.str, ""));
08651 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08652 p->owner->caller.ani2,
08653 S_COR(p->owner->caller.ani.number.valid,
08654 p->owner->caller.ani.number.str, ""));
08655 break;
08656 case 1:
08657 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08658 break;
08659 case 2:
08660 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08661 return NULL;
08662 }
08663 p->whichwink++;
08664
08665 case SIG_FEATDMF:
08666 case SIG_E911:
08667 case SIG_FGC_CAMAMF:
08668 case SIG_FGC_CAMA:
08669 case SIG_FEATB:
08670 case SIG_SF_FEATDMF:
08671 case SIG_SF_FEATB:
08672 case SIG_EMWINK:
08673
08674 if (!ast_strlen_zero(p->dop.dialstr)) {
08675 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08676 if (res < 0) {
08677 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08678 p->dop.dialstr[0] = '\0';
08679 return NULL;
08680 } else
08681 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08682 }
08683 p->dop.dialstr[0] = '\0';
08684 break;
08685 default:
08686 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08687 }
08688 break;
08689 case DAHDI_EVENT_HOOKCOMPLETE:
08690 if (p->inalarm) break;
08691 if ((p->radio || (p->oprmode < 0))) break;
08692 if (p->waitingfordt.tv_sec) break;
08693 switch (mysig) {
08694 case SIG_FXSLS:
08695 case SIG_FXSGS:
08696 case SIG_FXSKS:
08697 case SIG_EM:
08698 case SIG_EM_E1:
08699 case SIG_EMWINK:
08700 case SIG_FEATD:
08701 case SIG_SF:
08702 case SIG_SFWINK:
08703 case SIG_SF_FEATD:
08704 if (!ast_strlen_zero(p->dop.dialstr)) {
08705 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08706 if (res < 0) {
08707 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08708 p->dop.dialstr[0] = '\0';
08709 return NULL;
08710 } else
08711 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08712 }
08713 p->dop.dialstr[0] = '\0';
08714 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08715 break;
08716 case SIG_FEATDMF:
08717 case SIG_FEATDMF_TA:
08718 case SIG_E911:
08719 case SIG_FGC_CAMA:
08720 case SIG_FGC_CAMAMF:
08721 case SIG_FEATB:
08722 case SIG_SF_FEATDMF:
08723 case SIG_SF_FEATB:
08724 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08725 break;
08726 default:
08727 break;
08728 }
08729 break;
08730 case DAHDI_EVENT_POLARITY:
08731
08732
08733
08734
08735
08736
08737 if (p->polarity == POLARITY_IDLE) {
08738 p->polarity = POLARITY_REV;
08739 if (p->answeronpolarityswitch &&
08740 ((ast->_state == AST_STATE_DIALING) ||
08741 (ast->_state == AST_STATE_RINGING))) {
08742 ast_debug(1, "Answering on polarity switch!\n");
08743 ast_setstate(p->owner, AST_STATE_UP);
08744 if (p->hanguponpolarityswitch) {
08745 p->polaritydelaytv = ast_tvnow();
08746 }
08747 } else
08748 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08749 }
08750
08751
08752 if (p->hanguponpolarityswitch &&
08753 (p->polarityonanswerdelay > 0) &&
08754 (p->polarity == POLARITY_REV) &&
08755 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08756
08757 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) );
08758
08759 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08760 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08761 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08762 p->polarity = POLARITY_IDLE;
08763 } else
08764 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);
08765
08766 } else {
08767 p->polarity = POLARITY_IDLE;
08768 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08769 }
08770
08771 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) );
08772 break;
08773 default:
08774 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08775 }
08776 return &p->subs[idx].f;
08777 }
08778
08779 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08780 {
08781 int res;
08782 int idx;
08783 struct ast_frame *f;
08784 int usedindex = -1;
08785 struct dahdi_pvt *p = ast->tech_pvt;
08786
08787 if ((idx = dahdi_get_index(ast, p, 0)) < 0) {
08788 idx = SUB_REAL;
08789 }
08790
08791 p->subs[idx].f.frametype = AST_FRAME_NULL;
08792 p->subs[idx].f.datalen = 0;
08793 p->subs[idx].f.samples = 0;
08794 p->subs[idx].f.mallocd = 0;
08795 p->subs[idx].f.offset = 0;
08796 p->subs[idx].f.subclass.integer = 0;
08797 p->subs[idx].f.delivery = ast_tv(0,0);
08798 p->subs[idx].f.src = "dahdi_exception";
08799 p->subs[idx].f.data.ptr = NULL;
08800
08801
08802 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08803
08804
08805
08806
08807
08808 if (p->fake_event) {
08809 res = p->fake_event;
08810 p->fake_event = 0;
08811 } else
08812 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08813
08814 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08815 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08816 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08817 p->owner = p->subs[SUB_REAL].owner;
08818 if (p->owner && ast_bridged_channel(p->owner))
08819 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08820 p->subs[SUB_REAL].needunhold = 1;
08821 }
08822 switch (res) {
08823 case DAHDI_EVENT_ONHOOK:
08824 dahdi_disable_ec(p);
08825 if (p->owner) {
08826 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08827 dahdi_ring_phone(p);
08828 p->callwaitingrepeat = 0;
08829 p->cidcwexpire = 0;
08830 p->cid_suppress_expire = 0;
08831 } else
08832 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08833 update_conf(p);
08834 break;
08835 case DAHDI_EVENT_RINGOFFHOOK:
08836 dahdi_enable_ec(p);
08837 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08838 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08839 p->subs[SUB_REAL].needanswer = 1;
08840 p->dialing = 0;
08841 }
08842 break;
08843 case DAHDI_EVENT_HOOKCOMPLETE:
08844 case DAHDI_EVENT_RINGERON:
08845 case DAHDI_EVENT_RINGEROFF:
08846
08847 break;
08848 case DAHDI_EVENT_WINKFLASH:
08849 p->flashtime = ast_tvnow();
08850 if (p->owner) {
08851 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08852 if (p->owner->_state != AST_STATE_UP) {
08853
08854 usedindex = dahdi_get_index(p->owner, p, 0);
08855 if (usedindex > -1) {
08856 p->subs[usedindex].needanswer = 1;
08857 }
08858 ast_setstate(p->owner, AST_STATE_UP);
08859 }
08860 p->callwaitingrepeat = 0;
08861 p->cidcwexpire = 0;
08862 p->cid_suppress_expire = 0;
08863 if (ast_bridged_channel(p->owner))
08864 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08865 p->subs[SUB_REAL].needunhold = 1;
08866 } else
08867 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08868 update_conf(p);
08869 break;
08870 default:
08871 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08872 }
08873 f = &p->subs[idx].f;
08874 return f;
08875 }
08876 if (!(p->radio || (p->oprmode < 0)))
08877 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08878
08879 if (ast != p->owner) {
08880 if (p->owner) {
08881 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08882 }
08883 f = &p->subs[idx].f;
08884 return f;
08885 }
08886
08887 f = dahdi_handle_event(ast);
08888 if (!f) {
08889 const char *name = ast_strdupa(ast->name);
08890
08891
08892 ast_mutex_unlock(&p->lock);
08893 ast_channel_unlock(ast);
08894 ast_set_hangupsource(ast, name, 0);
08895 ast_channel_lock(ast);
08896 ast_mutex_lock(&p->lock);
08897 }
08898 return f;
08899 }
08900
08901 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08902 {
08903 struct dahdi_pvt *p = ast->tech_pvt;
08904 struct ast_frame *f;
08905 ast_mutex_lock(&p->lock);
08906 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08907 struct analog_pvt *analog_p = p->sig_pvt;
08908 f = analog_exception(analog_p, ast);
08909 } else {
08910 f = __dahdi_exception(ast);
08911 }
08912 ast_mutex_unlock(&p->lock);
08913 return f;
08914 }
08915
08916 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08917 {
08918 struct dahdi_pvt *p;
08919 int res;
08920 int idx;
08921 void *readbuf;
08922 struct ast_frame *f;
08923
08924
08925
08926
08927
08928
08929 p = ast->tech_pvt;
08930 while (ast_mutex_trylock(&p->lock)) {
08931 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08932
08933
08934
08935
08936
08937
08938 p = ast->tech_pvt;
08939 }
08940
08941 idx = dahdi_get_index(ast, p, 0);
08942
08943
08944 if (idx < 0) {
08945 ast_log(LOG_WARNING, "We don't exist?\n");
08946 ast_mutex_unlock(&p->lock);
08947 return NULL;
08948 }
08949
08950 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08951 ast_mutex_unlock(&p->lock);
08952 return NULL;
08953 }
08954
08955 p->subs[idx].f.frametype = AST_FRAME_NULL;
08956 p->subs[idx].f.datalen = 0;
08957 p->subs[idx].f.samples = 0;
08958 p->subs[idx].f.mallocd = 0;
08959 p->subs[idx].f.offset = 0;
08960 p->subs[idx].f.subclass.integer = 0;
08961 p->subs[idx].f.delivery = ast_tv(0,0);
08962 p->subs[idx].f.src = "dahdi_read";
08963 p->subs[idx].f.data.ptr = NULL;
08964
08965
08966 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08967 {
08968 struct dahdi_params ps;
08969
08970 memset(&ps, 0, sizeof(ps));
08971 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08972 ast_mutex_unlock(&p->lock);
08973 return NULL;
08974 }
08975 p->firstradio = 1;
08976 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08977 if (ps.rxisoffhook)
08978 {
08979 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08980 }
08981 else
08982 {
08983 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08984 }
08985 ast_mutex_unlock(&p->lock);
08986 return &p->subs[idx].f;
08987 }
08988 if (p->ringt > 0) {
08989 if (!(--p->ringt)) {
08990 ast_mutex_unlock(&p->lock);
08991 return NULL;
08992 }
08993 }
08994
08995 #ifdef HAVE_OPENR2
08996 if (p->mfcr2) {
08997 openr2_chan_process_event(p->r2chan);
08998 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08999 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
09000
09001
09002 if (p->mfcr2_call_accepted &&
09003 !p->mfcr2_progress &&
09004 ast->_state == AST_STATE_RINGING) {
09005 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
09006 ast_queue_frame(p->owner, &f);
09007 p->mfcr2_progress = 1;
09008 }
09009 }
09010 }
09011 #endif
09012
09013 if (p->subs[idx].needringing) {
09014
09015 p->subs[idx].needringing = 0;
09016 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09017 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
09018 ast_setstate(ast, AST_STATE_RINGING);
09019 ast_mutex_unlock(&p->lock);
09020 return &p->subs[idx].f;
09021 }
09022
09023 if (p->subs[idx].needbusy) {
09024
09025 p->subs[idx].needbusy = 0;
09026 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09027 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
09028 ast_mutex_unlock(&p->lock);
09029 return &p->subs[idx].f;
09030 }
09031
09032 if (p->subs[idx].needcongestion) {
09033
09034 p->subs[idx].needcongestion = 0;
09035 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09036 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
09037 ast_mutex_unlock(&p->lock);
09038 return &p->subs[idx].f;
09039 }
09040
09041 if (p->subs[idx].needanswer) {
09042
09043 p->subs[idx].needanswer = 0;
09044 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09045 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
09046 ast_mutex_unlock(&p->lock);
09047 return &p->subs[idx].f;
09048 }
09049 #ifdef HAVE_OPENR2
09050 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
09051
09052
09053
09054
09055 ast_mutex_unlock(&p->lock);
09056 return &ast_null_frame;
09057 }
09058 #endif
09059
09060 if (p->subs[idx].needflash) {
09061
09062 p->subs[idx].needflash = 0;
09063 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09064 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
09065 ast_mutex_unlock(&p->lock);
09066 return &p->subs[idx].f;
09067 }
09068
09069 if (p->subs[idx].needhold) {
09070
09071 p->subs[idx].needhold = 0;
09072 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09073 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
09074 ast_mutex_unlock(&p->lock);
09075 ast_debug(1, "Sending hold on '%s'\n", ast->name);
09076 return &p->subs[idx].f;
09077 }
09078
09079 if (p->subs[idx].needunhold) {
09080
09081 p->subs[idx].needunhold = 0;
09082 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
09083 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
09084 ast_mutex_unlock(&p->lock);
09085 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
09086 return &p->subs[idx].f;
09087 }
09088
09089
09090
09091
09092
09093 if (p->fake_event && p->owner == ast) {
09094 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09095 struct analog_pvt *analog_p = p->sig_pvt;
09096
09097 f = analog_exception(analog_p, ast);
09098 } else {
09099 f = __dahdi_exception(ast);
09100 }
09101 ast_mutex_unlock(&p->lock);
09102 return f;
09103 }
09104
09105 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
09106 if (!p->subs[idx].linear) {
09107 p->subs[idx].linear = 1;
09108 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09109 if (res)
09110 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
09111 }
09112 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
09113 (ast->rawreadformat == AST_FORMAT_ALAW)) {
09114 if (p->subs[idx].linear) {
09115 p->subs[idx].linear = 0;
09116 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09117 if (res)
09118 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
09119 }
09120 } else {
09121 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
09122 ast_mutex_unlock(&p->lock);
09123 return NULL;
09124 }
09125 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
09126 CHECK_BLOCKING(ast);
09127 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09128 ast_clear_flag(ast, AST_FLAG_BLOCKING);
09129
09130 if (res < 0) {
09131 f = NULL;
09132 if (res == -1) {
09133 if (errno == EAGAIN) {
09134
09135 ast_mutex_unlock(&p->lock);
09136 return &p->subs[idx].f;
09137 } else if (errno == ELAST) {
09138 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09139 struct analog_pvt *analog_p = p->sig_pvt;
09140 f = analog_exception(analog_p, ast);
09141 } else {
09142 f = __dahdi_exception(ast);
09143 }
09144 } else
09145 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
09146 }
09147 ast_mutex_unlock(&p->lock);
09148 return f;
09149 }
09150 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
09151 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
09152 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09153 struct analog_pvt *analog_p = p->sig_pvt;
09154 f = analog_exception(analog_p, ast);
09155 } else {
09156 f = __dahdi_exception(ast);
09157 }
09158 ast_mutex_unlock(&p->lock);
09159 return f;
09160 }
09161 if (p->tdd) {
09162 int c;
09163
09164 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
09165 if (c < 0) {
09166 ast_debug(1,"tdd_feed failed\n");
09167 ast_mutex_unlock(&p->lock);
09168 return NULL;
09169 }
09170 if (c) {
09171 p->subs[idx].f.subclass.integer = 0;
09172 p->subs[idx].f.frametype = AST_FRAME_TEXT;
09173 p->subs[idx].f.mallocd = 0;
09174 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09175 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
09176 p->subs[idx].f.datalen = 1;
09177 *((char *) p->subs[idx].f.data.ptr) = c;
09178 ast_mutex_unlock(&p->lock);
09179 return &p->subs[idx].f;
09180 }
09181 }
09182 if (idx == SUB_REAL) {
09183
09184 if (p->cidcwexpire) {
09185 if (!--p->cidcwexpire) {
09186
09187 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
09188 restore_conference(p);
09189 }
09190 }
09191 if (p->cid_suppress_expire) {
09192 --p->cid_suppress_expire;
09193 }
09194 if (p->callwaitingrepeat) {
09195 if (!--p->callwaitingrepeat) {
09196
09197 ++p->callwaitrings;
09198 dahdi_callwait(ast);
09199 }
09200 }
09201 }
09202 if (p->subs[idx].linear) {
09203 p->subs[idx].f.datalen = READ_SIZE * 2;
09204 } else
09205 p->subs[idx].f.datalen = READ_SIZE;
09206
09207
09208 if ((p->owner == ast) && p->cidspill) {
09209 send_callerid(p);
09210 }
09211
09212 p->subs[idx].f.frametype = AST_FRAME_VOICE;
09213 p->subs[idx].f.subclass.codec = ast->rawreadformat;
09214 p->subs[idx].f.samples = READ_SIZE;
09215 p->subs[idx].f.mallocd = 0;
09216 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
09217 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
09218 #if 0
09219 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
09220 #endif
09221 if (p->dialing || p->radio ||
09222 (idx && (ast->_state != AST_STATE_UP)) ||
09223 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
09224 ) {
09225
09226
09227 p->subs[idx].f.frametype = AST_FRAME_NULL;
09228 p->subs[idx].f.subclass.integer = 0;
09229 p->subs[idx].f.samples = 0;
09230 p->subs[idx].f.mallocd = 0;
09231 p->subs[idx].f.offset = 0;
09232 p->subs[idx].f.data.ptr = NULL;
09233 p->subs[idx].f.datalen= 0;
09234 }
09235 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
09236
09237 int mute;
09238
09239 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
09240
09241
09242 mute = ast_dsp_was_muted(p->dsp);
09243 if (p->muting != mute) {
09244 p->muting = mute;
09245 dahdi_confmute(p, mute);
09246 }
09247
09248 if (f) {
09249 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
09250 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
09251
09252
09253 ast_frfree(f);
09254 f = NULL;
09255 }
09256 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
09257 || f->frametype == AST_FRAME_DTMF_END) {
09258 #ifdef HAVE_PRI
09259 if (dahdi_sig_pri_lib_handles(p->sig)
09260 && ((struct sig_pri_chan *) p->sig_pvt)->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING
09261 && p->pri
09262 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
09263 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
09264
09265 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
09266 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
09267 f->subclass.integer, f->subclass.integer, ast->name);
09268
09269 f->frametype = AST_FRAME_NULL;
09270 f->subclass.integer = 0;
09271 }
09272 #endif
09273
09274 p->pulsedial = 0;
09275 } else if (p->waitingfordt.tv_sec) {
09276 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
09277 p->waitingfordt.tv_sec = 0;
09278 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
09279 ast_frfree(f);
09280 f = NULL;
09281 } else if (f->frametype == AST_FRAME_VOICE) {
09282 f->frametype = AST_FRAME_NULL;
09283 f->subclass.integer = 0;
09284 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) {
09285 p->waitingfordt.tv_sec = 0;
09286 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
09287 ast_dsp_set_features(p->dsp, p->dsp_features);
09288 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
09289 if (!ast_strlen_zero(p->dop.dialstr)) {
09290 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
09291 if (res < 0) {
09292 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
09293 p->dop.dialstr[0] = '\0';
09294 ast_mutex_unlock(&p->lock);
09295 ast_frfree(f);
09296 return NULL;
09297 } else {
09298 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
09299 p->dialing = 1;
09300 p->dop.dialstr[0] = '\0';
09301 p->dop.op = DAHDI_DIAL_OP_REPLACE;
09302 ast_setstate(ast, AST_STATE_DIALING);
09303 }
09304 }
09305 }
09306 }
09307 }
09308 }
09309 } else
09310 f = &p->subs[idx].f;
09311
09312 if (f) {
09313 switch (f->frametype) {
09314 case AST_FRAME_DTMF_BEGIN:
09315 case AST_FRAME_DTMF_END:
09316 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09317 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09318 } else {
09319 dahdi_handle_dtmf(ast, idx, &f);
09320 }
09321 break;
09322 case AST_FRAME_VOICE:
09323 if (p->cidspill || p->cid_suppress_expire) {
09324
09325 p->subs[idx].f.frametype = AST_FRAME_NULL;
09326 p->subs[idx].f.subclass.integer = 0;
09327 p->subs[idx].f.samples = 0;
09328 p->subs[idx].f.mallocd = 0;
09329 p->subs[idx].f.offset = 0;
09330 p->subs[idx].f.data.ptr = NULL;
09331 p->subs[idx].f.datalen= 0;
09332 }
09333 break;
09334 default:
09335 break;
09336 }
09337 }
09338
09339 ast_mutex_unlock(&p->lock);
09340 return f;
09341 }
09342
09343 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09344 {
09345 int sent=0;
09346 int size;
09347 int res;
09348 int fd;
09349 fd = p->subs[idx].dfd;
09350 while (len) {
09351 size = len;
09352 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09353 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09354 res = write(fd, buf, size);
09355 if (res != size) {
09356 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09357 return sent;
09358 }
09359 len -= size;
09360 buf += size;
09361 }
09362 return sent;
09363 }
09364
09365 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09366 {
09367 struct dahdi_pvt *p = ast->tech_pvt;
09368 int res;
09369 int idx;
09370 idx = dahdi_get_index(ast, p, 0);
09371 if (idx < 0) {
09372 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09373 return -1;
09374 }
09375
09376
09377 if (frame->frametype != AST_FRAME_VOICE) {
09378 if (frame->frametype != AST_FRAME_IMAGE)
09379 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09380 return 0;
09381 }
09382 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09383 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09384 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09385 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09386 return -1;
09387 }
09388 if (p->dialing) {
09389 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09390 return 0;
09391 }
09392 if (!p->owner) {
09393 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09394 return 0;
09395 }
09396 if (p->cidspill) {
09397 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09398 ast->name);
09399 return 0;
09400 }
09401
09402 if (!frame->data.ptr || !frame->datalen)
09403 return 0;
09404
09405 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09406 if (!p->subs[idx].linear) {
09407 p->subs[idx].linear = 1;
09408 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09409 if (res)
09410 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09411 }
09412 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09413 } else {
09414
09415 if (p->subs[idx].linear) {
09416 p->subs[idx].linear = 0;
09417 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09418 if (res)
09419 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09420 }
09421 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09422 }
09423 if (res < 0) {
09424 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09425 return -1;
09426 }
09427 return 0;
09428 }
09429
09430 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09431 {
09432 struct dahdi_pvt *p = chan->tech_pvt;
09433 int res=-1;
09434 int idx;
09435 int func = DAHDI_FLASH;
09436
09437 ast_mutex_lock(&p->lock);
09438 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09439 switch (p->sig) {
09440 #if defined(HAVE_PRI)
09441 case SIG_PRI_LIB_HANDLE_CASES:
09442 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09443 ast_mutex_unlock(&p->lock);
09444 return res;
09445 #endif
09446 #if defined(HAVE_SS7)
09447 case SIG_SS7:
09448 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09449 ast_mutex_unlock(&p->lock);
09450 return res;
09451 #endif
09452 default:
09453 break;
09454 }
09455 #ifdef HAVE_OPENR2
09456 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09457 ast_mutex_unlock(&p->lock);
09458
09459
09460 return 0;
09461 }
09462 #endif
09463 idx = dahdi_get_index(chan, p, 0);
09464 if (idx == SUB_REAL) {
09465 switch (condition) {
09466 case AST_CONTROL_BUSY:
09467 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09468 break;
09469 case AST_CONTROL_RINGING:
09470 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09471
09472 if (chan->_state != AST_STATE_UP) {
09473 if ((chan->_state != AST_STATE_RING) ||
09474 ((p->sig != SIG_FXSKS) &&
09475 (p->sig != SIG_FXSLS) &&
09476 (p->sig != SIG_FXSGS)))
09477 ast_setstate(chan, AST_STATE_RINGING);
09478 }
09479 break;
09480 case AST_CONTROL_INCOMPLETE:
09481 ast_debug(1, "Received AST_CONTROL_INCOMPLETE on %s\n", chan->name);
09482
09483 res = 0;
09484 break;
09485 case AST_CONTROL_PROCEEDING:
09486 ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n", chan->name);
09487
09488 res = 0;
09489 break;
09490 case AST_CONTROL_PROGRESS:
09491 ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n", chan->name);
09492
09493 res = 0;
09494 break;
09495 case AST_CONTROL_CONGESTION:
09496
09497 switch (chan->hangupcause) {
09498 case AST_CAUSE_USER_BUSY:
09499 case AST_CAUSE_NORMAL_CLEARING:
09500 case 0:
09501
09502 chan->hangupcause = AST_CAUSE_CONGESTION;
09503 break;
09504 default:
09505 break;
09506 }
09507 break;
09508 case AST_CONTROL_HOLD:
09509 ast_moh_start(chan, data, p->mohinterpret);
09510 break;
09511 case AST_CONTROL_UNHOLD:
09512 ast_moh_stop(chan);
09513 break;
09514 case AST_CONTROL_RADIO_KEY:
09515 if (p->radio)
09516 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09517 res = 0;
09518 break;
09519 case AST_CONTROL_RADIO_UNKEY:
09520 if (p->radio)
09521 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09522 res = 0;
09523 break;
09524 case AST_CONTROL_FLASH:
09525
09526 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09527
09528 p->dop.dialstr[0] = '\0';
09529 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09530 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09531 chan->name, strerror(errno));
09532 } else
09533 res = 0;
09534 } else
09535 res = 0;
09536 break;
09537 case AST_CONTROL_SRCUPDATE:
09538 res = 0;
09539 break;
09540 case -1:
09541 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09542 break;
09543 }
09544 } else {
09545 res = 0;
09546 }
09547 ast_mutex_unlock(&p->lock);
09548 return res;
09549 }
09550
09551 #if defined(HAVE_PRI)
09552 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09553 #else
09554 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09555 #endif
09556 {
09557 struct ast_str *chan_name;
09558 int x, y;
09559
09560
09561 if (!(chan_name = ast_str_create(32))) {
09562 return NULL;
09563 }
09564 if (i->channel == CHAN_PSEUDO) {
09565 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09566 #if defined(HAVE_PRI)
09567 } else if (i->pri) {
09568 ast_mutex_lock(&i->pri->lock);
09569 y = ++i->pri->new_chan_seq;
09570 if (is_outgoing) {
09571 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09572 address[0] = '\0';
09573 } else if (ast_strlen_zero(i->cid_subaddr)) {
09574
09575 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09576 } else {
09577
09578 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09579 i->cid_subaddr, y);
09580 }
09581 ast_mutex_unlock(&i->pri->lock);
09582 #endif
09583 } else {
09584 y = 1;
09585 do {
09586 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09587 for (x = 0; x < 3; ++x) {
09588 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09589 i->subs[x].owner->name + 6)) {
09590 break;
09591 }
09592 }
09593 ++y;
09594 } while (x < 3);
09595 }
09596 return chan_name;
09597 }
09598
09599 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09600 {
09601 struct ast_channel *tmp;
09602 format_t deflaw;
09603 int x;
09604 int features;
09605 struct ast_str *chan_name;
09606 struct ast_variable *v;
09607 char *dashptr;
09608 char device_name[AST_CHANNEL_NAME];
09609
09610 if (i->subs[idx].owner) {
09611 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09612 return NULL;
09613 }
09614
09615 #if defined(HAVE_PRI)
09616
09617
09618
09619
09620 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09621 #else
09622 chan_name = create_channel_name(i);
09623 #endif
09624 if (!chan_name) {
09625 return NULL;
09626 }
09627
09628 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));
09629 ast_free(chan_name);
09630 if (!tmp)
09631 return NULL;
09632 tmp->tech = &dahdi_tech;
09633 #if defined(HAVE_PRI)
09634 if (i->pri) {
09635 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09636 }
09637 #endif
09638 ast_channel_cc_params_init(tmp, i->cc_params);
09639 if (law) {
09640 i->law = law;
09641 if (law == DAHDI_LAW_ALAW) {
09642 deflaw = AST_FORMAT_ALAW;
09643 } else {
09644 deflaw = AST_FORMAT_ULAW;
09645 }
09646 } else {
09647 switch (i->sig) {
09648 case SIG_PRI_LIB_HANDLE_CASES:
09649
09650 i->law = (i->law_default == DAHDI_LAW_ALAW)
09651 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09652 break;
09653 default:
09654 i->law = i->law_default;
09655 break;
09656 }
09657 if (i->law_default == DAHDI_LAW_ALAW) {
09658 deflaw = AST_FORMAT_ALAW;
09659 } else {
09660 deflaw = AST_FORMAT_ULAW;
09661 }
09662 }
09663 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09664 tmp->nativeformats = deflaw;
09665
09666 tmp->rawreadformat = deflaw;
09667 tmp->readformat = deflaw;
09668 tmp->rawwriteformat = deflaw;
09669 tmp->writeformat = deflaw;
09670 i->subs[idx].linear = 0;
09671 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09672 features = 0;
09673 if (idx == SUB_REAL) {
09674 if (i->busydetect && CANBUSYDETECT(i))
09675 features |= DSP_FEATURE_BUSY_DETECT;
09676 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09677 features |= DSP_FEATURE_CALL_PROGRESS;
09678 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09679 features |= DSP_FEATURE_WAITDIALTONE;
09680 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09681 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09682 features |= DSP_FEATURE_FAX_DETECT;
09683 }
09684 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09685 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09686 i->hardwaredtmf = 0;
09687 features |= DSP_FEATURE_DIGIT_DETECT;
09688 } else if (NEED_MFDETECT(i)) {
09689 i->hardwaredtmf = 1;
09690 features |= DSP_FEATURE_DIGIT_DETECT;
09691 }
09692 }
09693 if (features) {
09694 if (i->dsp) {
09695 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09696 } else {
09697 if (i->channel != CHAN_PSEUDO)
09698 i->dsp = ast_dsp_new();
09699 else
09700 i->dsp = NULL;
09701 if (i->dsp) {
09702 i->dsp_features = features;
09703 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09704
09705 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09706
09707
09708 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09709 features = 0;
09710 }
09711 #endif
09712 ast_dsp_set_features(i->dsp, features);
09713 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09714 if (!ast_strlen_zero(progzone))
09715 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09716 if (i->busydetect && CANBUSYDETECT(i)) {
09717 ast_dsp_set_busy_count(i->dsp, i->busycount);
09718 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09719 }
09720 }
09721 }
09722 }
09723
09724 if (state == AST_STATE_RING)
09725 tmp->rings = 1;
09726 tmp->tech_pvt = i;
09727 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09728
09729 tmp->callgroup = i->callgroup;
09730 tmp->pickupgroup = i->pickupgroup;
09731 }
09732 if (!ast_strlen_zero(i->parkinglot))
09733 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09734 if (!ast_strlen_zero(i->language))
09735 ast_string_field_set(tmp, language, i->language);
09736 if (!i->owner)
09737 i->owner = tmp;
09738 if (!ast_strlen_zero(i->accountcode))
09739 ast_string_field_set(tmp, accountcode, i->accountcode);
09740 if (i->amaflags)
09741 tmp->amaflags = i->amaflags;
09742 i->subs[idx].owner = tmp;
09743 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09744 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09745 ast_string_field_set(tmp, call_forward, i->call_forward);
09746 }
09747
09748 if (!i->adsi)
09749 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09750 if (!ast_strlen_zero(i->exten))
09751 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09752 if (!ast_strlen_zero(i->rdnis)) {
09753 tmp->redirecting.from.number.valid = 1;
09754 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09755 }
09756 if (!ast_strlen_zero(i->dnid)) {
09757 tmp->dialed.number.str = ast_strdup(i->dnid);
09758 }
09759
09760
09761
09762 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09763 if (!ast_strlen_zero(i->cid_ani)) {
09764 tmp->caller.ani.number.valid = 1;
09765 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09766 } else if (!ast_strlen_zero(i->cid_num)) {
09767 tmp->caller.ani.number.valid = 1;
09768 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09769 }
09770 #else
09771 if (!ast_strlen_zero(i->cid_num)) {
09772 tmp->caller.ani.number.valid = 1;
09773 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09774 }
09775 #endif
09776 tmp->caller.id.name.presentation = i->callingpres;
09777 tmp->caller.id.number.presentation = i->callingpres;
09778 tmp->caller.id.number.plan = i->cid_ton;
09779 tmp->caller.ani2 = i->cid_ani2;
09780 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09781
09782 i->fake_event = 0;
09783
09784 dahdi_confmute(i, 0);
09785 i->muting = 0;
09786
09787 ast_jb_configure(tmp, &global_jbconf);
09788
09789
09790 ast_copy_string(device_name, tmp->name, sizeof(device_name));
09791 dashptr = strrchr(device_name, '-');
09792 if (dashptr) {
09793 *dashptr = '\0';
09794 }
09795 ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name);
09796
09797 for (v = i->vars ; v ; v = v->next)
09798 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09799
09800 ast_module_ref(ast_module_info->self);
09801
09802 dahdi_ami_channel_event(i, tmp);
09803 if (startpbx) {
09804 #ifdef HAVE_OPENR2
09805 if (i->mfcr2call) {
09806 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09807 }
09808 #endif
09809 if (ast_pbx_start(tmp)) {
09810 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09811 ast_hangup(tmp);
09812 return NULL;
09813 }
09814 }
09815 return tmp;
09816 }
09817
09818
09819 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09820 {
09821 char c;
09822
09823 *str = 0;
09824 for (;;)
09825 {
09826
09827 c = ast_waitfordigit(chan, ms);
09828
09829 if (c < 1)
09830 return c;
09831 *str++ = c;
09832 *str = 0;
09833 if (strchr(term, c))
09834 return 1;
09835 }
09836 }
09837
09838 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09839 {
09840 int j;
09841 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09842 for (;;)
09843 {
09844
09845 j = DAHDI_IOMUX_SIGEVENT;
09846
09847 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09848
09849 if (j & DAHDI_IOMUX_SIGEVENT) break;
09850 }
09851
09852 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09853 return 0;
09854 }
09855
09856
09857
09858
09859
09860
09861
09862
09863
09864
09865 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09866 {
09867 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09868 return analog_dnd(dahdichan->sig_pvt, flag);
09869 }
09870
09871 if (flag == -1) {
09872 return dahdichan->dnd;
09873 }
09874
09875
09876 dahdichan->dnd = flag;
09877 ast_verb(3, "%s DND on channel %d\n",
09878 flag? "Enabled" : "Disabled",
09879 dahdichan->channel);
09880 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09881 "Channel: DAHDI/%d\r\n"
09882 "Status: %s\r\n", dahdichan->channel,
09883 flag? "enabled" : "disabled");
09884
09885 return 0;
09886 }
09887
09888 static int canmatch_featurecode(const char *exten)
09889 {
09890 int extlen = strlen(exten);
09891 const char *pickup_ext;
09892 if (!extlen) {
09893 return 1;
09894 }
09895 pickup_ext = ast_pickup_ext();
09896 if (extlen < strlen(pickup_ext) && !strncmp(pickup_ext, exten, extlen)) {
09897 return 1;
09898 }
09899
09900 if (exten[0] == '*' && extlen < 3) {
09901 if (extlen == 1) {
09902 return 1;
09903 }
09904
09905 switch (exten[1]) {
09906 case '6':
09907 case '7':
09908 case '8':
09909 return 1;
09910 }
09911 }
09912 return 0;
09913 }
09914
09915 static void *analog_ss_thread(void *data)
09916 {
09917 struct ast_channel *chan = data;
09918 struct dahdi_pvt *p = chan->tech_pvt;
09919 char exten[AST_MAX_EXTENSION] = "";
09920 char exten2[AST_MAX_EXTENSION] = "";
09921 unsigned char buf[256];
09922 char dtmfcid[300];
09923 char dtmfbuf[300];
09924 struct callerid_state *cs = NULL;
09925 char *name = NULL, *number = NULL;
09926 int distMatches;
09927 int curRingData[3];
09928 int receivedRingT;
09929 int counter1;
09930 int counter;
09931 int samples = 0;
09932 struct ast_smdi_md_message *smdi_msg = NULL;
09933 int flags = 0;
09934 int i;
09935 int timeout;
09936 int getforward = 0;
09937 char *s1, *s2;
09938 int len = 0;
09939 int res;
09940 int idx;
09941
09942 ast_mutex_lock(&ss_thread_lock);
09943 ss_thread_count++;
09944 ast_mutex_unlock(&ss_thread_lock);
09945
09946
09947
09948 if (!p) {
09949 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09950 ast_hangup(chan);
09951 goto quit;
09952 }
09953 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09954 idx = dahdi_get_index(chan, p, 1);
09955 if (idx < 0) {
09956 ast_log(LOG_WARNING, "Huh?\n");
09957 ast_hangup(chan);
09958 goto quit;
09959 }
09960 if (p->dsp)
09961 ast_dsp_digitreset(p->dsp);
09962 switch (p->sig) {
09963 case SIG_FEATD:
09964 case SIG_FEATDMF:
09965 case SIG_FEATDMF_TA:
09966 case SIG_E911:
09967 case SIG_FGC_CAMAMF:
09968 case SIG_FEATB:
09969 case SIG_EMWINK:
09970 case SIG_SF_FEATD:
09971 case SIG_SF_FEATDMF:
09972 case SIG_SF_FEATB:
09973 case SIG_SFWINK:
09974 if (dahdi_wink(p, idx))
09975 goto quit;
09976
09977 case SIG_EM:
09978 case SIG_EM_E1:
09979 case SIG_SF:
09980 case SIG_FGC_CAMA:
09981 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09982 if (p->dsp)
09983 ast_dsp_digitreset(p->dsp);
09984
09985 if (p->dsp) {
09986 if (NEED_MFDETECT(p))
09987 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09988 else
09989 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09990 }
09991 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09992
09993 if (!p->immediate)
09994
09995 res = ast_waitfordigit(chan, 5000);
09996 else
09997 res = 0;
09998 if (res > 0) {
09999
10000 dtmfbuf[0] = res;
10001 switch (p->sig) {
10002 case SIG_FEATD:
10003 case SIG_SF_FEATD:
10004 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10005 if (res > 0)
10006 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10007 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10008 break;
10009 case SIG_FEATDMF_TA:
10010 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10011 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10012 if (dahdi_wink(p, idx)) goto quit;
10013 dtmfbuf[0] = 0;
10014
10015 res = ast_waitfordigit(chan, 5000);
10016 if (res <= 0) break;
10017 dtmfbuf[0] = res;
10018
10019 case SIG_FEATDMF:
10020 case SIG_E911:
10021 case SIG_FGC_CAMAMF:
10022 case SIG_SF_FEATDMF:
10023 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10024
10025 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
10026 {
10027 if (dahdi_wink(p, idx)) goto quit;
10028 dtmfbuf[0] = 0;
10029
10030 res = ast_waitfordigit(chan, 5000);
10031 if (res <= 0) break;
10032 dtmfbuf[0] = res;
10033 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10034 }
10035 if (res > 0) {
10036
10037 if (p->sig == SIG_E911)
10038 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10039 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
10040 }
10041 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10042 break;
10043 case SIG_FEATB:
10044 case SIG_SF_FEATB:
10045 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
10046 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10047 break;
10048 case SIG_EMWINK:
10049
10050
10051
10052
10053 if (res == '*') {
10054 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
10055 if (res > 0)
10056 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
10057 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
10058 break;
10059 }
10060 default:
10061
10062 len = 1;
10063 dtmfbuf[len] = '\0';
10064 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10065 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
10066 timeout = matchdigittimeout;
10067 } else {
10068 timeout = gendigittimeout;
10069 }
10070 res = ast_waitfordigit(chan, timeout);
10071 if (res < 0) {
10072 ast_debug(1, "waitfordigit returned < 0...\n");
10073 ast_hangup(chan);
10074 goto quit;
10075 } else if (res) {
10076 dtmfbuf[len++] = res;
10077 dtmfbuf[len] = '\0';
10078 } else {
10079 break;
10080 }
10081 }
10082 break;
10083 }
10084 }
10085 if (res == -1) {
10086 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
10087 ast_hangup(chan);
10088 goto quit;
10089 } else if (res < 0) {
10090 ast_debug(1, "Got hung up before digits finished\n");
10091 ast_hangup(chan);
10092 goto quit;
10093 }
10094
10095 if (p->sig == SIG_FGC_CAMA) {
10096 char anibuf[100];
10097
10098 if (ast_safe_sleep(chan,1000) == -1) {
10099 ast_hangup(chan);
10100 goto quit;
10101 }
10102 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10103 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
10104 res = my_getsigstr(chan, anibuf, "#", 10000);
10105 if ((res > 0) && (strlen(anibuf) > 2)) {
10106 if (anibuf[strlen(anibuf) - 1] == '#')
10107 anibuf[strlen(anibuf) - 1] = 0;
10108 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
10109 }
10110 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10111 }
10112
10113 ast_copy_string(exten, dtmfbuf, sizeof(exten));
10114 if (ast_strlen_zero(exten))
10115 ast_copy_string(exten, "s", sizeof(exten));
10116 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
10117
10118 if (exten[0] == '*') {
10119 char *stringp=NULL;
10120 ast_copy_string(exten2, exten, sizeof(exten2));
10121
10122 stringp=exten2 +1;
10123 s1 = strsep(&stringp, "*");
10124 s2 = strsep(&stringp, "*");
10125 if (s2) {
10126 if (!ast_strlen_zero(p->cid_num))
10127 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10128 else
10129 ast_set_callerid(chan, s1, NULL, s1);
10130 ast_copy_string(exten, s2, sizeof(exten));
10131 } else
10132 ast_copy_string(exten, s1, sizeof(exten));
10133 } else if (p->sig == SIG_FEATD)
10134 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10135 }
10136 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10137 if (exten[0] == '*') {
10138 char *stringp=NULL;
10139 ast_copy_string(exten2, exten, sizeof(exten2));
10140
10141 stringp=exten2 +1;
10142 s1 = strsep(&stringp, "#");
10143 s2 = strsep(&stringp, "#");
10144 if (s2) {
10145 if (!ast_strlen_zero(p->cid_num))
10146 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10147 else
10148 if (*(s1 + 2))
10149 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
10150 ast_copy_string(exten, s2 + 1, sizeof(exten));
10151 } else
10152 ast_copy_string(exten, s1 + 2, sizeof(exten));
10153 } else
10154 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
10155 }
10156 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
10157 if (exten[0] == '*') {
10158 char *stringp=NULL;
10159 ast_copy_string(exten2, exten, sizeof(exten2));
10160
10161 stringp=exten2 +1;
10162 s1 = strsep(&stringp, "#");
10163 s2 = strsep(&stringp, "#");
10164 if (s2 && (*(s2 + 1) == '0')) {
10165 if (*(s2 + 2))
10166 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
10167 }
10168 if (s1) ast_copy_string(exten, s1, sizeof(exten));
10169 else ast_copy_string(exten, "911", sizeof(exten));
10170 } else
10171 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
10172 }
10173 if (p->sig == SIG_FEATB) {
10174 if (exten[0] == '*') {
10175 char *stringp=NULL;
10176 ast_copy_string(exten2, exten, sizeof(exten2));
10177
10178 stringp=exten2 +1;
10179 s1 = strsep(&stringp, "#");
10180 ast_copy_string(exten, exten2 + 1, sizeof(exten));
10181 } else
10182 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
10183 }
10184 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
10185 dahdi_wink(p, idx);
10186
10187
10188
10189 if (ast_safe_sleep(chan, 100)) {
10190 ast_hangup(chan);
10191 goto quit;
10192 }
10193 }
10194 dahdi_enable_ec(p);
10195 if (NEED_MFDETECT(p)) {
10196 if (p->dsp) {
10197 if (!p->hardwaredtmf)
10198 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
10199 else {
10200 ast_dsp_free(p->dsp);
10201 p->dsp = NULL;
10202 }
10203 }
10204 }
10205
10206 if (ast_exists_extension(chan, chan->context, exten, 1,
10207 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10208 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10209 if (p->dsp) ast_dsp_digitreset(p->dsp);
10210 res = ast_pbx_run(chan);
10211 if (res) {
10212 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10213 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10214 }
10215 goto quit;
10216 } else {
10217 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
10218 sleep(2);
10219 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
10220 if (res < 0)
10221 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
10222 else
10223 sleep(1);
10224 res = ast_streamfile(chan, "ss-noservice", chan->language);
10225 if (res >= 0)
10226 ast_waitstream(chan, "");
10227 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10228 ast_hangup(chan);
10229 goto quit;
10230 }
10231 break;
10232 case SIG_FXOLS:
10233 case SIG_FXOGS:
10234 case SIG_FXOKS:
10235
10236 timeout = firstdigittimeout;
10237
10238
10239 if (p->subs[SUB_THREEWAY].owner)
10240 timeout = 999999;
10241 while (len < AST_MAX_EXTENSION-1) {
10242
10243
10244 if (p->immediate)
10245 res = 's';
10246 else
10247 res = ast_waitfordigit(chan, timeout);
10248 timeout = 0;
10249 if (res < 0) {
10250 ast_debug(1, "waitfordigit returned < 0...\n");
10251 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10252 ast_hangup(chan);
10253 goto quit;
10254 } else if (res) {
10255 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
10256 exten[len++]=res;
10257 exten[len] = '\0';
10258 }
10259 if (!ast_ignore_pattern(chan->context, exten))
10260 tone_zone_play_tone(p->subs[idx].dfd, -1);
10261 else
10262 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10263 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
10264 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
10265 if (getforward) {
10266
10267 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
10268 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
10269 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10270 if (res)
10271 break;
10272 usleep(500000);
10273 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10274 sleep(1);
10275 memset(exten, 0, sizeof(exten));
10276 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
10277 len = 0;
10278 getforward = 0;
10279 } else {
10280 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
10281 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
10282 if (!ast_strlen_zero(p->cid_num)) {
10283 if (!p->hidecallerid)
10284 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
10285 else
10286 ast_set_callerid(chan, NULL, NULL, p->cid_num);
10287 }
10288 if (!ast_strlen_zero(p->cid_name)) {
10289 if (!p->hidecallerid)
10290 ast_set_callerid(chan, NULL, p->cid_name, NULL);
10291 }
10292 ast_setstate(chan, AST_STATE_RING);
10293 dahdi_enable_ec(p);
10294 res = ast_pbx_run(chan);
10295 if (res) {
10296 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10297 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10298 }
10299 goto quit;
10300 }
10301 } else {
10302
10303
10304 timeout = matchdigittimeout;
10305 }
10306 } else if (res == 0) {
10307 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
10308 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10309 dahdi_wait_event(p->subs[idx].dfd);
10310 ast_hangup(chan);
10311 goto quit;
10312 } else if (p->callwaiting && !strcmp(exten, "*70")) {
10313 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
10314
10315 p->callwaiting = 0;
10316 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10317 if (res) {
10318 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10319 chan->name, strerror(errno));
10320 }
10321 len = 0;
10322 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
10323 memset(exten, 0, sizeof(exten));
10324 timeout = firstdigittimeout;
10325
10326 } else if (!strcmp(exten,ast_pickup_ext())) {
10327
10328
10329
10330
10331 if (idx == SUB_REAL) {
10332
10333 if (p->subs[SUB_THREEWAY].owner) {
10334
10335
10336 alloc_sub(p, SUB_CALLWAIT);
10337 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
10338 unalloc_sub(p, SUB_THREEWAY);
10339 }
10340 dahdi_enable_ec(p);
10341 if (ast_pickup_call(chan)) {
10342 ast_debug(1, "No call pickup possible...\n");
10343 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10344 dahdi_wait_event(p->subs[idx].dfd);
10345 }
10346 ast_hangup(chan);
10347 goto quit;
10348 } else {
10349 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
10350 ast_hangup(chan);
10351 goto quit;
10352 }
10353
10354 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10355 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10356
10357 p->hidecallerid = 1;
10358 ast_party_number_free(&chan->caller.id.number);
10359 ast_party_number_init(&chan->caller.id.number);
10360 ast_party_name_free(&chan->caller.id.name);
10361 ast_party_name_init(&chan->caller.id.name);
10362 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10363 if (res) {
10364 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10365 chan->name, strerror(errno));
10366 }
10367 len = 0;
10368 memset(exten, 0, sizeof(exten));
10369 timeout = firstdigittimeout;
10370 } else if (p->callreturn && !strcmp(exten, "*69")) {
10371 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10372 break;
10373 } else if (!strcmp(exten, "*78")) {
10374 dahdi_dnd(p, 1);
10375
10376 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10377 getforward = 0;
10378 memset(exten, 0, sizeof(exten));
10379 len = 0;
10380 } else if (!strcmp(exten, "*79")) {
10381 dahdi_dnd(p, 0);
10382
10383 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10384 getforward = 0;
10385 memset(exten, 0, sizeof(exten));
10386 len = 0;
10387 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10388 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10389 getforward = 1;
10390 memset(exten, 0, sizeof(exten));
10391 len = 0;
10392 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10393 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10394 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10395 memset(p->call_forward, 0, sizeof(p->call_forward));
10396 getforward = 0;
10397 memset(exten, 0, sizeof(exten));
10398 len = 0;
10399 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10400 p->subs[SUB_THREEWAY].owner &&
10401 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10402
10403
10404 ast_masq_park_call_exten(ast_bridged_channel(p->subs[SUB_THREEWAY].owner),
10405 chan, exten, chan->context, 0, NULL);
10406 ast_verb(3, "Parking call to '%s'\n", chan->name);
10407 break;
10408 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10409 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10410
10411 p->hidecallerid = 0;
10412 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10413 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10414 if (res) {
10415 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10416 chan->name, strerror(errno));
10417 }
10418 len = 0;
10419 memset(exten, 0, sizeof(exten));
10420 timeout = firstdigittimeout;
10421 } else if (!strcmp(exten, "*0")) {
10422 struct ast_channel *nbridge =
10423 p->subs[SUB_THREEWAY].owner;
10424 struct dahdi_pvt *pbridge = NULL;
10425
10426 if (nbridge && ast_bridged_channel(nbridge))
10427 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10428 if (nbridge && pbridge &&
10429 (nbridge->tech == &dahdi_tech) &&
10430 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10431 ISTRUNK(pbridge)) {
10432 int func = DAHDI_FLASH;
10433
10434 p->dop.dialstr[0] = '\0';
10435
10436 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10437 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10438 nbridge->name, strerror(errno));
10439 }
10440 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10441 unalloc_sub(p, SUB_THREEWAY);
10442 p->owner = p->subs[SUB_REAL].owner;
10443 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10444 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10445 ast_hangup(chan);
10446 goto quit;
10447 } else {
10448 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10449 dahdi_wait_event(p->subs[idx].dfd);
10450 tone_zone_play_tone(p->subs[idx].dfd, -1);
10451 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10452 unalloc_sub(p, SUB_THREEWAY);
10453 p->owner = p->subs[SUB_REAL].owner;
10454 ast_hangup(chan);
10455 goto quit;
10456 }
10457 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10458 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10459 && !canmatch_featurecode(exten)) {
10460 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10461 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10462 chan->context);
10463 break;
10464 }
10465 if (!timeout)
10466 timeout = gendigittimeout;
10467 if (len && !ast_ignore_pattern(chan->context, exten))
10468 tone_zone_play_tone(p->subs[idx].dfd, -1);
10469 }
10470 break;
10471 case SIG_FXSLS:
10472 case SIG_FXSGS:
10473 case SIG_FXSKS:
10474
10475 if (p->use_smdi && p->smdi_iface) {
10476 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10477
10478 if (smdi_msg != NULL) {
10479 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10480
10481 if (smdi_msg->type == 'B')
10482 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10483 else if (smdi_msg->type == 'N')
10484 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10485
10486 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10487 } else {
10488 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10489 }
10490 }
10491
10492 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10493 number = smdi_msg->calling_st;
10494
10495
10496
10497
10498 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10499 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10500
10501 if (p->cid_signalling == CID_SIG_DTMF) {
10502 int k = 0;
10503 cs = NULL;
10504 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10505 dahdi_setlinear(p->subs[idx].dfd, 0);
10506
10507
10508
10509
10510
10511
10512 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10513 res = 4000;
10514 for (;;) {
10515 struct ast_frame *f;
10516 res = ast_waitfor(chan, res);
10517 if (res <= 0) {
10518
10519
10520
10521
10522
10523 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10524 "Exiting simple switch\n");
10525 ast_hangup(chan);
10526 goto quit;
10527 }
10528 f = ast_read(chan);
10529 if (!f)
10530 break;
10531 if (f->frametype == AST_FRAME_DTMF) {
10532 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10533 dtmfbuf[k++] = f->subclass.integer;
10534 }
10535 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10536 res = 4000;
10537 }
10538 ast_frfree(f);
10539 if (chan->_state == AST_STATE_RING ||
10540 chan->_state == AST_STATE_RINGING)
10541 break;
10542 }
10543 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10544 dtmfbuf[k] = '\0';
10545 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10546
10547 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10548 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10549 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10550
10551 if (!ast_strlen_zero(dtmfcid))
10552 number = dtmfcid;
10553 else
10554 number = NULL;
10555
10556 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10557 cs = callerid_new(p->cid_signalling);
10558 if (cs) {
10559 samples = 0;
10560 #if 1
10561 bump_gains(p);
10562 #endif
10563
10564 dahdi_setlinear(p->subs[idx].dfd, 0);
10565
10566
10567 for (;;) {
10568 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10569 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10570 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10571 callerid_free(cs);
10572 ast_hangup(chan);
10573 goto quit;
10574 }
10575 if (i & DAHDI_IOMUX_SIGEVENT) {
10576 res = dahdi_get_event(p->subs[idx].dfd);
10577 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10578 if (res == DAHDI_EVENT_NOALARM) {
10579 p->inalarm = 0;
10580 }
10581
10582 if (p->cid_signalling == CID_SIG_V23_JP) {
10583 if (res == DAHDI_EVENT_RINGBEGIN) {
10584 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10585 usleep(1);
10586 }
10587 } else {
10588 res = 0;
10589 break;
10590 }
10591 } else if (i & DAHDI_IOMUX_READ) {
10592 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10593 if (res < 0) {
10594 if (errno != ELAST) {
10595 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10596 callerid_free(cs);
10597 ast_hangup(chan);
10598 goto quit;
10599 }
10600 break;
10601 }
10602 samples += res;
10603
10604 if (p->cid_signalling == CID_SIG_V23_JP) {
10605 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10606 } else {
10607 res = callerid_feed(cs, buf, res, AST_LAW(p));
10608 }
10609 if (res < 0) {
10610
10611
10612
10613
10614 ast_log(LOG_WARNING,
10615 "Failed to decode CallerID on channel '%s'\n",
10616 chan->name);
10617 break;
10618 } else if (res)
10619 break;
10620 else if (samples > (8000 * 10))
10621 break;
10622 }
10623 }
10624 if (res == 1) {
10625 callerid_get(cs, &name, &number, &flags);
10626 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10627 }
10628
10629 if (p->cid_signalling == CID_SIG_V23_JP) {
10630 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10631 usleep(1);
10632 }
10633
10634
10635 res = 4000;
10636 for (;;) {
10637 struct ast_frame *f;
10638 res = ast_waitfor(chan, res);
10639 if (res <= 0) {
10640 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10641 "Exiting simple switch\n");
10642 ast_hangup(chan);
10643 goto quit;
10644 }
10645 if (!(f = ast_read(chan))) {
10646 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10647 ast_hangup(chan);
10648 goto quit;
10649 }
10650 ast_frfree(f);
10651 if (chan->_state == AST_STATE_RING ||
10652 chan->_state == AST_STATE_RINGING)
10653 break;
10654 }
10655
10656
10657
10658 if (p->usedistinctiveringdetection) {
10659 len = 0;
10660 distMatches = 0;
10661
10662 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10663 curRingData[receivedRingT] = 0;
10664 receivedRingT = 0;
10665 counter = 0;
10666 counter1 = 0;
10667
10668 if (strcmp(p->context,p->defcontext) != 0) {
10669 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10670 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10671 }
10672
10673 for (;;) {
10674 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10675 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10676 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10677 callerid_free(cs);
10678 ast_hangup(chan);
10679 goto quit;
10680 }
10681 if (i & DAHDI_IOMUX_SIGEVENT) {
10682 res = dahdi_get_event(p->subs[idx].dfd);
10683 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10684 if (res == DAHDI_EVENT_NOALARM) {
10685 p->inalarm = 0;
10686 }
10687 res = 0;
10688
10689
10690 curRingData[receivedRingT] = p->ringt;
10691
10692 if (p->ringt < p->ringt_base/2)
10693 break;
10694
10695
10696 if (++receivedRingT == ARRAY_LEN(curRingData))
10697 break;
10698 } else if (i & DAHDI_IOMUX_READ) {
10699 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10700 if (res < 0) {
10701 if (errno != ELAST) {
10702 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10703 callerid_free(cs);
10704 ast_hangup(chan);
10705 goto quit;
10706 }
10707 break;
10708 }
10709 if (p->ringt > 0) {
10710 if (!(--p->ringt)) {
10711 res = -1;
10712 break;
10713 }
10714 }
10715 }
10716 }
10717
10718 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10719 for (counter = 0; counter < 3; counter++) {
10720
10721
10722 distMatches = 0;
10723 for (counter1 = 0; counter1 < 3; counter1++) {
10724 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10725 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10726 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10727 curRingData[counter1]);
10728 distMatches++;
10729 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10730 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10731 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10732 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10733 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10734 distMatches++;
10735 }
10736 }
10737
10738 if (distMatches == 3) {
10739
10740 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10741 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10742 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10743 break;
10744 }
10745 }
10746 }
10747
10748 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10749 #if 1
10750 restore_gains(p);
10751 #endif
10752 } else
10753 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10754 } else {
10755 ast_log(LOG_WARNING, "Channel %s in prering "
10756 "state, but I have nothing to do. "
10757 "Terminating simple switch, should be "
10758 "restarted by the actual ring.\n",
10759 chan->name);
10760 ast_hangup(chan);
10761 goto quit;
10762 }
10763 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10764 if (p->cid_signalling == CID_SIG_DTMF) {
10765 int k = 0;
10766 cs = NULL;
10767 dahdi_setlinear(p->subs[idx].dfd, 0);
10768 res = 2000;
10769 for (;;) {
10770 struct ast_frame *f;
10771 res = ast_waitfor(chan, res);
10772 if (res <= 0) {
10773 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10774 "Exiting simple switch\n");
10775 ast_hangup(chan);
10776 goto quit;
10777 }
10778 f = ast_read(chan);
10779 if (!f) {
10780
10781 ast_hangup(chan);
10782 goto quit;
10783 }
10784 if (f->frametype == AST_FRAME_DTMF) {
10785 dtmfbuf[k++] = f->subclass.integer;
10786 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10787 res = 2000;
10788 }
10789 ast_frfree(f);
10790
10791 if (p->ringt_base == p->ringt)
10792 break;
10793 }
10794 dtmfbuf[k] = '\0';
10795 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10796
10797 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10798 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10799 dtmfcid, flags);
10800
10801 if (!ast_strlen_zero(dtmfcid))
10802 number = dtmfcid;
10803 else
10804 number = NULL;
10805
10806 } else {
10807
10808 cs = callerid_new(p->cid_signalling);
10809 if (cs) {
10810 #if 1
10811 bump_gains(p);
10812 #endif
10813 samples = 0;
10814 len = 0;
10815 distMatches = 0;
10816
10817 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10818 curRingData[receivedRingT] = 0;
10819 receivedRingT = 0;
10820 counter = 0;
10821 counter1 = 0;
10822
10823 if (strcmp(p->context,p->defcontext) != 0) {
10824 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10825 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10826 }
10827
10828
10829 dahdi_setlinear(p->subs[idx].dfd, 0);
10830 for (;;) {
10831 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10832 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10833 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10834 callerid_free(cs);
10835 ast_hangup(chan);
10836 goto quit;
10837 }
10838 if (i & DAHDI_IOMUX_SIGEVENT) {
10839 res = dahdi_get_event(p->subs[idx].dfd);
10840 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10841 if (res == DAHDI_EVENT_NOALARM) {
10842 p->inalarm = 0;
10843 }
10844
10845 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10846 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10847 p->polarity = POLARITY_IDLE;
10848 callerid_free(cs);
10849 ast_hangup(chan);
10850 goto quit;
10851 }
10852 res = 0;
10853
10854
10855 curRingData[receivedRingT] = p->ringt;
10856
10857 if (p->ringt < p->ringt_base/2)
10858 break;
10859
10860
10861 if (++receivedRingT == ARRAY_LEN(curRingData))
10862 break;
10863 } else if (i & DAHDI_IOMUX_READ) {
10864 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10865 if (res < 0) {
10866 if (errno != ELAST) {
10867 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10868 callerid_free(cs);
10869 ast_hangup(chan);
10870 goto quit;
10871 }
10872 break;
10873 }
10874 if (p->ringt > 0) {
10875 if (!(--p->ringt)) {
10876 res = -1;
10877 break;
10878 }
10879 }
10880 samples += res;
10881 res = callerid_feed(cs, buf, res, AST_LAW(p));
10882 if (res < 0) {
10883
10884
10885
10886
10887 ast_log(LOG_WARNING,
10888 "Failed to decode CallerID on channel '%s'\n",
10889 chan->name);
10890 break;
10891 } else if (res)
10892 break;
10893 else if (samples > (8000 * 10))
10894 break;
10895 }
10896 }
10897 if (res == 1) {
10898 callerid_get(cs, &name, &number, &flags);
10899 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10900 }
10901 if (distinctiveringaftercid == 1) {
10902
10903 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10904 curRingData[receivedRingT] = 0;
10905 }
10906 receivedRingT = 0;
10907 ast_verb(3, "Detecting post-CID distinctive ring\n");
10908 for (;;) {
10909 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10910 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10911 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10912 callerid_free(cs);
10913 ast_hangup(chan);
10914 goto quit;
10915 }
10916 if (i & DAHDI_IOMUX_SIGEVENT) {
10917 res = dahdi_get_event(p->subs[idx].dfd);
10918 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10919 if (res == DAHDI_EVENT_NOALARM) {
10920 p->inalarm = 0;
10921 }
10922 res = 0;
10923
10924
10925 curRingData[receivedRingT] = p->ringt;
10926
10927 if (p->ringt < p->ringt_base/2)
10928 break;
10929
10930
10931 if (++receivedRingT == ARRAY_LEN(curRingData))
10932 break;
10933 } else if (i & DAHDI_IOMUX_READ) {
10934 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10935 if (res < 0) {
10936 if (errno != ELAST) {
10937 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10938 callerid_free(cs);
10939 ast_hangup(chan);
10940 goto quit;
10941 }
10942 break;
10943 }
10944 if (p->ringt > 0) {
10945 if (!(--p->ringt)) {
10946 res = -1;
10947 break;
10948 }
10949 }
10950 }
10951 }
10952 }
10953 if (p->usedistinctiveringdetection) {
10954
10955 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10956
10957 for (counter = 0; counter < 3; counter++) {
10958
10959
10960
10961 ast_verb(3, "Checking %d,%d,%d\n",
10962 p->drings.ringnum[counter].ring[0],
10963 p->drings.ringnum[counter].ring[1],
10964 p->drings.ringnum[counter].ring[2]);
10965 distMatches = 0;
10966 for (counter1 = 0; counter1 < 3; counter1++) {
10967 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10968 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10969 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10970 curRingData[counter1]);
10971 distMatches++;
10972 }
10973 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10974 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10975 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10976 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10977 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10978 distMatches++;
10979 }
10980 }
10981 if (distMatches == 3) {
10982
10983 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10984 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10985 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10986 break;
10987 }
10988 }
10989 }
10990
10991 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10992 #if 1
10993 restore_gains(p);
10994 #endif
10995 if (res < 0) {
10996 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10997 }
10998 } else
10999 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
11000 }
11001 } else
11002 cs = NULL;
11003
11004 if (number)
11005 ast_shrink_phone_number(number);
11006 ast_set_callerid(chan, number, name, number);
11007
11008 if (smdi_msg)
11009 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
11010
11011 if (cs)
11012 callerid_free(cs);
11013
11014 my_handle_notify_message(chan, p, flags, -1);
11015
11016 ast_setstate(chan, AST_STATE_RING);
11017 chan->rings = 1;
11018 p->ringt = p->ringt_base;
11019 res = ast_pbx_run(chan);
11020 if (res) {
11021 ast_hangup(chan);
11022 ast_log(LOG_WARNING, "PBX exited non-zero\n");
11023 }
11024 goto quit;
11025 default:
11026 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
11027 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11028 if (res < 0)
11029 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11030 }
11031 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
11032 if (res < 0)
11033 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
11034 ast_hangup(chan);
11035 quit:
11036 ast_mutex_lock(&ss_thread_lock);
11037 ss_thread_count--;
11038 ast_cond_signal(&ss_thread_complete);
11039 ast_mutex_unlock(&ss_thread_lock);
11040 return NULL;
11041 }
11042
11043 struct mwi_thread_data {
11044 struct dahdi_pvt *pvt;
11045 unsigned char buf[READ_SIZE];
11046 size_t len;
11047 };
11048
11049 static int calc_energy(const unsigned char *buf, int len, format_t law)
11050 {
11051 int x;
11052 int sum = 0;
11053
11054 if (!len)
11055 return 0;
11056
11057 for (x = 0; x < len; x++)
11058 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
11059
11060 return sum / len;
11061 }
11062
11063 static void *mwi_thread(void *data)
11064 {
11065 struct mwi_thread_data *mtd = data;
11066 struct callerid_state *cs;
11067 pthread_t threadid;
11068 int samples = 0;
11069 char *name, *number;
11070 int flags;
11071 int i, res;
11072 unsigned int spill_done = 0;
11073 int spill_result = -1;
11074
11075 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
11076 goto quit_no_clean;
11077 }
11078
11079 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
11080
11081 bump_gains(mtd->pvt);
11082
11083 for (;;) {
11084 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
11085 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
11086 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
11087 goto quit;
11088 }
11089
11090 if (i & DAHDI_IOMUX_SIGEVENT) {
11091 struct ast_channel *chan;
11092
11093
11094
11095
11096 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
11097
11098 switch (res) {
11099 case DAHDI_EVENT_NEONMWI_ACTIVE:
11100 case DAHDI_EVENT_NEONMWI_INACTIVE:
11101 case DAHDI_EVENT_NONE:
11102 case DAHDI_EVENT_BITSCHANGED:
11103 break;
11104 case DAHDI_EVENT_NOALARM:
11105 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11106 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11107
11108 analog_p->inalarm = 0;
11109 }
11110 mtd->pvt->inalarm = 0;
11111 handle_clear_alarms(mtd->pvt);
11112 break;
11113 case DAHDI_EVENT_ALARM:
11114 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11115 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
11116
11117 analog_p->inalarm = 1;
11118 }
11119 mtd->pvt->inalarm = 1;
11120 res = get_alarms(mtd->pvt);
11121 handle_alarms(mtd->pvt, res);
11122 break;
11123 default:
11124 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
11125 callerid_free(cs);
11126
11127 restore_gains(mtd->pvt);
11128 mtd->pvt->ringt = mtd->pvt->ringt_base;
11129
11130 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
11131 int result;
11132
11133 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
11134 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
11135 } else {
11136 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11137 }
11138 if (result) {
11139 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
11140 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11141 if (res < 0)
11142 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
11143 ast_hangup(chan);
11144 }
11145 } else {
11146 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
11147 }
11148 goto quit_no_clean;
11149 }
11150 } else if (i & DAHDI_IOMUX_READ) {
11151 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
11152 if (errno != ELAST) {
11153 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
11154 goto quit;
11155 }
11156 break;
11157 }
11158 samples += res;
11159 if (!spill_done) {
11160 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
11161
11162
11163
11164
11165 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
11166 break;
11167 } else if (spill_result) {
11168 spill_done = 1;
11169 }
11170 } else {
11171
11172
11173
11174 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
11175 break;
11176 }
11177 if (samples > (8000 * 4))
11178 break;
11179 }
11180 }
11181
11182 if (spill_result == 1) {
11183 callerid_get(cs, &name, &number, &flags);
11184 if (flags & CID_MSGWAITING) {
11185 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
11186 notify_message(mtd->pvt->mailbox, 1);
11187 } else if (flags & CID_NOMSGWAITING) {
11188 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
11189 notify_message(mtd->pvt->mailbox, 0);
11190 } else {
11191 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
11192 }
11193 }
11194
11195
11196 quit:
11197 callerid_free(cs);
11198
11199 restore_gains(mtd->pvt);
11200
11201 quit_no_clean:
11202 mtd->pvt->mwimonitoractive = 0;
11203 ast_free(mtd);
11204
11205 return NULL;
11206 }
11207
11208
11209
11210
11211
11212
11213
11214
11215 static int mwi_send_init(struct dahdi_pvt * pvt)
11216 {
11217 int x;
11218
11219 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11220
11221 if (pvt->mwisend_rpas) {
11222 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11223 pvt->mwisendactive = 1;
11224 } else if (pvt->mwisend_fsk) {
11225 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11226 pvt->mwisendactive = 1;
11227 } else {
11228 pvt->mwisendactive = 0;
11229 return 0;
11230 }
11231 #else
11232 if (mwisend_rpas) {
11233 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
11234 } else {
11235 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11236 }
11237 pvt->mwisendactive = 1;
11238 #endif
11239
11240 if (pvt->cidspill) {
11241 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
11242 ast_free(pvt->cidspill);
11243 pvt->cidspill = NULL;
11244 pvt->cidpos = 0;
11245 pvt->cidlen = 0;
11246 }
11247 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
11248 if (!pvt->cidspill) {
11249 pvt->mwisendactive = 0;
11250 return -1;
11251 }
11252 x = DAHDI_FLUSH_BOTH;
11253 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
11254 x = 3000;
11255 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
11256 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11257 if (pvt->mwisend_fsk) {
11258 #endif
11259 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
11260 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
11261 pvt->cidpos = 0;
11262 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11263 }
11264 #endif
11265 return 0;
11266 }
11267
11268 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
11269 {
11270 struct timeval now;
11271 int res;
11272
11273
11274
11275
11276 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
11277 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11278 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11279
11280 switch ( pvt->mwisend_data.mwisend_current) {
11281 case MWI_SEND_SA:
11282
11283 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
11284 if (res) {
11285 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
11286 goto quit;
11287 }
11288 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
11289 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
11290 break;
11291 case MWI_SEND_SA_WAIT:
11292 break;
11293 case MWI_SEND_PAUSE:
11294 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11295 if (pvt->mwisend_fsk) {
11296 #endif
11297 gettimeofday(&now, NULL);
11298 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
11299 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
11300 }
11301 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
11302 } else {
11303 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11304 }
11305 #endif
11306 break;
11307 case MWI_SEND_SPILL:
11308
11309 if(0 < num_read) {
11310 if (num_read > pvt->cidlen - pvt->cidpos)
11311 num_read = pvt->cidlen - pvt->cidpos;
11312 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
11313 if (res > 0) {
11314 pvt->cidpos += res;
11315 if (pvt->cidpos >= pvt->cidlen) {
11316 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
11317 }
11318 } else {
11319 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
11320 goto quit;
11321 }
11322 }
11323 break;
11324 case MWI_SEND_CLEANUP:
11325
11326 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11327 break;
11328 default:
11329
11330 goto quit;
11331 }
11332 }
11333
11334 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
11335 if (pvt->cidspill) {
11336 ast_free(pvt->cidspill);
11337 pvt->cidspill = NULL;
11338 pvt->cidpos = 0;
11339 pvt->cidlen = 0;
11340 }
11341 pvt->mwisendactive = 0;
11342 }
11343 return 0;
11344 quit:
11345 if (pvt->cidspill) {
11346 ast_free(pvt->cidspill);
11347 pvt->cidspill = NULL;
11348 pvt->cidpos = 0;
11349 pvt->cidlen = 0;
11350 }
11351 pvt->mwisendactive = 0;
11352 return -1;
11353 }
11354
11355 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11356 {
11357 int handled = 0;
11358
11359 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11360 switch (event) {
11361 case DAHDI_EVENT_RINGEROFF:
11362 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11363 handled = 1;
11364
11365 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11366 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11367 ast_free(pvt->cidspill);
11368 pvt->cidspill = NULL;
11369 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11370 pvt->mwisendactive = 0;
11371 } else {
11372 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11373 gettimeofday(&pvt->mwisend_data.pause, NULL);
11374 }
11375 }
11376 break;
11377
11378 case DAHDI_EVENT_RINGOFFHOOK:
11379 if (pvt->cidspill) {
11380 ast_free(pvt->cidspill);
11381 pvt->cidspill = NULL;
11382 pvt->cidpos = 0;
11383 pvt->cidlen = 0;
11384 }
11385 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11386 pvt->mwisendactive = 0;
11387 break;
11388 case DAHDI_EVENT_RINGERON:
11389 case DAHDI_EVENT_HOOKCOMPLETE:
11390 break;
11391 default:
11392 break;
11393 }
11394 }
11395 return handled;
11396 }
11397
11398
11399 static int dahdi_destroy_channel_bynum(int channel)
11400 {
11401 struct dahdi_pvt *cur;
11402
11403 ast_mutex_lock(&iflock);
11404 for (cur = iflist; cur; cur = cur->next) {
11405 if (cur->channel == channel) {
11406 int x = DAHDI_FLASH;
11407
11408
11409 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11410
11411 destroy_channel(cur, 1);
11412 ast_mutex_unlock(&iflock);
11413 ast_module_unref(ast_module_info->self);
11414 return RESULT_SUCCESS;
11415 }
11416 }
11417 ast_mutex_unlock(&iflock);
11418 return RESULT_FAILURE;
11419 }
11420
11421 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11422 {
11423 int res;
11424 pthread_t threadid;
11425 struct ast_channel *chan;
11426
11427
11428
11429 switch (event) {
11430 case DAHDI_EVENT_NONE:
11431 case DAHDI_EVENT_BITSCHANGED:
11432 break;
11433 case DAHDI_EVENT_WINKFLASH:
11434 case DAHDI_EVENT_RINGOFFHOOK:
11435 if (i->inalarm) break;
11436 if (i->radio) break;
11437
11438 switch (i->sig) {
11439 case SIG_FXOLS:
11440 case SIG_FXOGS:
11441 case SIG_FXOKS:
11442 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11443 if (res && (errno == EBUSY))
11444 break;
11445
11446
11447 ast_free(i->cidspill);
11448 i->cidspill = NULL;
11449 restore_conference(i);
11450
11451 if (i->immediate) {
11452 dahdi_enable_ec(i);
11453
11454 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11455 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11456 if (!chan) {
11457 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11458 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11459 if (res < 0)
11460 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11461 }
11462 } else {
11463
11464 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11465 if (chan) {
11466 if (has_voicemail(i))
11467 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11468 else
11469 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11470 if (res < 0)
11471 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11472 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11473 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11474 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11475 if (res < 0)
11476 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11477 ast_hangup(chan);
11478 }
11479 } else
11480 ast_log(LOG_WARNING, "Unable to create channel\n");
11481 }
11482 break;
11483 case SIG_FXSLS:
11484 case SIG_FXSGS:
11485 case SIG_FXSKS:
11486 i->ringt = i->ringt_base;
11487
11488 case SIG_EMWINK:
11489 case SIG_FEATD:
11490 case SIG_FEATDMF:
11491 case SIG_FEATDMF_TA:
11492 case SIG_E911:
11493 case SIG_FGC_CAMA:
11494 case SIG_FGC_CAMAMF:
11495 case SIG_FEATB:
11496 case SIG_EM:
11497 case SIG_EM_E1:
11498 case SIG_SFWINK:
11499 case SIG_SF_FEATD:
11500 case SIG_SF_FEATDMF:
11501 case SIG_SF_FEATB:
11502 case SIG_SF:
11503
11504 if (i->cid_start == CID_START_POLARITY_IN) {
11505 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11506 } else {
11507 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11508 }
11509
11510 if (!chan) {
11511 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11512 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11513 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11514 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11515 if (res < 0) {
11516 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11517 }
11518 ast_hangup(chan);
11519 }
11520 break;
11521 default:
11522 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11523 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11524 if (res < 0)
11525 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11526 return NULL;
11527 }
11528 break;
11529 case DAHDI_EVENT_NOALARM:
11530 switch (i->sig) {
11531 #if defined(HAVE_PRI)
11532 case SIG_PRI_LIB_HANDLE_CASES:
11533 ast_mutex_lock(&i->lock);
11534 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11535 ast_mutex_unlock(&i->lock);
11536 break;
11537 #endif
11538 #if defined(HAVE_SS7)
11539 case SIG_SS7:
11540 sig_ss7_set_alarm(i->sig_pvt, 0);
11541 break;
11542 #endif
11543 default:
11544 i->inalarm = 0;
11545 break;
11546 }
11547 handle_clear_alarms(i);
11548 break;
11549 case DAHDI_EVENT_ALARM:
11550 switch (i->sig) {
11551 #if defined(HAVE_PRI)
11552 case SIG_PRI_LIB_HANDLE_CASES:
11553 ast_mutex_lock(&i->lock);
11554 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11555 ast_mutex_unlock(&i->lock);
11556 break;
11557 #endif
11558 #if defined(HAVE_SS7)
11559 case SIG_SS7:
11560 sig_ss7_set_alarm(i->sig_pvt, 1);
11561 break;
11562 #endif
11563 default:
11564 i->inalarm = 1;
11565 break;
11566 }
11567 res = get_alarms(i);
11568 handle_alarms(i, res);
11569
11570 case DAHDI_EVENT_ONHOOK:
11571 if (i->radio)
11572 break;
11573
11574 switch (i->sig) {
11575 case SIG_FXOLS:
11576 case SIG_FXOGS:
11577 case SIG_FEATD:
11578 case SIG_FEATDMF:
11579 case SIG_FEATDMF_TA:
11580 case SIG_E911:
11581 case SIG_FGC_CAMA:
11582 case SIG_FGC_CAMAMF:
11583 case SIG_FEATB:
11584 case SIG_EM:
11585 case SIG_EM_E1:
11586 case SIG_EMWINK:
11587 case SIG_SF_FEATD:
11588 case SIG_SF_FEATDMF:
11589 case SIG_SF_FEATB:
11590 case SIG_SF:
11591 case SIG_SFWINK:
11592 case SIG_FXSLS:
11593 case SIG_FXSGS:
11594 case SIG_FXSKS:
11595 case SIG_FXOKS:
11596 dahdi_disable_ec(i);
11597
11598 #ifdef ZHONE_HACK
11599 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11600 usleep(1);
11601 #endif
11602 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11603 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11604 break;
11605 case SIG_SS7:
11606 case SIG_PRI_LIB_HANDLE_CASES:
11607 dahdi_disable_ec(i);
11608 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11609 break;
11610 default:
11611 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11612 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11613 return NULL;
11614 }
11615 break;
11616 case DAHDI_EVENT_POLARITY:
11617 switch (i->sig) {
11618 case SIG_FXSLS:
11619 case SIG_FXSKS:
11620 case SIG_FXSGS:
11621
11622
11623
11624
11625 if (i->hanguponpolarityswitch)
11626 i->polarity = POLARITY_REV;
11627 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11628 i->polarity = POLARITY_REV;
11629 ast_verb(2, "Starting post polarity "
11630 "CID detection on channel %d\n",
11631 i->channel);
11632 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11633 if (!chan) {
11634 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11635 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11636 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11637 ast_hangup(chan);
11638 }
11639 }
11640 break;
11641 default:
11642 ast_log(LOG_WARNING, "handle_init_event detected "
11643 "polarity reversal on non-FXO (SIG_FXS) "
11644 "interface %d\n", i->channel);
11645 }
11646 break;
11647 case DAHDI_EVENT_REMOVED:
11648 ast_log(LOG_NOTICE,
11649 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11650 i->channel);
11651 return i;
11652 case DAHDI_EVENT_NEONMWI_ACTIVE:
11653 if (i->mwimonitor_neon) {
11654 notify_message(i->mailbox, 1);
11655 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11656 }
11657 break;
11658 case DAHDI_EVENT_NEONMWI_INACTIVE:
11659 if (i->mwimonitor_neon) {
11660 notify_message(i->mailbox, 0);
11661 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11662 }
11663 break;
11664 }
11665 return NULL;
11666 }
11667
11668 static void *do_monitor(void *data)
11669 {
11670 int count, res, res2, spoint, pollres=0;
11671 struct dahdi_pvt *i;
11672 struct dahdi_pvt *last = NULL;
11673 struct dahdi_pvt *doomed;
11674 time_t thispass = 0, lastpass = 0;
11675 int found;
11676 char buf[1024];
11677 struct pollfd *pfds=NULL;
11678 int lastalloc = -1;
11679
11680
11681
11682 #if 0
11683 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11684 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11685 return NULL;
11686 }
11687 ast_debug(1, "Monitor starting...\n");
11688 #endif
11689 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11690
11691 for (;;) {
11692
11693 ast_mutex_lock(&iflock);
11694 if (!pfds || (lastalloc != ifcount)) {
11695 if (pfds) {
11696 ast_free(pfds);
11697 pfds = NULL;
11698 }
11699 if (ifcount) {
11700 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11701 ast_mutex_unlock(&iflock);
11702 return NULL;
11703 }
11704 }
11705 lastalloc = ifcount;
11706 }
11707
11708
11709 count = 0;
11710 for (i = iflist; i; i = i->next) {
11711 ast_mutex_lock(&i->lock);
11712 if (pfds && (i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11713 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11714 struct analog_pvt *p = i->sig_pvt;
11715
11716 if (!p) {
11717 ast_log(LOG_ERROR, "No sig_pvt?\n");
11718 } else if (!p->owner && !p->subs[SUB_REAL].owner) {
11719
11720 pfds[count].fd = i->subs[SUB_REAL].dfd;
11721 pfds[count].events = POLLPRI;
11722 pfds[count].revents = 0;
11723
11724 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11725 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11726 pfds[count].events |= POLLIN;
11727 }
11728 count++;
11729 }
11730 } else {
11731 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11732
11733 pfds[count].fd = i->subs[SUB_REAL].dfd;
11734 pfds[count].events = POLLPRI;
11735 pfds[count].revents = 0;
11736
11737
11738 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11739 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11740 pfds[count].events |= POLLIN;
11741 }
11742 count++;
11743 }
11744 }
11745 }
11746 ast_mutex_unlock(&i->lock);
11747 }
11748
11749 ast_mutex_unlock(&iflock);
11750
11751 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11752 pthread_testcancel();
11753
11754 res = poll(pfds, count, 1000);
11755 pthread_testcancel();
11756 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11757
11758
11759 if (res < 0) {
11760 if ((errno != EAGAIN) && (errno != EINTR))
11761 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11762 continue;
11763 }
11764
11765
11766 ast_mutex_lock(&iflock);
11767 found = 0;
11768 spoint = 0;
11769 lastpass = thispass;
11770 thispass = time(NULL);
11771 doomed = NULL;
11772 for (i = iflist;; i = i->next) {
11773 if (doomed) {
11774 int res;
11775 res = dahdi_destroy_channel_bynum(doomed->channel);
11776 if (res != RESULT_SUCCESS) {
11777 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11778 }
11779 doomed = NULL;
11780 }
11781 if (!i) {
11782 break;
11783 }
11784
11785 if (thispass != lastpass) {
11786 if (!found && ((i == last) || ((i == iflist) && !last))) {
11787 last = i;
11788 if (last) {
11789 struct analog_pvt *analog_p = last->sig_pvt;
11790
11791 if (analog_p
11792 && !last->mwisendactive
11793 && (last->sig & __DAHDI_SIG_FXO)
11794 && !analog_p->fxsoffhookstate
11795 && !last->owner
11796 && !ast_strlen_zero(last->mailbox)
11797 && (thispass - analog_p->onhooktime > 3)) {
11798 res = has_voicemail(last);
11799 if (analog_p->msgstate != res) {
11800
11801 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11802 if (res2) {
11803
11804 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11805 }
11806
11807 if (mwi_send_init(last)) {
11808 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11809 }
11810 analog_p->msgstate = res;
11811 found ++;
11812 }
11813 }
11814 last = last->next;
11815 }
11816 }
11817 }
11818 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11819 if (i->radio && !i->owner)
11820 {
11821 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11822 if (res)
11823 {
11824 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11825
11826 ast_mutex_unlock(&iflock);
11827 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11828 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11829 else
11830 doomed = handle_init_event(i, res);
11831 ast_mutex_lock(&iflock);
11832 }
11833 continue;
11834 }
11835 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11836 if (pollres & POLLIN) {
11837 if (i->owner || i->subs[SUB_REAL].owner) {
11838 #ifdef HAVE_PRI
11839 if (!i->pri)
11840 #endif
11841 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11842 continue;
11843 }
11844 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11845 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11846 continue;
11847 }
11848 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11849 if (res > 0) {
11850 if (i->mwimonitor_fsk) {
11851 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11852 pthread_attr_t attr;
11853 pthread_t threadid;
11854 struct mwi_thread_data *mtd;
11855
11856 pthread_attr_init(&attr);
11857 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11858
11859 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11860 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11861 mtd->pvt = i;
11862 memcpy(mtd->buf, buf, res);
11863 mtd->len = res;
11864 i->mwimonitoractive = 1;
11865 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11866 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11867 i->mwimonitoractive = 0;
11868 ast_free(mtd);
11869 }
11870 }
11871 }
11872
11873 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11874 int energy;
11875 struct timeval now;
11876
11877
11878
11879 if (1 == i->dtmfcid_holdoff_state) {
11880 gettimeofday(&i->dtmfcid_delay, NULL);
11881 i->dtmfcid_holdoff_state = 2;
11882 } else if (2 == i->dtmfcid_holdoff_state) {
11883 gettimeofday(&now, NULL);
11884 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11885 i->dtmfcid_holdoff_state = 0;
11886 }
11887 } else {
11888 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11889 if (!i->mwisendactive && energy > dtmfcid_level) {
11890 pthread_t threadid;
11891 struct ast_channel *chan;
11892 ast_mutex_unlock(&iflock);
11893 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11894
11895 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11896 i->dtmfcid_holdoff_state = 1;
11897 } else {
11898 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11899 if (!chan) {
11900 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11901 } else {
11902 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11903 if (res) {
11904 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11905 ast_hangup(chan);
11906 } else {
11907 i->dtmfcid_holdoff_state = 1;
11908 }
11909 }
11910 }
11911 ast_mutex_lock(&iflock);
11912 }
11913 }
11914 }
11915 if (i->mwisendactive) {
11916 mwi_send_process_buffer(i, res);
11917 }
11918 } else {
11919 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11920 }
11921 }
11922 if (pollres & POLLPRI) {
11923 if (i->owner || i->subs[SUB_REAL].owner) {
11924 #ifdef HAVE_PRI
11925 if (!i->pri)
11926 #endif
11927 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11928 continue;
11929 }
11930 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11931 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11932
11933 ast_mutex_unlock(&iflock);
11934 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11935 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11936 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11937 else
11938 doomed = handle_init_event(i, res);
11939 }
11940 ast_mutex_lock(&iflock);
11941 }
11942 }
11943 }
11944 ast_mutex_unlock(&iflock);
11945 }
11946
11947 return NULL;
11948
11949 }
11950
11951 static int restart_monitor(void)
11952 {
11953
11954 if (monitor_thread == AST_PTHREADT_STOP)
11955 return 0;
11956 ast_mutex_lock(&monlock);
11957 if (monitor_thread == pthread_self()) {
11958 ast_mutex_unlock(&monlock);
11959 ast_log(LOG_WARNING, "Cannot kill myself\n");
11960 return -1;
11961 }
11962 if (monitor_thread != AST_PTHREADT_NULL) {
11963
11964 pthread_kill(monitor_thread, SIGURG);
11965 } else {
11966
11967 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11968 ast_mutex_unlock(&monlock);
11969 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11970 return -1;
11971 }
11972 }
11973 ast_mutex_unlock(&monlock);
11974 return 0;
11975 }
11976
11977 #if defined(HAVE_PRI)
11978 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11979 {
11980 int x;
11981 int trunkgroup;
11982
11983 trunkgroup = pris[*span].mastertrunkgroup;
11984 if (trunkgroup) {
11985
11986 for (x = 0; x < NUM_SPANS; x++) {
11987 if (pris[x].pri.trunkgroup == trunkgroup) {
11988 *span = x;
11989 return 0;
11990 }
11991 }
11992 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11993 *span = -1;
11994 } else {
11995 if (pris[*span].pri.trunkgroup) {
11996 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);
11997 *span = -1;
11998 } else if (pris[*span].mastertrunkgroup) {
11999 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
12000 *span = -1;
12001 } else {
12002 if (si->totalchans == 31) {
12003
12004 pris[*span].dchannels[0] = 16 + offset;
12005 } else if (si->totalchans == 24) {
12006
12007 pris[*span].dchannels[0] = 24 + offset;
12008 } else if (si->totalchans == 3) {
12009
12010 pris[*span].dchannels[0] = 3 + offset;
12011 } else {
12012 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);
12013 *span = -1;
12014 return 0;
12015 }
12016 pris[*span].pri.span = *span + 1;
12017 }
12018 }
12019 return 0;
12020 }
12021 #endif
12022
12023 #if defined(HAVE_PRI)
12024 static int pri_create_trunkgroup(int trunkgroup, int *channels)
12025 {
12026 struct dahdi_spaninfo si;
12027 struct dahdi_params p;
12028 int fd;
12029 int span;
12030 int ospan=0;
12031 int x,y;
12032 for (x = 0; x < NUM_SPANS; x++) {
12033 if (pris[x].pri.trunkgroup == trunkgroup) {
12034 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
12035 return -1;
12036 }
12037 }
12038 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12039 if (!channels[y])
12040 break;
12041 memset(&si, 0, sizeof(si));
12042 memset(&p, 0, sizeof(p));
12043 fd = open("/dev/dahdi/channel", O_RDWR);
12044 if (fd < 0) {
12045 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
12046 return -1;
12047 }
12048 x = channels[y];
12049 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
12050 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
12051 close(fd);
12052 return -1;
12053 }
12054 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
12055 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
12056 return -1;
12057 }
12058 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
12059 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
12060 close(fd);
12061 return -1;
12062 }
12063 span = p.spanno - 1;
12064 if (pris[span].pri.trunkgroup) {
12065 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
12066 close(fd);
12067 return -1;
12068 }
12069 if (pris[span].pri.pvts[0]) {
12070 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
12071 close(fd);
12072 return -1;
12073 }
12074 if (!y) {
12075 pris[span].pri.trunkgroup = trunkgroup;
12076 ospan = span;
12077 }
12078 pris[ospan].dchannels[y] = channels[y];
12079 pris[span].pri.span = span + 1;
12080 close(fd);
12081 }
12082 return 0;
12083 }
12084 #endif
12085
12086 #if defined(HAVE_PRI)
12087 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
12088 {
12089 if (pris[span].mastertrunkgroup) {
12090 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);
12091 return -1;
12092 }
12093 pris[span].mastertrunkgroup = trunkgroup;
12094 pris[span].prilogicalspan = logicalspan;
12095 return 0;
12096 }
12097 #endif
12098
12099 #if defined(HAVE_SS7)
12100 static unsigned int parse_pointcode(const char *pcstring)
12101 {
12102 unsigned int code1, code2, code3;
12103 int numvals;
12104
12105 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
12106 if (numvals == 1)
12107 return code1;
12108 if (numvals == 3)
12109 return (code1 << 16) | (code2 << 8) | code3;
12110
12111 return 0;
12112 }
12113 #endif
12114
12115 #if defined(HAVE_SS7)
12116 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
12117 {
12118 if ((linkset < 0) || (linkset >= NUM_SPANS))
12119 return NULL;
12120 else
12121 return &linksets[linkset - 1];
12122 }
12123 #endif
12124
12125 #ifdef HAVE_OPENR2
12126 static void dahdi_r2_destroy_links(void)
12127 {
12128 int i = 0;
12129 if (!r2links) {
12130 return;
12131 }
12132 for (; i < r2links_count; i++) {
12133 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
12134 pthread_cancel(r2links[i]->r2master);
12135 pthread_join(r2links[i]->r2master, NULL);
12136 openr2_context_delete(r2links[i]->protocol_context);
12137 }
12138 ast_free(r2links[i]);
12139 }
12140 ast_free(r2links);
12141 r2links = NULL;
12142 r2links_count = 0;
12143 }
12144
12145 #define R2_LINK_CAPACITY 10
12146 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
12147 {
12148 struct dahdi_mfcr2 *new_r2link = NULL;
12149 struct dahdi_mfcr2 **new_r2links = NULL;
12150
12151
12152 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
12153 new_r2link = ast_calloc(1, sizeof(**r2links));
12154 if (!new_r2link) {
12155 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12156 return NULL;
12157 }
12158 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
12159 if (!new_r2links) {
12160 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
12161 ast_free(new_r2link);
12162 return NULL;
12163 }
12164 r2links = new_r2links;
12165 new_r2link->r2master = AST_PTHREADT_NULL;
12166 r2links[r2links_count] = new_r2link;
12167 r2links_count++;
12168 ast_log(LOG_DEBUG, "Created new R2 link!\n");
12169 }
12170 return r2links[r2links_count - 1];
12171 }
12172
12173 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
12174 {
12175 char tmplogdir[] = "/tmp";
12176 char logdir[OR2_MAX_PATH];
12177 int threshold = 0;
12178 int snres = 0;
12179 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
12180 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
12181 conf->mfcr2.max_dnis);
12182 if (!r2_link->protocol_context) {
12183 return -1;
12184 }
12185 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
12186 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
12187 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
12188 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
12189 #endif
12190 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
12191 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
12192 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
12193 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
12194 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
12195 if (ast_strlen_zero(conf->mfcr2.logdir)) {
12196 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12197 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12198 }
12199 } else {
12200 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
12201 if (snres >= sizeof(logdir)) {
12202 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
12203 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
12204 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
12205 }
12206 } else {
12207 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
12208 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
12209 }
12210 }
12211 }
12212 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
12213 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
12214 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
12215 }
12216 }
12217 r2_link->monitored_count = 0;
12218 return 0;
12219 }
12220 #endif
12221
12222
12223
12224
12225
12226
12227 static int sigtype_to_signalling(int sigtype)
12228 {
12229 return sigtype;
12230 }
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
12245 {
12246 struct stat stbuf;
12247 int num;
12248
12249 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
12250 if (stat(path, &stbuf) < 0) {
12251 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
12252 return -errno;
12253 }
12254 if (!S_ISCHR(stbuf.st_mode)) {
12255 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
12256 return -EINVAL;
12257 }
12258 num = minor(stbuf.st_rdev);
12259 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
12260 return num;
12261
12262 }
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
12279 {
12280
12281 struct dahdi_pvt *tmp;
12282 char fn[80];
12283 struct dahdi_bufferinfo bi;
12284
12285 int res;
12286 #if defined(HAVE_PRI)
12287 int span = 0;
12288 #endif
12289 int here = 0;
12290 int x;
12291 struct analog_pvt *analog_p = NULL;
12292 struct dahdi_params p;
12293 #if defined(HAVE_PRI)
12294 struct dahdi_spaninfo si;
12295 struct sig_pri_chan *pri_chan = NULL;
12296 #endif
12297 #if defined(HAVE_SS7)
12298 struct sig_ss7_chan *ss7_chan = NULL;
12299 #endif
12300
12301
12302 for (tmp = iflist; tmp; tmp = tmp->next) {
12303 if (!tmp->destroy) {
12304 if (tmp->channel == channel) {
12305
12306 here = 1;
12307 break;
12308 }
12309 if (tmp->channel > channel) {
12310
12311 tmp = NULL;
12312 break;
12313 }
12314 }
12315 }
12316
12317 if (!here && reloading != 1) {
12318 tmp = ast_calloc(1, sizeof(*tmp));
12319 if (!tmp) {
12320 return NULL;
12321 }
12322 tmp->cc_params = ast_cc_config_params_init();
12323 if (!tmp->cc_params) {
12324 ast_free(tmp);
12325 return NULL;
12326 }
12327 ast_mutex_init(&tmp->lock);
12328 ifcount++;
12329 for (x = 0; x < 3; x++)
12330 tmp->subs[x].dfd = -1;
12331 tmp->channel = channel;
12332 tmp->priindication_oob = conf->chan.priindication_oob;
12333 }
12334
12335 if (tmp) {
12336 int chan_sig = conf->chan.sig;
12337
12338
12339 if (reloading && tmp->vars) {
12340 ast_variables_destroy(tmp->vars);
12341 tmp->vars = NULL;
12342 }
12343
12344
12345 if (!here) {
12346
12347 if ((channel != CHAN_PSEUDO)) {
12348 int count = 0;
12349
12350 snprintf(fn, sizeof(fn), "%d", channel);
12351
12352 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12353 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
12354 usleep(1);
12355 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
12356 count++;
12357 }
12358
12359 if (tmp->subs[SUB_REAL].dfd < 0) {
12360 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);
12361 destroy_dahdi_pvt(tmp);
12362 return NULL;
12363 }
12364 memset(&p, 0, sizeof(p));
12365 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12366 if (res < 0) {
12367 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
12368 destroy_dahdi_pvt(tmp);
12369 return NULL;
12370 }
12371 if (conf->is_sig_auto)
12372 chan_sig = sigtype_to_signalling(p.sigtype);
12373 if (p.sigtype != (chan_sig & 0x3ffff)) {
12374 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));
12375 destroy_dahdi_pvt(tmp);
12376 return NULL;
12377 }
12378 tmp->law_default = p.curlaw;
12379 tmp->law = p.curlaw;
12380 tmp->span = p.spanno;
12381 #if defined(HAVE_PRI)
12382 span = p.spanno - 1;
12383 #endif
12384 } else {
12385 chan_sig = 0;
12386 }
12387 tmp->sig = chan_sig;
12388 tmp->outsigmod = conf->chan.outsigmod;
12389
12390 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12391 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12392 if (!analog_p) {
12393 destroy_dahdi_pvt(tmp);
12394 return NULL;
12395 }
12396 tmp->sig_pvt = analog_p;
12397 }
12398 #if defined(HAVE_SS7)
12399 if (chan_sig == SIG_SS7) {
12400 struct dahdi_ss7 *ss7;
12401 int clear = 0;
12402
12403 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12404 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12405 destroy_dahdi_pvt(tmp);
12406 return NULL;
12407 }
12408
12409 ss7 = ss7_resolve_linkset(cur_linkset);
12410 if (!ss7) {
12411 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12412 destroy_dahdi_pvt(tmp);
12413 return NULL;
12414 }
12415 ss7->ss7.span = cur_linkset;
12416 if (cur_cicbeginswith < 0) {
12417 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12418 destroy_dahdi_pvt(tmp);
12419 return NULL;
12420 }
12421 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12422 if (!ss7_chan) {
12423 destroy_dahdi_pvt(tmp);
12424 return NULL;
12425 }
12426 tmp->sig_pvt = ss7_chan;
12427 tmp->ss7 = &ss7->ss7;
12428
12429 ss7_chan->channel = tmp->channel;
12430 ss7_chan->cic = cur_cicbeginswith++;
12431
12432
12433 ss7_chan->dpc = cur_defaultdpc;
12434
12435 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12436
12437 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12438 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12439 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12440 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12441
12442 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12443 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12444 }
12445 #endif
12446 #ifdef HAVE_OPENR2
12447 if (chan_sig == SIG_MFCR2) {
12448 struct dahdi_mfcr2 *r2_link;
12449 r2_link = dahdi_r2_get_link();
12450 if (!r2_link) {
12451 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12452 destroy_dahdi_pvt(tmp);
12453 return NULL;
12454 }
12455 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12456 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12457 destroy_dahdi_pvt(tmp);
12458 return NULL;
12459 }
12460 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12461 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12462 destroy_dahdi_pvt(tmp);
12463 return NULL;
12464 }
12465 r2_link->pvts[r2_link->numchans++] = tmp;
12466 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12467 tmp->subs[SUB_REAL].dfd,
12468 NULL, NULL);
12469 if (!tmp->r2chan) {
12470 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12471 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12472 destroy_dahdi_pvt(tmp);
12473 return NULL;
12474 }
12475 tmp->mfcr2 = r2_link;
12476 if (conf->mfcr2.call_files) {
12477 openr2_chan_enable_call_files(tmp->r2chan);
12478 }
12479 openr2_chan_set_client_data(tmp->r2chan, tmp);
12480
12481 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12482 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12483 tmp->mfcr2_category = conf->mfcr2.category;
12484 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12485 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12486 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12487 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12488 tmp->mfcr2call = 0;
12489 tmp->mfcr2_dnis_index = 0;
12490 tmp->mfcr2_ani_index = 0;
12491 r2_link->monitored_count++;
12492 }
12493 #endif
12494 #ifdef HAVE_PRI
12495 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12496 int offset;
12497 int matchesdchan;
12498 int x,y;
12499 int myswitchtype = 0;
12500
12501 offset = 0;
12502 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12503 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12504 destroy_dahdi_pvt(tmp);
12505 return NULL;
12506 }
12507 if (span >= NUM_SPANS) {
12508 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12509 destroy_dahdi_pvt(tmp);
12510 return NULL;
12511 } else {
12512 si.spanno = 0;
12513 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12514 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12515 destroy_dahdi_pvt(tmp);
12516 return NULL;
12517 }
12518
12519 tmp->logicalspan = pris[span].prilogicalspan;
12520 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12521 if (span < 0) {
12522 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12523 destroy_dahdi_pvt(tmp);
12524 return NULL;
12525 }
12526 myswitchtype = conf->pri.pri.switchtype;
12527
12528 matchesdchan=0;
12529 for (x = 0; x < NUM_SPANS; x++) {
12530 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12531 if (pris[x].dchannels[y] == tmp->channel) {
12532 matchesdchan = 1;
12533 break;
12534 }
12535 }
12536 }
12537 if (!matchesdchan) {
12538 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12539 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12540 destroy_dahdi_pvt(tmp);
12541 return NULL;
12542 }
12543 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12544 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12545 destroy_dahdi_pvt(tmp);
12546 return NULL;
12547 }
12548 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12549 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));
12550 destroy_dahdi_pvt(tmp);
12551 return NULL;
12552 }
12553 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12554 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12555 destroy_dahdi_pvt(tmp);
12556 return NULL;
12557 }
12558 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12559 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12560 destroy_dahdi_pvt(tmp);
12561 return NULL;
12562 }
12563 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12564 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12565 destroy_dahdi_pvt(tmp);
12566 return NULL;
12567 }
12568 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12569 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12570 destroy_dahdi_pvt(tmp);
12571 return NULL;
12572 }
12573 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12574 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12575 pris[span].pri.trunkgroup);
12576 destroy_dahdi_pvt(tmp);
12577 return NULL;
12578 }
12579
12580 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12581 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12582 if (!pri_chan) {
12583 destroy_dahdi_pvt(tmp);
12584 return NULL;
12585 }
12586 tmp->sig_pvt = pri_chan;
12587 tmp->pri = &pris[span].pri;
12588
12589 tmp->priexclusive = conf->chan.priexclusive;
12590
12591 if (!tmp->pri->cc_params) {
12592 tmp->pri->cc_params = ast_cc_config_params_init();
12593 if (!tmp->pri->cc_params) {
12594 destroy_dahdi_pvt(tmp);
12595 return NULL;
12596 }
12597 }
12598 ast_cc_copy_config_params(tmp->pri->cc_params,
12599 conf->chan.cc_params);
12600
12601 pris[span].pri.sig = chan_sig;
12602 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12603 pris[span].pri.switchtype = myswitchtype;
12604 pris[span].pri.nsf = conf->pri.pri.nsf;
12605 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12606 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12607 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12608 pris[span].pri.minunused = conf->pri.pri.minunused;
12609 pris[span].pri.minidle = conf->pri.pri.minidle;
12610 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12611 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12612 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12613 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12614 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12615 #endif
12616 #ifdef HAVE_PRI_INBANDDISCONNECT
12617 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12618 #endif
12619 #if defined(HAVE_PRI_CALL_HOLD)
12620 pris[span].pri.hold_disconnect_transfer =
12621 conf->pri.pri.hold_disconnect_transfer;
12622 #endif
12623 #if defined(HAVE_PRI_CCSS)
12624 pris[span].pri.cc_ptmp_recall_mode =
12625 conf->pri.pri.cc_ptmp_recall_mode;
12626 pris[span].pri.cc_qsig_signaling_link_req =
12627 conf->pri.pri.cc_qsig_signaling_link_req;
12628 pris[span].pri.cc_qsig_signaling_link_rsp =
12629 conf->pri.pri.cc_qsig_signaling_link_rsp;
12630 #endif
12631 #if defined(HAVE_PRI_CALL_WAITING)
12632 pris[span].pri.max_call_waiting_calls =
12633 conf->pri.pri.max_call_waiting_calls;
12634 pris[span].pri.allow_call_waiting_calls =
12635 conf->pri.pri.allow_call_waiting_calls;
12636 #endif
12637 pris[span].pri.transfer = conf->chan.transfer;
12638 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12639 #if defined(HAVE_PRI_L2_PERSISTENCE)
12640 pris[span].pri.l2_persistence = conf->pri.pri.l2_persistence;
12641 #endif
12642 #if defined(HAVE_PRI_AOC_EVENTS)
12643 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12644 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12645 #endif
12646 if (chan_sig == SIG_BRI_PTMP) {
12647 pris[span].pri.layer1_ignored = conf->pri.pri.layer1_ignored;
12648 } else {
12649
12650 pris[span].pri.layer1_ignored = 0;
12651 }
12652 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12653 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12654 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12655 #if defined(HAVE_PRI_MWI)
12656 ast_copy_string(pris[span].pri.mwi_mailboxes,
12657 conf->pri.pri.mwi_mailboxes,
12658 sizeof(pris[span].pri.mwi_mailboxes));
12659 #endif
12660 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12661 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12662 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12663 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12664 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12665 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12666 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12667 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12668
12669 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12670 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12671 }
12672
12673 #if defined(HAVE_PRI_CALL_WAITING)
12674
12675 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12676 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12677 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12678 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12679 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12680 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12681 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12682 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12683 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12684 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12685 #endif
12686 } else {
12687 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12688 destroy_dahdi_pvt(tmp);
12689 return NULL;
12690 }
12691 }
12692 }
12693 #endif
12694 } else {
12695
12696 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));
12697 chan_sig = tmp->sig;
12698 if (tmp->subs[SUB_REAL].dfd > -1) {
12699 memset(&p, 0, sizeof(p));
12700 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12701 }
12702 }
12703
12704 switch (chan_sig) {
12705 case SIG_FXSKS:
12706 case SIG_FXSLS:
12707 case SIG_EM:
12708 case SIG_EM_E1:
12709 case SIG_EMWINK:
12710 case SIG_FEATD:
12711 case SIG_FEATDMF:
12712 case SIG_FEATDMF_TA:
12713 case SIG_FEATB:
12714 case SIG_E911:
12715 case SIG_SF:
12716 case SIG_SFWINK:
12717 case SIG_FGC_CAMA:
12718 case SIG_FGC_CAMAMF:
12719 case SIG_SF_FEATD:
12720 case SIG_SF_FEATDMF:
12721 case SIG_SF_FEATB:
12722 p.starttime = 250;
12723 break;
12724 }
12725
12726 if (tmp->radio) {
12727
12728 p.channo = channel;
12729 p.rxwinktime = 1;
12730 p.rxflashtime = 1;
12731 p.starttime = 1;
12732 p.debouncetime = 5;
12733 } else {
12734 p.channo = channel;
12735
12736 if (conf->timing.prewinktime >= 0)
12737 p.prewinktime = conf->timing.prewinktime;
12738 if (conf->timing.preflashtime >= 0)
12739 p.preflashtime = conf->timing.preflashtime;
12740 if (conf->timing.winktime >= 0)
12741 p.winktime = conf->timing.winktime;
12742 if (conf->timing.flashtime >= 0)
12743 p.flashtime = conf->timing.flashtime;
12744 if (conf->timing.starttime >= 0)
12745 p.starttime = conf->timing.starttime;
12746 if (conf->timing.rxwinktime >= 0)
12747 p.rxwinktime = conf->timing.rxwinktime;
12748 if (conf->timing.rxflashtime >= 0)
12749 p.rxflashtime = conf->timing.rxflashtime;
12750 if (conf->timing.debouncetime >= 0)
12751 p.debouncetime = conf->timing.debouncetime;
12752 }
12753
12754
12755 if (tmp->subs[SUB_REAL].dfd >= 0)
12756 {
12757 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12758 if (res < 0) {
12759 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12760 destroy_dahdi_pvt(tmp);
12761 return NULL;
12762 }
12763 }
12764 #if 1
12765 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12766 memset(&bi, 0, sizeof(bi));
12767 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12768 if (!res) {
12769 bi.txbufpolicy = conf->chan.buf_policy;
12770 bi.rxbufpolicy = conf->chan.buf_policy;
12771 bi.numbufs = conf->chan.buf_no;
12772 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12773 if (res < 0) {
12774 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12775 }
12776 } else {
12777 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12778 }
12779 tmp->buf_policy = conf->chan.buf_policy;
12780 tmp->buf_no = conf->chan.buf_no;
12781 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12782 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12783 tmp->faxbuf_no = conf->chan.faxbuf_no;
12784
12785
12786
12787
12788 tmp->bufsize = bi.bufsize;
12789 }
12790 #endif
12791 tmp->immediate = conf->chan.immediate;
12792 tmp->transfertobusy = conf->chan.transfertobusy;
12793 if (chan_sig & __DAHDI_SIG_FXS) {
12794 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12795 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12796 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12797 }
12798 tmp->ringt_base = ringt_base;
12799 tmp->firstradio = 0;
12800 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12801 tmp->permcallwaiting = conf->chan.callwaiting;
12802 else
12803 tmp->permcallwaiting = 0;
12804
12805 tmp->destroy = 0;
12806 tmp->drings = conf->chan.drings;
12807
12808
12809 if (tmp->drings.ringnum[0].range == 0)
12810 tmp->drings.ringnum[0].range = 10;
12811 if (tmp->drings.ringnum[1].range == 0)
12812 tmp->drings.ringnum[1].range = 10;
12813 if (tmp->drings.ringnum[2].range == 0)
12814 tmp->drings.ringnum[2].range = 10;
12815
12816 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12817 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12818 tmp->threewaycalling = conf->chan.threewaycalling;
12819 tmp->adsi = conf->chan.adsi;
12820 tmp->use_smdi = conf->chan.use_smdi;
12821 tmp->permhidecallerid = conf->chan.hidecallerid;
12822 tmp->hidecalleridname = conf->chan.hidecalleridname;
12823 tmp->callreturn = conf->chan.callreturn;
12824 tmp->echocancel = conf->chan.echocancel;
12825 tmp->echotraining = conf->chan.echotraining;
12826 tmp->pulse = conf->chan.pulse;
12827 if (tmp->echocancel.head.tap_length) {
12828 tmp->echocanbridged = conf->chan.echocanbridged;
12829 } else {
12830 if (conf->chan.echocanbridged)
12831 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12832 tmp->echocanbridged = 0;
12833 }
12834 tmp->busydetect = conf->chan.busydetect;
12835 tmp->busycount = conf->chan.busycount;
12836 tmp->busy_tonelength = conf->chan.busy_tonelength;
12837 tmp->busy_quietlength = conf->chan.busy_quietlength;
12838 tmp->callprogress = conf->chan.callprogress;
12839 tmp->waitfordialtone = conf->chan.waitfordialtone;
12840 tmp->cancallforward = conf->chan.cancallforward;
12841 tmp->dtmfrelax = conf->chan.dtmfrelax;
12842 tmp->callwaiting = tmp->permcallwaiting;
12843 tmp->hidecallerid = tmp->permhidecallerid;
12844 tmp->channel = channel;
12845 tmp->stripmsd = conf->chan.stripmsd;
12846 tmp->use_callerid = conf->chan.use_callerid;
12847 tmp->cid_signalling = conf->chan.cid_signalling;
12848 tmp->cid_start = conf->chan.cid_start;
12849 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12850 tmp->restrictcid = conf->chan.restrictcid;
12851 tmp->use_callingpres = conf->chan.use_callingpres;
12852 if (tmp->usedistinctiveringdetection) {
12853 if (!tmp->use_callerid) {
12854 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12855 tmp->use_callerid = 1;
12856 }
12857 }
12858
12859 if (tmp->cid_signalling == CID_SIG_SMDI) {
12860 if (!tmp->use_smdi) {
12861 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12862 tmp->use_smdi = 1;
12863 }
12864 }
12865 if (tmp->use_smdi) {
12866 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12867 if (!(tmp->smdi_iface)) {
12868 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12869 tmp->use_smdi = 0;
12870 }
12871 }
12872
12873 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12874 tmp->amaflags = conf->chan.amaflags;
12875 if (!here) {
12876 tmp->confno = -1;
12877 tmp->propconfno = -1;
12878 }
12879 tmp->canpark = conf->chan.canpark;
12880 tmp->transfer = conf->chan.transfer;
12881 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12882 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12883 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12884 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12885 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12886 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12887 tmp->cid_ton = 0;
12888 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12889 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12890 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12891 } else {
12892 tmp->cid_num[0] = '\0';
12893 tmp->cid_name[0] = '\0';
12894 }
12895 #if defined(HAVE_PRI)
12896 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12897 tmp->cid_tag[0] = '\0';
12898 } else
12899 #endif
12900 {
12901 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12902 }
12903 tmp->cid_subaddr[0] = '\0';
12904 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12905 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12906 char *mailbox, *context;
12907 mailbox = context = ast_strdupa(tmp->mailbox);
12908 strsep(&context, "@");
12909 if (ast_strlen_zero(context))
12910 context = "default";
12911 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12912 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12913 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12914 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12915 AST_EVENT_IE_END);
12916 }
12917 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12918 tmp->mwisend_setting = conf->chan.mwisend_setting;
12919 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12920 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12921 #endif
12922
12923 tmp->group = conf->chan.group;
12924 tmp->callgroup = conf->chan.callgroup;
12925 tmp->pickupgroup= conf->chan.pickupgroup;
12926 if (conf->chan.vars) {
12927 struct ast_variable *v, *tmpvar;
12928 for (v = conf->chan.vars ; v ; v = v->next) {
12929 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12930 tmpvar->next = tmp->vars;
12931 tmp->vars = tmpvar;
12932 }
12933 }
12934 }
12935 tmp->cid_rxgain = conf->chan.cid_rxgain;
12936 tmp->rxgain = conf->chan.rxgain;
12937 tmp->txgain = conf->chan.txgain;
12938 tmp->txdrc = conf->chan.txdrc;
12939 tmp->rxdrc = conf->chan.rxdrc;
12940 tmp->tonezone = conf->chan.tonezone;
12941 if (tmp->subs[SUB_REAL].dfd > -1) {
12942 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12943 if (tmp->dsp)
12944 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12945 update_conf(tmp);
12946 if (!here) {
12947 switch (chan_sig) {
12948 case SIG_PRI_LIB_HANDLE_CASES:
12949 case SIG_SS7:
12950 case SIG_MFCR2:
12951 break;
12952 default:
12953
12954 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12955 break;
12956 }
12957 }
12958 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12959 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12960
12961 switch (tmp->sig) {
12962 #ifdef HAVE_PRI
12963 case SIG_PRI_LIB_HANDLE_CASES:
12964 sig_pri_set_alarm(tmp->sig_pvt, 1);
12965 break;
12966 #endif
12967 #if defined(HAVE_SS7)
12968 case SIG_SS7:
12969 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12970 break;
12971 #endif
12972 default:
12973
12974 analog_p = tmp->sig_pvt;
12975 if (analog_p) {
12976 analog_p->inalarm = 1;
12977 }
12978 tmp->inalarm = 1;
12979 break;
12980 }
12981 handle_alarms(tmp, res);
12982 }
12983 }
12984
12985 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12986 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12987 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12988 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12989 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12990
12991 if (!here) {
12992 tmp->locallyblocked = 0;
12993 tmp->remotelyblocked = 0;
12994 switch (tmp->sig) {
12995 #if defined(HAVE_PRI)
12996 case SIG_PRI_LIB_HANDLE_CASES:
12997 tmp->inservice = 1;
12998 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12999 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
13000 if (chan_sig == SIG_PRI) {
13001 char db_chan_name[20];
13002 char db_answer[5];
13003
13004
13005
13006
13007
13008 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
13009 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
13010 unsigned *why;
13011
13012 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
13013 if (tmp->pri->enable_service_message_support) {
13014 char state;
13015
13016 sscanf(db_answer, "%1c:%30u", &state, why);
13017
13018
13019 *why &= (SRVST_NEAREND | SRVST_FAREND);
13020 }
13021 if (!*why) {
13022 ast_db_del(db_chan_name, SRVST_DBKEY);
13023 }
13024 }
13025 }
13026 #endif
13027 break;
13028 #endif
13029 #if defined(HAVE_SS7)
13030 case SIG_SS7:
13031 tmp->inservice = 0;
13032 break;
13033 #endif
13034 default:
13035
13036 tmp->inservice = 1;
13037 break;
13038 }
13039 }
13040
13041 switch (tmp->sig) {
13042 #if defined(HAVE_PRI)
13043 case SIG_PRI_LIB_HANDLE_CASES:
13044 if (pri_chan) {
13045 pri_chan->channel = tmp->channel;
13046 pri_chan->hidecallerid = tmp->hidecallerid;
13047 pri_chan->hidecalleridname = tmp->hidecalleridname;
13048 pri_chan->immediate = tmp->immediate;
13049 pri_chan->inalarm = tmp->inalarm;
13050 pri_chan->priexclusive = tmp->priexclusive;
13051 pri_chan->priindication_oob = tmp->priindication_oob;
13052 pri_chan->use_callerid = tmp->use_callerid;
13053 pri_chan->use_callingpres = tmp->use_callingpres;
13054 ast_copy_string(pri_chan->context, tmp->context,
13055 sizeof(pri_chan->context));
13056 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
13057 sizeof(pri_chan->mohinterpret));
13058 pri_chan->stripmsd = tmp->stripmsd;
13059 }
13060 break;
13061 #endif
13062 #if defined(HAVE_SS7)
13063 case SIG_SS7:
13064 if (ss7_chan) {
13065 ss7_chan->inalarm = tmp->inalarm;
13066
13067 ss7_chan->stripmsd = tmp->stripmsd;
13068 ss7_chan->hidecallerid = tmp->hidecallerid;
13069 ss7_chan->use_callerid = tmp->use_callerid;
13070 ss7_chan->use_callingpres = tmp->use_callingpres;
13071 ss7_chan->immediate = tmp->immediate;
13072 ss7_chan->locallyblocked = tmp->locallyblocked;
13073 ss7_chan->remotelyblocked = tmp->remotelyblocked;
13074 ast_copy_string(ss7_chan->context, tmp->context,
13075 sizeof(ss7_chan->context));
13076 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
13077 sizeof(ss7_chan->mohinterpret));
13078 }
13079 break;
13080 #endif
13081 default:
13082
13083 analog_p = tmp->sig_pvt;
13084 if (analog_p) {
13085 analog_p->channel = tmp->channel;
13086 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
13087 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
13088 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
13089 analog_p->permcallwaiting = conf->chan.callwaiting;
13090 analog_p->callreturn = conf->chan.callreturn;
13091 analog_p->cancallforward = conf->chan.cancallforward;
13092 analog_p->canpark = conf->chan.canpark;
13093 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
13094 analog_p->immediate = conf->chan.immediate;
13095 analog_p->permhidecallerid = conf->chan.permhidecallerid;
13096 analog_p->pulse = conf->chan.pulse;
13097 analog_p->threewaycalling = conf->chan.threewaycalling;
13098 analog_p->transfer = conf->chan.transfer;
13099 analog_p->transfertobusy = conf->chan.transfertobusy;
13100 analog_p->use_callerid = tmp->use_callerid;
13101 analog_p->use_smdi = tmp->use_smdi;
13102 analog_p->smdi_iface = tmp->smdi_iface;
13103 analog_p->outsigmod = ANALOG_SIG_NONE;
13104 analog_p->echotraining = conf->chan.echotraining;
13105 analog_p->cid_signalling = conf->chan.cid_signalling;
13106 analog_p->stripmsd = conf->chan.stripmsd;
13107 switch (conf->chan.cid_start) {
13108 case CID_START_POLARITY:
13109 analog_p->cid_start = ANALOG_CID_START_POLARITY;
13110 break;
13111 case CID_START_POLARITY_IN:
13112 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
13113 break;
13114 case CID_START_DTMF_NOALERT:
13115 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
13116 break;
13117 default:
13118 analog_p->cid_start = ANALOG_CID_START_RING;
13119 break;
13120 }
13121 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
13122 analog_p->ringt = conf->chan.ringt;
13123 analog_p->ringt_base = ringt_base;
13124 analog_p->onhooktime = time(NULL);
13125 if (chan_sig & __DAHDI_SIG_FXO) {
13126 memset(&p, 0, sizeof(p));
13127 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
13128 if (!res) {
13129 analog_p->fxsoffhookstate = p.rxisoffhook;
13130 }
13131 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
13132 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
13133 #endif
13134 }
13135 analog_p->msgstate = -1;
13136
13137 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
13138 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
13139 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
13140
13141 analog_config_complete(analog_p);
13142 }
13143 break;
13144 }
13145 #if defined(HAVE_PRI)
13146 if (tmp->channel == CHAN_PSEUDO) {
13147
13148
13149
13150
13151 dahdi_pseudo_parms.buf_no = tmp->buf_no;
13152 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
13153 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
13154 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
13155 }
13156 #endif
13157 }
13158 if (tmp && !here) {
13159
13160 dahdi_iflist_insert(tmp);
13161 }
13162 return tmp;
13163 }
13164
13165 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
13166 {
13167 #if defined(HAVE_PRI)
13168 if (0 < span) {
13169
13170 if (!p->pri || p->pri->span != span) {
13171 return 0;
13172 }
13173 if (!groupmatch && channelmatch == -1) {
13174
13175 *groupmatched = 1;
13176 return 1;
13177 }
13178 }
13179 #endif
13180
13181 if (groupmatch) {
13182 if ((p->group & groupmatch) != groupmatch)
13183
13184 return 0;
13185 *groupmatched = 1;
13186 }
13187
13188 if (channelmatch != -1) {
13189 if (p->channel != channelmatch)
13190
13191 return 0;
13192 *channelmatched = 1;
13193 }
13194
13195 return 1;
13196 }
13197
13198 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
13199 {
13200 struct dahdi_pvt *p = *pvt;
13201
13202 if (p->inalarm)
13203 return 0;
13204
13205 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
13206 return analog_available(p->sig_pvt);
13207
13208 switch (p->sig) {
13209 #if defined(HAVE_PRI)
13210 case SIG_PRI_LIB_HANDLE_CASES:
13211 {
13212 struct sig_pri_chan *pvt_chan;
13213 int res;
13214
13215 pvt_chan = p->sig_pvt;
13216 res = sig_pri_available(&pvt_chan, is_specific_channel);
13217 *pvt = pvt_chan->chan_pvt;
13218 return res;
13219 }
13220 #endif
13221 #if defined(HAVE_SS7)
13222 case SIG_SS7:
13223 return sig_ss7_available(p->sig_pvt);
13224 #endif
13225 default:
13226 break;
13227 }
13228
13229 if (p->locallyblocked || p->remotelyblocked) {
13230 return 0;
13231 }
13232
13233
13234 if (!p->owner) {
13235 #ifdef HAVE_OPENR2
13236
13237 if (p->mfcr2) {
13238 if (p->mfcr2call) {
13239 return 0;
13240 } else {
13241 return 1;
13242 }
13243 }
13244 #endif
13245 return 1;
13246 }
13247
13248 return 0;
13249 }
13250
13251 #if defined(HAVE_PRI)
13252 #if defined(HAVE_PRI_CALL_WAITING)
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
13266 {
13267 struct dahdi_pvt *pvt = priv;
13268
13269 pvt->stripmsd = pri->ch_cfg.stripmsd;
13270 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
13271 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
13272 pvt->immediate = pri->ch_cfg.immediate;
13273 pvt->priexclusive = pri->ch_cfg.priexclusive;
13274 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
13275 pvt->use_callerid = pri->ch_cfg.use_callerid;
13276 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
13277 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
13278 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
13279 }
13280 #endif
13281 #endif
13282
13283 #if defined(HAVE_PRI)
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
13297 {
13298 int pvt_idx;
13299 int res;
13300 unsigned idx;
13301 struct dahdi_pvt *pvt;
13302 struct sig_pri_chan *chan;
13303 struct dahdi_bufferinfo bi;
13304
13305 static int nobch_channel = CHAN_PSEUDO;
13306
13307
13308 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
13309 if (!pri->pvts[pvt_idx]) {
13310 break;
13311 }
13312 }
13313 if (pri->numchans == pvt_idx) {
13314 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
13315 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
13316 return -1;
13317 }
13318
13319
13320 pri->pvts[pvt_idx] = NULL;
13321 ++pri->numchans;
13322 }
13323
13324 pvt = ast_calloc(1, sizeof(*pvt));
13325 if (!pvt) {
13326 return -1;
13327 }
13328 pvt->cc_params = ast_cc_config_params_init();
13329 if (!pvt->cc_params) {
13330 ast_free(pvt);
13331 return -1;
13332 }
13333 ast_mutex_init(&pvt->lock);
13334 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
13335 pvt->subs[idx].dfd = -1;
13336 }
13337 pvt->buf_no = dahdi_pseudo_parms.buf_no;
13338 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
13339 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
13340 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
13341
13342 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
13343 if (!chan) {
13344 destroy_dahdi_pvt(pvt);
13345 return -1;
13346 }
13347 chan->no_b_channel = 1;
13348
13349
13350
13351
13352
13353
13354 pvt->law_default = DAHDI_LAW_ALAW;
13355
13356 pvt->sig = pri->sig;
13357 pvt->outsigmod = -1;
13358 pvt->pri = pri;
13359 pvt->sig_pvt = chan;
13360 pri->pvts[pvt_idx] = chan;
13361
13362 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13363 if (pvt->subs[SUB_REAL].dfd < 0) {
13364 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
13365 strerror(errno));
13366 destroy_dahdi_pvt(pvt);
13367 return -1;
13368 }
13369 memset(&bi, 0, sizeof(bi));
13370 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13371 if (!res) {
13372 pvt->bufsize = bi.bufsize;
13373 bi.txbufpolicy = pvt->buf_policy;
13374 bi.rxbufpolicy = pvt->buf_policy;
13375 bi.numbufs = pvt->buf_no;
13376 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13377 if (res < 0) {
13378 ast_log(LOG_WARNING,
13379 "Unable to set buffer policy on no B channel interface: %s\n",
13380 strerror(errno));
13381 }
13382 } else
13383 ast_log(LOG_WARNING,
13384 "Unable to check buffer policy on no B channel interface: %s\n",
13385 strerror(errno));
13386
13387 --nobch_channel;
13388 if (CHAN_PSEUDO < nobch_channel) {
13389 nobch_channel = CHAN_PSEUDO - 1;
13390 }
13391 pvt->channel = nobch_channel;
13392 pvt->span = pri->span;
13393 chan->channel = pvt->channel;
13394
13395 dahdi_nobch_insert(pri, pvt);
13396
13397 return pvt_idx;
13398 }
13399 #endif
13400
13401
13402
13403
13404
13405
13406 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13407 {
13408 struct dahdi_pvt *p;
13409 struct dahdi_bufferinfo bi;
13410 int res;
13411
13412 p = ast_malloc(sizeof(*p));
13413 if (!p) {
13414 return NULL;
13415 }
13416 *p = *src;
13417
13418
13419 p->cc_params = ast_cc_config_params_init();
13420 if (!p->cc_params) {
13421 ast_free(p);
13422 return NULL;
13423 }
13424 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13425
13426 p->which_iflist = DAHDI_IFLIST_NONE;
13427 p->next = NULL;
13428 p->prev = NULL;
13429 ast_mutex_init(&p->lock);
13430 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13431 if (p->subs[SUB_REAL].dfd < 0) {
13432 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13433 destroy_dahdi_pvt(p);
13434 return NULL;
13435 }
13436 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13437 if (!res) {
13438 bi.txbufpolicy = src->buf_policy;
13439 bi.rxbufpolicy = src->buf_policy;
13440 bi.numbufs = src->buf_no;
13441 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13442 if (res < 0) {
13443 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13444 }
13445 } else
13446 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13447 p->destroy = 1;
13448 dahdi_iflist_insert(p);
13449 return p;
13450 }
13451
13452 struct dahdi_starting_point {
13453
13454 ast_group_t groupmatch;
13455
13456 int channelmatch;
13457
13458 int rr_starting_point;
13459
13460 int span;
13461
13462 int cadance;
13463
13464 char opt;
13465
13466 char backwards;
13467
13468 char roundrobin;
13469 };
13470 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13471 {
13472 char *dest;
13473 char *s;
13474 int x;
13475 int res = 0;
13476 struct dahdi_pvt *p;
13477 char *subdir = NULL;
13478 AST_DECLARE_APP_ARGS(args,
13479 AST_APP_ARG(group);
13480
13481
13482 AST_APP_ARG(other);
13483 );
13484
13485
13486
13487
13488
13489
13490
13491
13492
13493
13494
13495
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508 if (data) {
13509 dest = ast_strdupa(data);
13510 } else {
13511 ast_log(LOG_WARNING, "Channel requested with no data\n");
13512 return NULL;
13513 }
13514 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13515 if (!args.argc || ast_strlen_zero(args.group)) {
13516 ast_log(LOG_WARNING, "No channel/group specified\n");
13517 return NULL;
13518 }
13519
13520
13521 memset(param, 0, sizeof(*param));
13522 param->channelmatch = -1;
13523
13524 if (strchr(args.group, '!') != NULL) {
13525 char *prev = args.group;
13526 while ((s = strchr(prev, '!')) != NULL) {
13527 *s++ = '/';
13528 prev = s;
13529 }
13530 *(prev - 1) = '\0';
13531 subdir = args.group;
13532 args.group = prev;
13533 } else if (args.group[0] == 'i') {
13534
13535 res = sscanf(args.group + 1, "%30d", &x);
13536 if (res < 1) {
13537 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13538 return NULL;
13539 }
13540 param->span = x;
13541
13542
13543 s = strchr(args.group, '-');
13544 if (!s) {
13545
13546 return iflist;
13547 }
13548 args.group = s + 1;
13549 res = 0;
13550 }
13551 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13552
13553 s = args.group + 1;
13554 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13555 if (res < 1) {
13556 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13557 return NULL;
13558 }
13559 param->groupmatch = ((ast_group_t) 1 << x);
13560
13561 if (toupper(args.group[0]) == 'G') {
13562 if (args.group[0] == 'G') {
13563 param->backwards = 1;
13564 p = ifend;
13565 } else
13566 p = iflist;
13567 } else {
13568 if (ARRAY_LEN(round_robin) <= x) {
13569 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13570 x, data);
13571 return NULL;
13572 }
13573 if (args.group[0] == 'R') {
13574 param->backwards = 1;
13575 p = round_robin[x] ? round_robin[x]->prev : ifend;
13576 if (!p)
13577 p = ifend;
13578 } else {
13579 p = round_robin[x] ? round_robin[x]->next : iflist;
13580 if (!p)
13581 p = iflist;
13582 }
13583 param->roundrobin = 1;
13584 param->rr_starting_point = x;
13585 }
13586 } else {
13587 s = args.group;
13588 if (!strcasecmp(s, "pseudo")) {
13589
13590 x = CHAN_PSEUDO;
13591 param->channelmatch = x;
13592 } else {
13593 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13594 if (res < 1) {
13595 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13596 return NULL;
13597 } else {
13598 param->channelmatch = x;
13599 }
13600 }
13601 if (subdir) {
13602 char path[PATH_MAX];
13603 struct stat stbuf;
13604
13605 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13606 subdir, param->channelmatch);
13607 if (stat(path, &stbuf) < 0) {
13608 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13609 path, strerror(errno));
13610 return NULL;
13611 }
13612 if (!S_ISCHR(stbuf.st_mode)) {
13613 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13614 path);
13615 return NULL;
13616 }
13617 param->channelmatch = minor(stbuf.st_rdev);
13618 }
13619
13620 p = iflist;
13621 }
13622
13623 if (param->opt == 'r' && res < 3) {
13624 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13625 param->opt = '\0';
13626 }
13627
13628 return p;
13629 }
13630
13631 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13632 {
13633 int callwait = 0;
13634 struct dahdi_pvt *p;
13635 struct ast_channel *tmp = NULL;
13636 struct dahdi_pvt *exitpvt;
13637 int channelmatched = 0;
13638 int groupmatched = 0;
13639 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13640 int transcapdigital = 0;
13641 #endif
13642 struct dahdi_starting_point start;
13643
13644 ast_mutex_lock(&iflock);
13645 p = determine_starting_point(data, &start);
13646 if (!p) {
13647
13648 ast_mutex_unlock(&iflock);
13649 return NULL;
13650 }
13651
13652
13653 exitpvt = p;
13654 while (p && !tmp) {
13655 if (start.roundrobin)
13656 round_robin[start.rr_starting_point] = p;
13657
13658 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13659 && available(&p, channelmatched)) {
13660 ast_debug(1, "Using channel %d\n", p->channel);
13661
13662 callwait = (p->owner != NULL);
13663 #ifdef HAVE_OPENR2
13664 if (p->mfcr2) {
13665 ast_mutex_lock(&p->lock);
13666 if (p->mfcr2call) {
13667 ast_mutex_unlock(&p->lock);
13668 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13669 goto next;
13670 }
13671 p->mfcr2call = 1;
13672 ast_mutex_unlock(&p->lock);
13673 }
13674 #endif
13675 if (p->channel == CHAN_PSEUDO) {
13676 p = duplicate_pseudo(p);
13677 if (!p) {
13678 break;
13679 }
13680 }
13681
13682 p->distinctivering = 0;
13683
13684 switch (start.opt) {
13685 case '\0':
13686
13687 break;
13688 case 'c':
13689
13690 p->confirmanswer = 1;
13691 break;
13692 case 'r':
13693
13694 p->distinctivering = start.cadance;
13695 break;
13696 case 'd':
13697 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13698
13699 transcapdigital = AST_TRANS_CAP_DIGITAL;
13700 #endif
13701 break;
13702 default:
13703 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13704 break;
13705 }
13706
13707 p->outgoing = 1;
13708 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13709 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13710 #ifdef HAVE_PRI
13711 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13712
13713
13714
13715
13716
13717 ast_mutex_lock(&p->lock);
13718 ast_mutex_unlock(&p->lock);
13719
13720 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13721 sizeof(p->dnid));
13722 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13723 #endif
13724 #if defined(HAVE_SS7)
13725 } else if (p->sig == SIG_SS7) {
13726 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13727 #endif
13728 } else {
13729 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13730 }
13731 if (!tmp) {
13732 p->outgoing = 0;
13733 #if defined(HAVE_PRI)
13734 switch (p->sig) {
13735 case SIG_PRI_LIB_HANDLE_CASES:
13736 #if defined(HAVE_PRI_CALL_WAITING)
13737 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13738 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13739 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13740 }
13741 #endif
13742
13743
13744
13745
13746 ((struct sig_pri_chan *) p->sig_pvt)->allocated = 0;
13747 break;
13748 default:
13749 break;
13750 }
13751 #endif
13752 } else {
13753 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13754 }
13755 break;
13756 }
13757 #ifdef HAVE_OPENR2
13758 next:
13759 #endif
13760 if (start.backwards) {
13761 p = p->prev;
13762 if (!p)
13763 p = ifend;
13764 } else {
13765 p = p->next;
13766 if (!p)
13767 p = iflist;
13768 }
13769
13770 if (p == exitpvt)
13771 break;
13772 }
13773 ast_mutex_unlock(&iflock);
13774 restart_monitor();
13775 if (cause && !tmp) {
13776 if (callwait || channelmatched) {
13777 *cause = AST_CAUSE_BUSY;
13778 } else if (groupmatched) {
13779 *cause = AST_CAUSE_CONGESTION;
13780 } else {
13781
13782
13783
13784
13785 }
13786 }
13787
13788 return tmp;
13789 }
13790
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800
13801 static int dahdi_devicestate(void *data)
13802 {
13803 #if defined(HAVE_PRI)
13804 char *device;
13805 unsigned span;
13806 int res;
13807
13808 device = data;
13809
13810 if (*device != 'I') {
13811
13812 return AST_DEVICE_UNKNOWN;
13813 }
13814 res = sscanf(device, "I%30u", &span);
13815 if (res != 1 || !span || NUM_SPANS < span) {
13816
13817 return AST_DEVICE_UNKNOWN;
13818 }
13819 device = strchr(device, '/');
13820 if (!device) {
13821
13822 return AST_DEVICE_UNKNOWN;
13823 }
13824
13825
13826
13827
13828
13829 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13830 ++device;
13831 if (!strcmp(device, "congestion"))
13832 #endif
13833 {
13834 return pris[span - 1].pri.congestion_devstate;
13835 }
13836 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13837 else if (!strcmp(device, "threshold")) {
13838 return pris[span - 1].pri.threshold_devstate;
13839 }
13840 return AST_DEVICE_UNKNOWN;
13841 #endif
13842 #else
13843 return AST_DEVICE_UNKNOWN;
13844 #endif
13845 }
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13864 {
13865 struct dahdi_pvt *p;
13866 struct dahdi_pvt *exitpvt;
13867 struct dahdi_starting_point start;
13868 int groupmatched = 0;
13869 int channelmatched = 0;
13870
13871 ast_mutex_lock(&iflock);
13872 p = determine_starting_point(dest, &start);
13873 if (!p) {
13874 ast_mutex_unlock(&iflock);
13875 return -1;
13876 }
13877 exitpvt = p;
13878 for (;;) {
13879 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13880
13881 struct ast_str *device_name;
13882 char *dash;
13883 const char *monitor_type;
13884 char dialstring[AST_CHANNEL_NAME];
13885 char full_device_name[AST_CHANNEL_NAME];
13886
13887 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13888 case AST_CC_MONITOR_NEVER:
13889 break;
13890 case AST_CC_MONITOR_NATIVE:
13891 case AST_CC_MONITOR_ALWAYS:
13892 case AST_CC_MONITOR_GENERIC:
13893 #if defined(HAVE_PRI)
13894 if (dahdi_sig_pri_lib_handles(p->sig)) {
13895
13896
13897
13898
13899 snprintf(full_device_name, sizeof(full_device_name),
13900 "DAHDI/I%d/congestion", p->pri->span);
13901 } else
13902 #endif
13903 {
13904 #if defined(HAVE_PRI)
13905 device_name = create_channel_name(p, 1, "");
13906 #else
13907 device_name = create_channel_name(p);
13908 #endif
13909 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13910 device_name ? ast_str_buffer(device_name) : "");
13911 ast_free(device_name);
13912
13913
13914
13915
13916
13917 dash = strrchr(full_device_name, '-');
13918 if (dash) {
13919 *dash = '\0';
13920 }
13921 }
13922 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13923
13924
13925
13926
13927
13928
13929
13930 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13931 callback(inbound,
13932 #if defined(HAVE_PRI)
13933 p->pri ? p->pri->cc_params : p->cc_params,
13934 #else
13935 p->cc_params,
13936 #endif
13937 monitor_type, full_device_name, dialstring, NULL);
13938 break;
13939 }
13940 }
13941 p = start.backwards ? p->prev : p->next;
13942 if (!p) {
13943 p = start.backwards ? ifend : iflist;
13944 }
13945 if (p == exitpvt) {
13946 break;
13947 }
13948 }
13949 ast_mutex_unlock(&iflock);
13950 return 0;
13951 }
13952
13953 #if defined(HAVE_SS7)
13954 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13955 {
13956 int i;
13957
13958 if (ss7) {
13959 for (i = 0; i < NUM_SPANS; i++) {
13960 if (linksets[i].ss7.ss7 == ss7) {
13961 ast_verbose("[%d] %s", i + 1, s);
13962 return;
13963 }
13964 }
13965 }
13966 ast_verbose("%s", s);
13967 }
13968 #endif
13969
13970 #if defined(HAVE_SS7)
13971 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13972 {
13973 int i;
13974
13975 if (ss7) {
13976 for (i = 0; i < NUM_SPANS; i++) {
13977 if (linksets[i].ss7.ss7 == ss7) {
13978 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13979 return;
13980 }
13981 }
13982 }
13983 ast_log(LOG_ERROR, "%s", s);
13984 }
13985 #endif
13986
13987 #if defined(HAVE_OPENR2)
13988 static void *mfcr2_monitor(void *data)
13989 {
13990 struct dahdi_mfcr2 *mfcr2 = data;
13991
13992
13993
13994
13995
13996 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13997 int res = 0;
13998 int i = 0;
13999 int oldstate = 0;
14000 int quit_loop = 0;
14001 int maxsleep = 20;
14002 int was_idle = 0;
14003 int pollsize = 0;
14004
14005
14006 for (i = 0; i < mfcr2->numchans; i++) {
14007 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
14008 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
14009 }
14010 while (1) {
14011
14012
14013 pollsize = 0;
14014 for (i = 0; i < mfcr2->numchans; i++) {
14015 pollers[i].revents = 0;
14016 pollers[i].events = 0;
14017 if (mfcr2->pvts[i]->owner) {
14018 continue;
14019 }
14020 if (!mfcr2->pvts[i]->r2chan) {
14021 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
14022 quit_loop = 1;
14023 break;
14024 }
14025 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
14026 pollers[i].events = POLLIN | POLLPRI;
14027 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
14028 pollsize++;
14029 }
14030 if (quit_loop) {
14031 break;
14032 }
14033 if (pollsize == 0) {
14034 if (!was_idle) {
14035 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
14036 was_idle = 1;
14037 }
14038 poll(NULL, 0, maxsleep);
14039 continue;
14040 }
14041 was_idle = 0;
14042
14043
14044 pthread_testcancel();
14045 res = poll(pollers, mfcr2->numchans, maxsleep);
14046 pthread_testcancel();
14047 if ((res < 0) && (errno != EINTR)) {
14048 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
14049 break;
14050 }
14051
14052 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
14053 for (i = 0; i < mfcr2->numchans; i++) {
14054 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
14055 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
14056 }
14057 }
14058 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
14059 }
14060 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
14061 return 0;
14062 }
14063 #endif
14064
14065 #if defined(HAVE_PRI)
14066 static void dahdi_pri_message(struct pri *pri, char *s)
14067 {
14068 int x;
14069 int y;
14070 int dchan = -1;
14071 int span = -1;
14072 int dchancount = 0;
14073
14074 if (pri) {
14075 for (x = 0; x < NUM_SPANS; x++) {
14076 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14077 if (pris[x].pri.dchans[y]) {
14078 dchancount++;
14079 }
14080
14081 if (pris[x].pri.dchans[y] == pri) {
14082 dchan = y;
14083 }
14084 }
14085 if (dchan >= 0) {
14086 span = x;
14087 break;
14088 }
14089 dchancount = 0;
14090 }
14091 if (-1 < span) {
14092 if (1 < dchancount) {
14093 ast_verbose("[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14094 } else {
14095 ast_verbose("PRI Span: %d %s", span + 1, s);
14096 }
14097 } else {
14098 ast_verbose("PRI Span: ? %s", s);
14099 }
14100 } else {
14101 ast_verbose("PRI Span: ? %s", s);
14102 }
14103
14104 ast_mutex_lock(&pridebugfdlock);
14105
14106 if (pridebugfd >= 0) {
14107 if (write(pridebugfd, s, strlen(s)) < 0) {
14108 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14109 }
14110 }
14111
14112 ast_mutex_unlock(&pridebugfdlock);
14113 }
14114 #endif
14115
14116 #if defined(HAVE_PRI)
14117 static void dahdi_pri_error(struct pri *pri, char *s)
14118 {
14119 int x;
14120 int y;
14121 int dchan = -1;
14122 int span = -1;
14123 int dchancount = 0;
14124
14125 if (pri) {
14126 for (x = 0; x < NUM_SPANS; x++) {
14127 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14128 if (pris[x].pri.dchans[y]) {
14129 dchancount++;
14130 }
14131
14132 if (pris[x].pri.dchans[y] == pri) {
14133 dchan = y;
14134 }
14135 }
14136 if (dchan >= 0) {
14137 span = x;
14138 break;
14139 }
14140 dchancount = 0;
14141 }
14142 if (-1 < span) {
14143 if (1 < dchancount) {
14144 ast_log(LOG_ERROR, "[PRI Span: %d D-Channel: %d] %s", span + 1, dchan, s);
14145 } else {
14146 ast_log(LOG_ERROR, "PRI Span: %d %s", span + 1, s);
14147 }
14148 } else {
14149 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14150 }
14151 } else {
14152 ast_log(LOG_ERROR, "PRI Span: ? %s", s);
14153 }
14154
14155 ast_mutex_lock(&pridebugfdlock);
14156
14157 if (pridebugfd >= 0) {
14158 if (write(pridebugfd, s, strlen(s)) < 0) {
14159 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
14160 }
14161 }
14162
14163 ast_mutex_unlock(&pridebugfdlock);
14164 }
14165 #endif
14166
14167 #if defined(HAVE_PRI)
14168 static int prepare_pri(struct dahdi_pri *pri)
14169 {
14170 int i, res, x;
14171 struct dahdi_params p;
14172 struct dahdi_bufferinfo bi;
14173 struct dahdi_spaninfo si;
14174
14175 pri->pri.calls = &dahdi_pri_callbacks;
14176
14177 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
14178 if (!pri->dchannels[i])
14179 break;
14180 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
14181 x = pri->dchannels[i];
14182 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
14183 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
14184 return -1;
14185 }
14186 memset(&p, 0, sizeof(p));
14187 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
14188 if (res) {
14189 dahdi_close_pri_fd(pri, i);
14190 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
14191 return -1;
14192 }
14193 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
14194 dahdi_close_pri_fd(pri, i);
14195 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
14196 return -1;
14197 }
14198 memset(&si, 0, sizeof(si));
14199 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
14200 if (res) {
14201 dahdi_close_pri_fd(pri, i);
14202 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
14203 }
14204 if (!si.alarms) {
14205 pri_event_noalarm(&pri->pri, i, 1);
14206 } else {
14207 pri_event_alarm(&pri->pri, i, 1);
14208 }
14209 memset(&bi, 0, sizeof(bi));
14210 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
14211 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
14212 bi.numbufs = 32;
14213 bi.bufsize = 1024;
14214 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
14215 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
14216 dahdi_close_pri_fd(pri, i);
14217 return -1;
14218 }
14219 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
14220 }
14221 return 0;
14222 }
14223 #endif
14224
14225 #if defined(HAVE_PRI)
14226 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
14227 {
14228 int which, span;
14229 char *ret = NULL;
14230
14231 if (pos != rpos)
14232 return ret;
14233
14234 for (which = span = 0; span < NUM_SPANS; span++) {
14235 if (pris[span].pri.pri && ++which > state) {
14236 if (ast_asprintf(&ret, "%d", span + 1) < 0) {
14237 ret = NULL;
14238 }
14239 break;
14240 }
14241 }
14242 return ret;
14243 }
14244 #endif
14245
14246 #if defined(HAVE_PRI)
14247 static char *complete_span_4(const char *line, const char *word, int pos, int state)
14248 {
14249 return complete_span_helper(line,word,pos,state,3);
14250 }
14251 #endif
14252
14253 #if defined(HAVE_PRI)
14254 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14255 {
14256 int myfd;
14257 switch (cmd) {
14258 case CLI_INIT:
14259 e->command = "pri set debug file";
14260 e->usage = "Usage: pri set debug file [output-file]\n"
14261 " Sends PRI debug output to the specified output file\n";
14262 return NULL;
14263 case CLI_GENERATE:
14264 return NULL;
14265 }
14266 if (a->argc < 5)
14267 return CLI_SHOWUSAGE;
14268
14269 if (ast_strlen_zero(a->argv[4]))
14270 return CLI_SHOWUSAGE;
14271
14272 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
14273 if (myfd < 0) {
14274 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
14275 return CLI_SUCCESS;
14276 }
14277
14278 ast_mutex_lock(&pridebugfdlock);
14279
14280 if (pridebugfd >= 0)
14281 close(pridebugfd);
14282
14283 pridebugfd = myfd;
14284 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
14285 ast_mutex_unlock(&pridebugfdlock);
14286 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
14287 return CLI_SUCCESS;
14288 }
14289 #endif
14290
14291 #if defined(HAVE_PRI)
14292 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14293 {
14294 int span;
14295 int x;
14296 int level = 0;
14297 switch (cmd) {
14298 case CLI_INIT:
14299 e->command = "pri set debug {on|off|0|1|2} span";
14300 e->usage =
14301 "Usage: pri set debug {<level>|on|off} span <span>\n"
14302 " Enables debugging on a given PRI span\n";
14303 return NULL;
14304 case CLI_GENERATE:
14305 return complete_span_4(a->line, a->word, a->pos, a->n);
14306 }
14307 if (a->argc < 6) {
14308 return CLI_SHOWUSAGE;
14309 }
14310
14311 if (!strcasecmp(a->argv[3], "on")) {
14312 level = 1;
14313 } else if (!strcasecmp(a->argv[3], "off")) {
14314 level = 0;
14315 } else {
14316 level = atoi(a->argv[3]);
14317 }
14318 span = atoi(a->argv[5]);
14319 if ((span < 1) || (span > NUM_SPANS)) {
14320 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
14321 return CLI_SUCCESS;
14322 }
14323 if (!pris[span-1].pri.pri) {
14324 ast_cli(a->fd, "No PRI running on span %d\n", span);
14325 return CLI_SUCCESS;
14326 }
14327
14328
14329 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14330 if (pris[span - 1].pri.dchans[x]) {
14331 switch (level) {
14332 case 0:
14333 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
14334 break;
14335 case 1:
14336 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
14337 break;
14338 default:
14339 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
14340 break;
14341 }
14342 }
14343 }
14344 if (level == 0) {
14345
14346 ast_mutex_lock(&pridebugfdlock);
14347 if (0 <= pridebugfd) {
14348 close(pridebugfd);
14349 pridebugfd = -1;
14350 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
14351 pridebugfilename);
14352 }
14353 ast_mutex_unlock(&pridebugfdlock);
14354 }
14355 pris[span - 1].pri.debug = (level) ? 1 : 0;
14356 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
14357 return CLI_SUCCESS;
14358 }
14359 #endif
14360
14361 #if defined(HAVE_PRI)
14362 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14363 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
14364 {
14365 unsigned *why;
14366 int channel;
14367 int trunkgroup;
14368 int x, y, fd = a->fd;
14369 int interfaceid = 0;
14370 char db_chan_name[20], db_answer[5];
14371 struct dahdi_pvt *tmp;
14372 struct dahdi_pri *pri;
14373
14374 if (a->argc < 5 || a->argc > 6)
14375 return CLI_SHOWUSAGE;
14376 if (strchr(a->argv[4], ':')) {
14377 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
14378 return CLI_SHOWUSAGE;
14379 if ((trunkgroup < 1) || (channel < 1))
14380 return CLI_SHOWUSAGE;
14381 pri = NULL;
14382 for (x=0;x<NUM_SPANS;x++) {
14383 if (pris[x].pri.trunkgroup == trunkgroup) {
14384 pri = pris + x;
14385 break;
14386 }
14387 }
14388 if (!pri) {
14389 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
14390 return CLI_FAILURE;
14391 }
14392 } else
14393 channel = atoi(a->argv[4]);
14394
14395 if (a->argc == 6)
14396 interfaceid = atoi(a->argv[5]);
14397
14398
14399 for (x = 0; x < NUM_SPANS; x++) {
14400 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
14401 if (pris[x].dchannels[y] == channel) {
14402 pri = pris + x;
14403 if (pri->pri.enable_service_message_support) {
14404 ast_mutex_lock(&pri->pri.lock);
14405 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14406 ast_mutex_unlock(&pri->pri.lock);
14407 } else {
14408 ast_cli(fd,
14409 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14410 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14411 }
14412 return CLI_SUCCESS;
14413 }
14414 }
14415 }
14416
14417
14418 ast_mutex_lock(&iflock);
14419 for (tmp = iflist; tmp; tmp = tmp->next) {
14420 if (tmp->pri && tmp->channel == channel) {
14421 ast_mutex_unlock(&iflock);
14422 ast_mutex_lock(&tmp->pri->lock);
14423 if (!tmp->pri->enable_service_message_support) {
14424 ast_mutex_unlock(&tmp->pri->lock);
14425 ast_cli(fd,
14426 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14427 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14428 return CLI_SUCCESS;
14429 }
14430 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14431 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14432 switch(changestatus) {
14433 case 0:
14434
14435 ast_db_del(db_chan_name, SRVST_DBKEY);
14436 *why &= ~SRVST_NEAREND;
14437 if (*why) {
14438 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14439 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14440 } else {
14441 dahdi_pri_update_span_devstate(tmp->pri);
14442 }
14443 break;
14444
14445 case 2:
14446
14447 ast_db_del(db_chan_name, SRVST_DBKEY);
14448 *why |= SRVST_NEAREND;
14449 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14450 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14451 dahdi_pri_update_span_devstate(tmp->pri);
14452 break;
14453
14454
14455 default:
14456 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14457 break;
14458 }
14459 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14460 ast_mutex_unlock(&tmp->pri->lock);
14461 return CLI_SUCCESS;
14462 }
14463 }
14464 ast_mutex_unlock(&iflock);
14465
14466 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14467 return CLI_FAILURE;
14468 }
14469
14470 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14471 {
14472 switch (cmd) {
14473 case CLI_INIT:
14474 e->command = "pri service enable channel";
14475 e->usage =
14476 "Usage: pri service enable channel <channel> [<interface id>]\n"
14477 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14478 " to restore a channel to service, with optional interface id\n"
14479 " as agreed upon with remote switch operator\n";
14480 return NULL;
14481 case CLI_GENERATE:
14482 return NULL;
14483 }
14484 return handle_pri_service_generic(e, cmd, a, 0);
14485 }
14486
14487 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14488 {
14489 switch (cmd) {
14490 case CLI_INIT:
14491 e->command = "pri service disable channel";
14492 e->usage =
14493 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14494 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14495 " to remove a channel from service, with optional interface id\n"
14496 " as agreed upon with remote switch operator\n";
14497 return NULL;
14498 case CLI_GENERATE:
14499 return NULL;
14500 }
14501 return handle_pri_service_generic(e, cmd, a, 2);
14502 }
14503 #endif
14504 #endif
14505
14506 #if defined(HAVE_PRI)
14507 static char *handle_pri_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14508 {
14509 int span;
14510
14511 switch (cmd) {
14512 case CLI_INIT:
14513 e->command = "pri show channels";
14514 e->usage =
14515 "Usage: pri show channels\n"
14516 " Displays PRI channel information such as the current mapping\n"
14517 " of DAHDI B channels to Asterisk channel names and which calls\n"
14518 " are on hold or call-waiting. Calls on hold or call-waiting\n"
14519 " are not associated with any B channel.\n";
14520 return NULL;
14521 case CLI_GENERATE:
14522 return NULL;
14523 }
14524
14525 if (a->argc != 3)
14526 return CLI_SHOWUSAGE;
14527
14528 sig_pri_cli_show_channels_header(a->fd);
14529 for (span = 0; span < NUM_SPANS; ++span) {
14530 if (pris[span].pri.pri) {
14531 sig_pri_cli_show_channels(a->fd, &pris[span].pri);
14532 }
14533 }
14534 return CLI_SUCCESS;
14535 }
14536 #endif
14537
14538 #if defined(HAVE_PRI)
14539 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14540 {
14541 int span;
14542
14543 switch (cmd) {
14544 case CLI_INIT:
14545 e->command = "pri show spans";
14546 e->usage =
14547 "Usage: pri show spans\n"
14548 " Displays PRI span information\n";
14549 return NULL;
14550 case CLI_GENERATE:
14551 return NULL;
14552 }
14553
14554 if (a->argc != 3)
14555 return CLI_SHOWUSAGE;
14556
14557 for (span = 0; span < NUM_SPANS; span++) {
14558 if (pris[span].pri.pri) {
14559 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14560 }
14561 }
14562 return CLI_SUCCESS;
14563 }
14564 #endif
14565
14566 #if defined(HAVE_PRI)
14567 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14568 {
14569 int span;
14570
14571 switch (cmd) {
14572 case CLI_INIT:
14573 e->command = "pri show span";
14574 e->usage =
14575 "Usage: pri show span <span>\n"
14576 " Displays PRI Information on a given PRI span\n";
14577 return NULL;
14578 case CLI_GENERATE:
14579 return complete_span_4(a->line, a->word, a->pos, a->n);
14580 }
14581
14582 if (a->argc < 4)
14583 return CLI_SHOWUSAGE;
14584 span = atoi(a->argv[3]);
14585 if ((span < 1) || (span > NUM_SPANS)) {
14586 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14587 return CLI_SUCCESS;
14588 }
14589 if (!pris[span-1].pri.pri) {
14590 ast_cli(a->fd, "No PRI running on span %d\n", span);
14591 return CLI_SUCCESS;
14592 }
14593
14594 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14595
14596 return CLI_SUCCESS;
14597 }
14598 #endif
14599
14600 #if defined(HAVE_PRI)
14601 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14602 {
14603 int x;
14604 int span;
14605 int count=0;
14606 int debug;
14607
14608 switch (cmd) {
14609 case CLI_INIT:
14610 e->command = "pri show debug";
14611 e->usage =
14612 "Usage: pri show debug\n"
14613 " Show the debug state of pri spans\n";
14614 return NULL;
14615 case CLI_GENERATE:
14616 return NULL;
14617 }
14618
14619 for (span = 0; span < NUM_SPANS; span++) {
14620 if (pris[span].pri.pri) {
14621 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14622 if (pris[span].pri.dchans[x]) {
14623 debug = pri_get_debug(pris[span].pri.dchans[x]);
14624 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" );
14625 count++;
14626 }
14627 }
14628 }
14629
14630 }
14631 ast_mutex_lock(&pridebugfdlock);
14632 if (pridebugfd >= 0)
14633 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14634 ast_mutex_unlock(&pridebugfdlock);
14635
14636 if (!count)
14637 ast_cli(a->fd, "No PRI running\n");
14638 return CLI_SUCCESS;
14639 }
14640 #endif
14641
14642 #if defined(HAVE_PRI)
14643 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14644 {
14645 switch (cmd) {
14646 case CLI_INIT:
14647 e->command = "pri show version";
14648 e->usage =
14649 "Usage: pri show version\n"
14650 "Show libpri version information\n";
14651 return NULL;
14652 case CLI_GENERATE:
14653 return NULL;
14654 }
14655
14656 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14657
14658 return CLI_SUCCESS;
14659 }
14660 #endif
14661
14662 #if defined(HAVE_PRI)
14663 static struct ast_cli_entry dahdi_pri_cli[] = {
14664 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14665 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14666 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14667 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14668 #endif
14669 AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
14670 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
14671 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
14672 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14673 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14674 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14675 };
14676 #endif
14677
14678 #ifdef HAVE_OPENR2
14679
14680 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14681 {
14682 switch (cmd) {
14683 case CLI_INIT:
14684 e->command = "mfcr2 show version";
14685 e->usage =
14686 "Usage: mfcr2 show version\n"
14687 " Shows the version of the OpenR2 library being used.\n";
14688 return NULL;
14689 case CLI_GENERATE:
14690 return NULL;
14691 }
14692 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14693 return CLI_SUCCESS;
14694 }
14695
14696 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14697 {
14698 #define FORMAT "%4s %40s\n"
14699 int i = 0;
14700 int numvariants = 0;
14701 const openr2_variant_entry_t *variants;
14702 switch (cmd) {
14703 case CLI_INIT:
14704 e->command = "mfcr2 show variants";
14705 e->usage =
14706 "Usage: mfcr2 show variants\n"
14707 " Shows the list of MFC/R2 variants supported.\n";
14708 return NULL;
14709 case CLI_GENERATE:
14710 return NULL;
14711 }
14712 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14713 ast_cli(a->fd, "Failed to get list of variants.\n");
14714 return CLI_FAILURE;
14715 }
14716 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14717 for (i = 0; i < numvariants; i++) {
14718 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14719 }
14720 return CLI_SUCCESS;
14721 #undef FORMAT
14722 }
14723
14724 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14725 {
14726 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14727 int filtertype = 0;
14728 int targetnum = 0;
14729 char channo[5];
14730 char anino[5];
14731 char dnisno[5];
14732 struct dahdi_pvt *p;
14733 openr2_context_t *r2context;
14734 openr2_variant_t r2variant;
14735 switch (cmd) {
14736 case CLI_INIT:
14737 e->command = "mfcr2 show channels [group|context]";
14738 e->usage =
14739 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14740 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14741 return NULL;
14742 case CLI_GENERATE:
14743 return NULL;
14744 }
14745 if (!((a->argc == 3) || (a->argc == 5))) {
14746 return CLI_SHOWUSAGE;
14747 }
14748 if (a->argc == 5) {
14749 if (!strcasecmp(a->argv[3], "group")) {
14750 targetnum = atoi(a->argv[4]);
14751 if ((targetnum < 0) || (targetnum > 63))
14752 return CLI_SHOWUSAGE;
14753 targetnum = 1 << targetnum;
14754 filtertype = 1;
14755 } else if (!strcasecmp(a->argv[3], "context")) {
14756 filtertype = 2;
14757 } else {
14758 return CLI_SHOWUSAGE;
14759 }
14760 }
14761 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14762 ast_mutex_lock(&iflock);
14763 for (p = iflist; p; p = p->next) {
14764 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14765 continue;
14766 }
14767 if (filtertype) {
14768 switch(filtertype) {
14769 case 1:
14770 if (p->group != targetnum) {
14771 continue;
14772 }
14773 break;
14774 case 2:
14775 if (strcasecmp(p->context, a->argv[4])) {
14776 continue;
14777 }
14778 break;
14779 default:
14780 ;
14781 }
14782 }
14783 r2context = openr2_chan_get_context(p->r2chan);
14784 r2variant = openr2_context_get_variant(r2context);
14785 snprintf(channo, sizeof(channo), "%d", p->channel);
14786 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14787 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14788 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14789 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14790 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14791 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14792 }
14793 ast_mutex_unlock(&iflock);
14794 return CLI_SUCCESS;
14795 #undef FORMAT
14796 }
14797
14798 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14799 {
14800 struct dahdi_pvt *p = NULL;
14801 int channo = 0;
14802 char *toklevel = NULL;
14803 char *saveptr = NULL;
14804 char *logval = NULL;
14805 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14806 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14807 switch (cmd) {
14808 case CLI_INIT:
14809 e->command = "mfcr2 set debug";
14810 e->usage =
14811 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14812 " Set a new logging level for the specified channel.\n"
14813 " If no channel is specified the logging level will be applied to all channels.\n";
14814 return NULL;
14815 case CLI_GENERATE:
14816 return NULL;
14817 }
14818 if (a->argc < 4) {
14819 return CLI_SHOWUSAGE;
14820 }
14821 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14822 logval = ast_strdupa(a->argv[3]);
14823 toklevel = strtok_r(logval, ",", &saveptr);
14824 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14825 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14826 return CLI_FAILURE;
14827 } else if (OR2_LOG_NOTHING == tmplevel) {
14828 loglevel = tmplevel;
14829 } else {
14830 loglevel |= tmplevel;
14831 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14832 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14833 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14834 continue;
14835 }
14836 loglevel |= tmplevel;
14837 }
14838 }
14839 ast_mutex_lock(&iflock);
14840 for (p = iflist; p; p = p->next) {
14841 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14842 continue;
14843 }
14844 if ((channo != -1) && (p->channel != channo )) {
14845 continue;
14846 }
14847 openr2_chan_set_log_level(p->r2chan, loglevel);
14848 if (channo != -1) {
14849 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14850 break;
14851 }
14852 }
14853 if ((channo != -1) && !p) {
14854 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14855 }
14856 if (channo == -1) {
14857 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14858 }
14859 ast_mutex_unlock(&iflock);
14860 return CLI_SUCCESS;
14861 }
14862
14863 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14864 {
14865 struct dahdi_pvt *p = NULL;
14866 int channo = 0;
14867 switch (cmd) {
14868 case CLI_INIT:
14869 e->command = "mfcr2 call files [on|off]";
14870 e->usage =
14871 "Usage: mfcr2 call files [on|off] <channel>\n"
14872 " Enable call files creation on the specified channel.\n"
14873 " If no channel is specified call files creation policy will be applied to all channels.\n";
14874 return NULL;
14875 case CLI_GENERATE:
14876 return NULL;
14877 }
14878 if (a->argc < 4) {
14879 return CLI_SHOWUSAGE;
14880 }
14881 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14882 ast_mutex_lock(&iflock);
14883 for (p = iflist; p; p = p->next) {
14884 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14885 continue;
14886 }
14887 if ((channo != -1) && (p->channel != channo )) {
14888 continue;
14889 }
14890 if (ast_true(a->argv[3])) {
14891 openr2_chan_enable_call_files(p->r2chan);
14892 } else {
14893 openr2_chan_disable_call_files(p->r2chan);
14894 }
14895 if (channo != -1) {
14896 if (ast_true(a->argv[3])) {
14897 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14898 } else {
14899 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14900 }
14901 break;
14902 }
14903 }
14904 if ((channo != -1) && !p) {
14905 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14906 }
14907 if (channo == -1) {
14908 if (ast_true(a->argv[3])) {
14909 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14910 } else {
14911 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14912 }
14913 }
14914 ast_mutex_unlock(&iflock);
14915 return CLI_SUCCESS;
14916 }
14917
14918 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14919 {
14920 struct dahdi_pvt *p = NULL;
14921 int channo = 0;
14922 switch (cmd) {
14923 case CLI_INIT:
14924 e->command = "mfcr2 set idle";
14925 e->usage =
14926 "Usage: mfcr2 set idle <channel>\n"
14927 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14928 " Force the given channel into IDLE state.\n"
14929 " If no channel is specified, all channels will be set to IDLE.\n";
14930 return NULL;
14931 case CLI_GENERATE:
14932 return NULL;
14933 }
14934 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14935 ast_mutex_lock(&iflock);
14936 for (p = iflist; p; p = p->next) {
14937 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14938 continue;
14939 }
14940 if ((channo != -1) && (p->channel != channo )) {
14941 continue;
14942 }
14943 openr2_chan_set_idle(p->r2chan);
14944 ast_mutex_lock(&p->lock);
14945 p->locallyblocked = 0;
14946 p->mfcr2call = 0;
14947 ast_mutex_unlock(&p->lock);
14948 if (channo != -1) {
14949 break;
14950 }
14951 }
14952 if ((channo != -1) && !p) {
14953 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14954 }
14955 ast_mutex_unlock(&iflock);
14956 return CLI_SUCCESS;
14957 }
14958
14959 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14960 {
14961 struct dahdi_pvt *p = NULL;
14962 int channo = 0;
14963 switch (cmd) {
14964 case CLI_INIT:
14965 e->command = "mfcr2 set blocked";
14966 e->usage =
14967 "Usage: mfcr2 set blocked <channel>\n"
14968 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14969 " Force the given channel into BLOCKED state.\n"
14970 " If no channel is specified, all channels will be set to BLOCKED.\n";
14971 return NULL;
14972 case CLI_GENERATE:
14973 return NULL;
14974 }
14975 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14976 ast_mutex_lock(&iflock);
14977 for (p = iflist; p; p = p->next) {
14978 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14979 continue;
14980 }
14981 if ((channo != -1) && (p->channel != channo )) {
14982 continue;
14983 }
14984 openr2_chan_set_blocked(p->r2chan);
14985 ast_mutex_lock(&p->lock);
14986 p->locallyblocked = 1;
14987 ast_mutex_unlock(&p->lock);
14988 if (channo != -1) {
14989 break;
14990 }
14991 }
14992 if ((channo != -1) && !p) {
14993 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14994 }
14995 ast_mutex_unlock(&iflock);
14996 return CLI_SUCCESS;
14997 }
14998
14999 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
15000 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
15001 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
15002 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
15003 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
15004 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
15005 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
15006 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
15007 };
15008
15009 #endif
15010
15011 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15012 {
15013 int channel;
15014 int ret;
15015 switch (cmd) {
15016 case CLI_INIT:
15017 e->command = "dahdi destroy channel";
15018 e->usage =
15019 "Usage: dahdi destroy channel <chan num>\n"
15020 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
15021 return NULL;
15022 case CLI_GENERATE:
15023 return NULL;
15024 }
15025 if (a->argc != 4)
15026 return CLI_SHOWUSAGE;
15027
15028 channel = atoi(a->argv[3]);
15029 ret = dahdi_destroy_channel_bynum(channel);
15030 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
15031 }
15032
15033 static void dahdi_softhangup_all(void)
15034 {
15035 struct dahdi_pvt *p;
15036 retry:
15037 ast_mutex_lock(&iflock);
15038 for (p = iflist; p; p = p->next) {
15039 ast_mutex_lock(&p->lock);
15040 if (p->owner && !p->restartpending) {
15041 if (ast_channel_trylock(p->owner)) {
15042 if (option_debug > 2)
15043 ast_verbose("Avoiding deadlock\n");
15044
15045 ast_mutex_unlock(&p->lock);
15046 ast_mutex_unlock(&iflock);
15047 goto retry;
15048 }
15049 if (option_debug > 2)
15050 ast_verbose("Softhanging up on %s\n", p->owner->name);
15051 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
15052 p->restartpending = 1;
15053 num_restart_pending++;
15054 ast_channel_unlock(p->owner);
15055 }
15056 ast_mutex_unlock(&p->lock);
15057 }
15058 ast_mutex_unlock(&iflock);
15059 }
15060
15061 static int setup_dahdi(int reload);
15062 static int dahdi_restart(void)
15063 {
15064 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15065 int i, j;
15066 #endif
15067 int cancel_code;
15068 struct dahdi_pvt *p;
15069
15070 ast_mutex_lock(&restart_lock);
15071 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
15072 dahdi_softhangup_all();
15073 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
15074 #ifdef HAVE_OPENR2
15075 dahdi_r2_destroy_links();
15076 #endif
15077
15078 #if defined(HAVE_PRI)
15079 for (i = 0; i < NUM_SPANS; i++) {
15080 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
15081 cancel_code = pthread_cancel(pris[i].pri.master);
15082 pthread_kill(pris[i].pri.master, SIGURG);
15083 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);
15084 pthread_join(pris[i].pri.master, NULL);
15085 ast_debug(4, "Joined thread of span %d\n", i);
15086 }
15087 }
15088 #endif
15089
15090 #if defined(HAVE_SS7)
15091 for (i = 0; i < NUM_SPANS; i++) {
15092 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
15093 cancel_code = pthread_cancel(linksets[i].ss7.master);
15094 pthread_kill(linksets[i].ss7.master, SIGURG);
15095 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);
15096 pthread_join(linksets[i].ss7.master, NULL);
15097 ast_debug(4, "Joined thread of span %d\n", i);
15098 }
15099 }
15100 #endif
15101
15102 ast_mutex_lock(&monlock);
15103 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15104 cancel_code = pthread_cancel(monitor_thread);
15105 pthread_kill(monitor_thread, SIGURG);
15106 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
15107 pthread_join(monitor_thread, NULL);
15108 ast_debug(4, "Joined monitor thread\n");
15109 }
15110 monitor_thread = AST_PTHREADT_NULL;
15111
15112 ast_mutex_lock(&ss_thread_lock);
15113 while (ss_thread_count > 0) {
15114 int x = DAHDI_FLASH;
15115 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
15116
15117 ast_mutex_lock(&iflock);
15118 for (p = iflist; p; p = p->next) {
15119 if (p->owner) {
15120
15121 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
15122 }
15123 }
15124 ast_mutex_unlock(&iflock);
15125 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
15126 }
15127
15128
15129 dahdi_softhangup_all();
15130 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
15131 destroy_all_channels();
15132 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
15133
15134 ast_mutex_unlock(&monlock);
15135
15136 #ifdef HAVE_PRI
15137 for (i = 0; i < NUM_SPANS; i++) {
15138 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
15139 dahdi_close_pri_fd(&(pris[i]), j);
15140 }
15141
15142 memset(pris, 0, sizeof(pris));
15143 for (i = 0; i < NUM_SPANS; i++) {
15144 sig_pri_init_pri(&pris[i].pri);
15145 }
15146 pri_set_error(dahdi_pri_error);
15147 pri_set_message(dahdi_pri_message);
15148 #endif
15149 #if defined(HAVE_SS7)
15150 for (i = 0; i < NUM_SPANS; i++) {
15151 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
15152 dahdi_close_ss7_fd(&(linksets[i]), j);
15153 }
15154
15155 memset(linksets, 0, sizeof(linksets));
15156 for (i = 0; i < NUM_SPANS; i++) {
15157 sig_ss7_init_linkset(&linksets[i].ss7);
15158 }
15159 ss7_set_error(dahdi_ss7_error);
15160 ss7_set_message(dahdi_ss7_message);
15161 #endif
15162
15163 if (setup_dahdi(2) != 0) {
15164 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
15165 ast_mutex_unlock(&ss_thread_lock);
15166 return 1;
15167 }
15168 ast_mutex_unlock(&ss_thread_lock);
15169 ast_mutex_unlock(&restart_lock);
15170 return 0;
15171 }
15172
15173 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15174 {
15175 switch (cmd) {
15176 case CLI_INIT:
15177 e->command = "dahdi restart";
15178 e->usage =
15179 "Usage: dahdi restart\n"
15180 " Restarts the DAHDI channels: destroys them all and then\n"
15181 " re-reads them from chan_dahdi.conf.\n"
15182 " Note that this will STOP any running CALL on DAHDI channels.\n"
15183 "";
15184 return NULL;
15185 case CLI_GENERATE:
15186 return NULL;
15187 }
15188 if (a->argc != 2)
15189 return CLI_SHOWUSAGE;
15190
15191 if (dahdi_restart() != 0)
15192 return CLI_FAILURE;
15193 return CLI_SUCCESS;
15194 }
15195
15196 static int action_dahdirestart(struct mansession *s, const struct message *m)
15197 {
15198 if (dahdi_restart() != 0) {
15199 astman_send_error(s, m, "Failed rereading DAHDI configuration");
15200 return 1;
15201 }
15202 astman_send_ack(s, m, "DAHDIRestart: Success");
15203 return 0;
15204 }
15205
15206 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15207 {
15208 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15209 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
15210 unsigned int targetnum = 0;
15211 int filtertype = 0;
15212 struct dahdi_pvt *tmp = NULL;
15213 char tmps[20] = "";
15214 char statestr[20] = "";
15215 char blockstr[20] = "";
15216
15217 switch (cmd) {
15218 case CLI_INIT:
15219 e->command = "dahdi show channels [group|context]";
15220 e->usage =
15221 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
15222 " Shows a list of available channels with optional filtering\n"
15223 " <group> must be a number between 0 and 63\n";
15224 return NULL;
15225 case CLI_GENERATE:
15226 return NULL;
15227 }
15228
15229
15230
15231 if (!((a->argc == 3) || (a->argc == 5)))
15232 return CLI_SHOWUSAGE;
15233
15234 if (a->argc == 5) {
15235 if (!strcasecmp(a->argv[3], "group")) {
15236 targetnum = atoi(a->argv[4]);
15237 if ((targetnum < 0) || (targetnum > 63))
15238 return CLI_SHOWUSAGE;
15239 targetnum = 1 << targetnum;
15240 filtertype = 1;
15241 } else if (!strcasecmp(a->argv[3], "context")) {
15242 filtertype = 2;
15243 }
15244 }
15245
15246 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
15247 ast_mutex_lock(&iflock);
15248 for (tmp = iflist; tmp; tmp = tmp->next) {
15249 if (filtertype) {
15250 switch(filtertype) {
15251 case 1:
15252 if (!(tmp->group & targetnum)) {
15253 continue;
15254 }
15255 break;
15256 case 2:
15257 if (strcasecmp(tmp->context, a->argv[4])) {
15258 continue;
15259 }
15260 break;
15261 default:
15262 break;
15263 }
15264 }
15265 if (tmp->channel > 0) {
15266 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
15267 } else
15268 ast_copy_string(tmps, "pseudo", sizeof(tmps));
15269
15270 if (tmp->locallyblocked)
15271 blockstr[0] = 'L';
15272 else
15273 blockstr[0] = ' ';
15274
15275 if (tmp->remotelyblocked)
15276 blockstr[1] = 'R';
15277 else
15278 blockstr[1] = ' ';
15279
15280 blockstr[2] = '\0';
15281
15282 snprintf(statestr, sizeof(statestr), "%s", "In Service");
15283
15284 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
15285 }
15286 ast_mutex_unlock(&iflock);
15287 return CLI_SUCCESS;
15288 #undef FORMAT
15289 #undef FORMAT2
15290 }
15291
15292 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15293 {
15294 int channel;
15295 struct dahdi_pvt *tmp = NULL;
15296 struct dahdi_confinfo ci;
15297 struct dahdi_params ps;
15298 int x;
15299
15300 switch (cmd) {
15301 case CLI_INIT:
15302 e->command = "dahdi show channel";
15303 e->usage =
15304 "Usage: dahdi show channel <chan num>\n"
15305 " Detailed information about a given channel\n";
15306 return NULL;
15307 case CLI_GENERATE:
15308 return NULL;
15309 }
15310
15311 if (a->argc != 4)
15312 return CLI_SHOWUSAGE;
15313
15314 channel = atoi(a->argv[3]);
15315
15316 ast_mutex_lock(&iflock);
15317 for (tmp = iflist; tmp; tmp = tmp->next) {
15318 if (tmp->channel == channel) {
15319 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
15320 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
15321 ast_cli(a->fd, "Span: %d\n", tmp->span);
15322 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
15323 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
15324 ast_cli(a->fd, "Context: %s\n", tmp->context);
15325 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
15326 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
15327 #if defined(HAVE_PRI)
15328 #if defined(HAVE_PRI_SUBADDR)
15329 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
15330 #endif
15331 #endif
15332 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
15333 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
15334 if (tmp->vars) {
15335 struct ast_variable *v;
15336 ast_cli(a->fd, "Variables:\n");
15337 for (v = tmp->vars ; v ; v = v->next)
15338 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
15339 }
15340 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
15341 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
15342 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
15343 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
15344 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
15345 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)" : "");
15346 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)" : "");
15347 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)" : "");
15348 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
15349 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
15350 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
15351 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
15352 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
15353 if (tmp->busydetect) {
15354 #if defined(BUSYDETECT_TONEONLY)
15355 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
15356 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
15357 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
15358 #endif
15359 #ifdef BUSYDETECT_DEBUG
15360 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
15361 #endif
15362 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
15363 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
15364 }
15365 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
15366 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
15367 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
15368 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
15369 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
15370 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
15371 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
15372 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
15373 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
15374 ast_cli(a->fd, "Echo Cancellation:\n");
15375
15376 if (tmp->echocancel.head.tap_length) {
15377 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
15378 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
15379 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
15380 }
15381 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
15382 } else {
15383 ast_cli(a->fd, "\tnone\n");
15384 }
15385 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
15386 if (tmp->master)
15387 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
15388 for (x = 0; x < MAX_SLAVES; x++) {
15389 if (tmp->slaves[x])
15390 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
15391 }
15392 #ifdef HAVE_OPENR2
15393 if (tmp->mfcr2) {
15394 char calldir[OR2_MAX_PATH];
15395 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
15396 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
15397 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
15398 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
15399 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
15400 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
15401 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
15402 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
15403 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
15404 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
15405 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
15406 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
15407 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
15408 #endif
15409 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
15410 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
15411 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
15412 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
15413 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
15414 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
15415 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
15416 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
15417 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
15418 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
15419 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
15420 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
15421 }
15422 #endif
15423 #if defined(HAVE_SS7)
15424 if (tmp->ss7) {
15425 struct sig_ss7_chan *chan = tmp->sig_pvt;
15426
15427 ast_cli(a->fd, "CIC: %d\n", chan->cic);
15428 }
15429 #endif
15430 #ifdef HAVE_PRI
15431 if (tmp->pri) {
15432 struct sig_pri_chan *chan = tmp->sig_pvt;
15433
15434 ast_cli(a->fd, "PRI Flags: ");
15435 if (chan->resetting != SIG_PRI_RESET_IDLE) {
15436 ast_cli(a->fd, "Resetting=%d ", chan->resetting);
15437 }
15438 if (chan->call)
15439 ast_cli(a->fd, "Call ");
15440 if (chan->allocated) {
15441 ast_cli(a->fd, "Allocated ");
15442 }
15443 ast_cli(a->fd, "\n");
15444 if (tmp->logicalspan)
15445 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15446 else
15447 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15448 }
15449 #endif
15450 memset(&ci, 0, sizeof(ci));
15451 ps.channo = tmp->channel;
15452 if (tmp->subs[SUB_REAL].dfd > -1) {
15453 memset(&ci, 0, sizeof(ci));
15454 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15455 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15456 }
15457 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15458 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15459 }
15460 memset(&ps, 0, sizeof(ps));
15461 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15462 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15463 } else {
15464 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15465 }
15466 }
15467 ast_mutex_unlock(&iflock);
15468 return CLI_SUCCESS;
15469 }
15470 }
15471 ast_mutex_unlock(&iflock);
15472
15473 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15474 return CLI_FAILURE;
15475 }
15476
15477 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15478 {
15479 int i, j;
15480 switch (cmd) {
15481 case CLI_INIT:
15482 e->command = "dahdi show cadences";
15483 e->usage =
15484 "Usage: dahdi show cadences\n"
15485 " Shows all cadences currently defined\n";
15486 return NULL;
15487 case CLI_GENERATE:
15488 return NULL;
15489 }
15490 for (i = 0; i < num_cadence; i++) {
15491 char output[1024];
15492 char tmp[16], tmp2[64];
15493 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15494 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15495
15496 for (j = 0; j < 16; j++) {
15497 if (cadences[i].ringcadence[j] == 0)
15498 break;
15499 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15500 if (cidrings[i] * 2 - 1 == j)
15501 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15502 else
15503 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15504 if (j != 0)
15505 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15506 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15507 }
15508 ast_cli(a->fd,"%s\n",output);
15509 }
15510 return CLI_SUCCESS;
15511 }
15512
15513
15514 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15515 {
15516 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15517 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15518 int span;
15519 int res;
15520 char alarmstr[50];
15521
15522 int ctl;
15523 struct dahdi_spaninfo s;
15524
15525 switch (cmd) {
15526 case CLI_INIT:
15527 e->command = "dahdi show status";
15528 e->usage =
15529 "Usage: dahdi show status\n"
15530 " Shows a list of DAHDI cards with status\n";
15531 return NULL;
15532 case CLI_GENERATE:
15533 return NULL;
15534 }
15535 ctl = open("/dev/dahdi/ctl", O_RDWR);
15536 if (ctl < 0) {
15537 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15538 return CLI_FAILURE;
15539 }
15540 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC", "Framing", "Coding", "Options", "LBO");
15541
15542 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15543 s.spanno = span;
15544 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15545 if (res) {
15546 continue;
15547 }
15548 alarmstr[0] = '\0';
15549 if (s.alarms > 0) {
15550 if (s.alarms & DAHDI_ALARM_BLUE)
15551 strcat(alarmstr, "BLU/");
15552 if (s.alarms & DAHDI_ALARM_YELLOW)
15553 strcat(alarmstr, "YEL/");
15554 if (s.alarms & DAHDI_ALARM_RED)
15555 strcat(alarmstr, "RED/");
15556 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15557 strcat(alarmstr, "LB/");
15558 if (s.alarms & DAHDI_ALARM_RECOVER)
15559 strcat(alarmstr, "REC/");
15560 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15561 strcat(alarmstr, "NOP/");
15562 if (!strlen(alarmstr))
15563 strcat(alarmstr, "UUU/");
15564 if (strlen(alarmstr)) {
15565
15566 alarmstr[strlen(alarmstr) - 1] = '\0';
15567 }
15568 } else {
15569 if (s.numchans)
15570 strcpy(alarmstr, "OK");
15571 else
15572 strcpy(alarmstr, "UNCONFIGURED");
15573 }
15574
15575 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15576 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15577 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15578 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15579 "CAS",
15580 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15581 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15582 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15583 "Unk",
15584 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15585 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15586 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15587 lbostr[s.lbo]
15588 );
15589 }
15590 close(ctl);
15591
15592 return CLI_SUCCESS;
15593 #undef FORMAT
15594 #undef FORMAT2
15595 }
15596
15597 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15598 {
15599 int pseudo_fd = -1;
15600 struct dahdi_versioninfo vi;
15601
15602 switch (cmd) {
15603 case CLI_INIT:
15604 e->command = "dahdi show version";
15605 e->usage =
15606 "Usage: dahdi show version\n"
15607 " Shows the DAHDI version in use\n";
15608 return NULL;
15609 case CLI_GENERATE:
15610 return NULL;
15611 }
15612 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15613 ast_cli(a->fd, "Failed to open control file to get version.\n");
15614 return CLI_SUCCESS;
15615 }
15616
15617 strcpy(vi.version, "Unknown");
15618 strcpy(vi.echo_canceller, "Unknown");
15619
15620 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15621 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15622 else
15623 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15624
15625 close(pseudo_fd);
15626
15627 return CLI_SUCCESS;
15628 }
15629
15630 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15631 {
15632 int channel;
15633 int gain;
15634 int tx;
15635 struct dahdi_hwgain hwgain;
15636 struct dahdi_pvt *tmp = NULL;
15637
15638 switch (cmd) {
15639 case CLI_INIT:
15640 e->command = "dahdi set hwgain";
15641 e->usage =
15642 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15643 " Sets the hardware gain on a a given channel, overriding the\n"
15644 " value provided at module loadtime, whether the channel is in\n"
15645 " use or not. Changes take effect immediately.\n"
15646 " <rx|tx> which direction do you want to change (relative to our module)\n"
15647 " <chan num> is the channel number relative to the device\n"
15648 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15649 return NULL;
15650 case CLI_GENERATE:
15651 return NULL;
15652 }
15653
15654 if (a->argc != 6)
15655 return CLI_SHOWUSAGE;
15656
15657 if (!strcasecmp("rx", a->argv[3]))
15658 tx = 0;
15659 else if (!strcasecmp("tx", a->argv[3]))
15660 tx = 1;
15661 else
15662 return CLI_SHOWUSAGE;
15663
15664 channel = atoi(a->argv[4]);
15665 gain = atof(a->argv[5])*10.0;
15666
15667 ast_mutex_lock(&iflock);
15668
15669 for (tmp = iflist; tmp; tmp = tmp->next) {
15670
15671 if (tmp->channel != channel)
15672 continue;
15673
15674 if (tmp->subs[SUB_REAL].dfd == -1)
15675 break;
15676
15677 hwgain.newgain = gain;
15678 hwgain.tx = tx;
15679 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15680 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15681 ast_mutex_unlock(&iflock);
15682 return CLI_FAILURE;
15683 }
15684 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15685 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15686 break;
15687 }
15688
15689 ast_mutex_unlock(&iflock);
15690
15691 if (tmp)
15692 return CLI_SUCCESS;
15693
15694 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15695 return CLI_FAILURE;
15696
15697 }
15698
15699 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15700 {
15701 int channel;
15702 float gain;
15703 int tx;
15704 int res;
15705 struct dahdi_pvt *tmp = NULL;
15706
15707 switch (cmd) {
15708 case CLI_INIT:
15709 e->command = "dahdi set swgain";
15710 e->usage =
15711 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15712 " Sets the software gain on a a given channel, overriding the\n"
15713 " value provided at module loadtime, whether the channel is in\n"
15714 " use or not. Changes take effect immediately.\n"
15715 " <rx|tx> which direction do you want to change (relative to our module)\n"
15716 " <chan num> is the channel number relative to the device\n"
15717 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15718 return NULL;
15719 case CLI_GENERATE:
15720 return NULL;
15721 }
15722
15723 if (a->argc != 6)
15724 return CLI_SHOWUSAGE;
15725
15726 if (!strcasecmp("rx", a->argv[3]))
15727 tx = 0;
15728 else if (!strcasecmp("tx", a->argv[3]))
15729 tx = 1;
15730 else
15731 return CLI_SHOWUSAGE;
15732
15733 channel = atoi(a->argv[4]);
15734 gain = atof(a->argv[5]);
15735
15736 ast_mutex_lock(&iflock);
15737 for (tmp = iflist; tmp; tmp = tmp->next) {
15738
15739 if (tmp->channel != channel)
15740 continue;
15741
15742 if (tmp->subs[SUB_REAL].dfd == -1)
15743 break;
15744
15745 if (tx)
15746 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15747 else
15748 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15749
15750 if (res) {
15751 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15752 ast_mutex_unlock(&iflock);
15753 return CLI_FAILURE;
15754 }
15755
15756 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15757 tx ? "tx" : "rx", gain, channel);
15758 break;
15759 }
15760 ast_mutex_unlock(&iflock);
15761
15762 if (tmp)
15763 return CLI_SUCCESS;
15764
15765 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15766 return CLI_FAILURE;
15767
15768 }
15769
15770 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15771 {
15772 int channel;
15773 int on;
15774 struct dahdi_pvt *dahdi_chan = NULL;
15775
15776 switch (cmd) {
15777 case CLI_INIT:
15778 e->command = "dahdi set dnd";
15779 e->usage =
15780 "Usage: dahdi set dnd <chan#> <on|off>\n"
15781 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15782 " Changes take effect immediately.\n"
15783 " <chan num> is the channel number\n"
15784 " <on|off> Enable or disable DND mode?\n"
15785 ;
15786 return NULL;
15787 case CLI_GENERATE:
15788 return NULL;
15789 }
15790
15791 if (a->argc != 5)
15792 return CLI_SHOWUSAGE;
15793
15794 if ((channel = atoi(a->argv[3])) <= 0) {
15795 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15796 return CLI_SHOWUSAGE;
15797 }
15798
15799 if (ast_true(a->argv[4]))
15800 on = 1;
15801 else if (ast_false(a->argv[4]))
15802 on = 0;
15803 else {
15804 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15805 return CLI_SHOWUSAGE;
15806 }
15807
15808 ast_mutex_lock(&iflock);
15809 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15810 if (dahdi_chan->channel != channel)
15811 continue;
15812
15813
15814 dahdi_dnd(dahdi_chan, on);
15815 break;
15816 }
15817 ast_mutex_unlock(&iflock);
15818
15819 if (!dahdi_chan) {
15820 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15821 return CLI_FAILURE;
15822 }
15823
15824 return CLI_SUCCESS;
15825 }
15826
15827 static struct ast_cli_entry dahdi_cli[] = {
15828 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15829 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15830 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15831 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15832 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15833 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15834 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15835 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15836 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15837 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15838 };
15839
15840 #define TRANSFER 0
15841 #define HANGUP 1
15842
15843 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15844 {
15845 if (p) {
15846 switch (mode) {
15847 case TRANSFER:
15848 p->fake_event = DAHDI_EVENT_WINKFLASH;
15849 break;
15850 case HANGUP:
15851 p->fake_event = DAHDI_EVENT_ONHOOK;
15852 break;
15853 default:
15854 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15855 }
15856 }
15857 return 0;
15858 }
15859 static struct dahdi_pvt *find_channel(int channel)
15860 {
15861 struct dahdi_pvt *p;
15862
15863 ast_mutex_lock(&iflock);
15864 for (p = iflist; p; p = p->next) {
15865 if (p->channel == channel) {
15866 break;
15867 }
15868 }
15869 ast_mutex_unlock(&iflock);
15870 return p;
15871 }
15872
15873
15874
15875
15876
15877
15878
15879
15880
15881
15882 static struct dahdi_pvt *find_channel_from_str(const char *channel)
15883 {
15884 int chan_num;
15885
15886 if (sscanf(channel, "%30d", &chan_num) != 1) {
15887
15888 return NULL;
15889 }
15890
15891 return find_channel(chan_num);
15892 }
15893
15894 static int action_dahdidndon(struct mansession *s, const struct message *m)
15895 {
15896 struct dahdi_pvt *p;
15897 const char *channel = astman_get_header(m, "DAHDIChannel");
15898
15899 if (ast_strlen_zero(channel)) {
15900 astman_send_error(s, m, "No channel specified");
15901 return 0;
15902 }
15903 p = find_channel_from_str(channel);
15904 if (!p) {
15905 astman_send_error(s, m, "No such channel");
15906 return 0;
15907 }
15908 dahdi_dnd(p, 1);
15909 astman_send_ack(s, m, "DND Enabled");
15910 return 0;
15911 }
15912
15913 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15914 {
15915 struct dahdi_pvt *p;
15916 const char *channel = astman_get_header(m, "DAHDIChannel");
15917
15918 if (ast_strlen_zero(channel)) {
15919 astman_send_error(s, m, "No channel specified");
15920 return 0;
15921 }
15922 p = find_channel_from_str(channel);
15923 if (!p) {
15924 astman_send_error(s, m, "No such channel");
15925 return 0;
15926 }
15927 dahdi_dnd(p, 0);
15928 astman_send_ack(s, m, "DND Disabled");
15929 return 0;
15930 }
15931
15932 static int action_transfer(struct mansession *s, const struct message *m)
15933 {
15934 struct dahdi_pvt *p;
15935 const char *channel = astman_get_header(m, "DAHDIChannel");
15936
15937 if (ast_strlen_zero(channel)) {
15938 astman_send_error(s, m, "No channel specified");
15939 return 0;
15940 }
15941 p = find_channel_from_str(channel);
15942 if (!p) {
15943 astman_send_error(s, m, "No such channel");
15944 return 0;
15945 }
15946 if (!analog_lib_handles(p->sig, 0, 0)) {
15947 astman_send_error(s, m, "Channel signaling is not analog");
15948 return 0;
15949 }
15950 dahdi_fake_event(p,TRANSFER);
15951 astman_send_ack(s, m, "DAHDITransfer");
15952 return 0;
15953 }
15954
15955 static int action_transferhangup(struct mansession *s, const struct message *m)
15956 {
15957 struct dahdi_pvt *p;
15958 const char *channel = astman_get_header(m, "DAHDIChannel");
15959
15960 if (ast_strlen_zero(channel)) {
15961 astman_send_error(s, m, "No channel specified");
15962 return 0;
15963 }
15964 p = find_channel_from_str(channel);
15965 if (!p) {
15966 astman_send_error(s, m, "No such channel");
15967 return 0;
15968 }
15969 if (!analog_lib_handles(p->sig, 0, 0)) {
15970 astman_send_error(s, m, "Channel signaling is not analog");
15971 return 0;
15972 }
15973 dahdi_fake_event(p,HANGUP);
15974 astman_send_ack(s, m, "DAHDIHangup");
15975 return 0;
15976 }
15977
15978 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15979 {
15980 struct dahdi_pvt *p;
15981 const char *channel = astman_get_header(m, "DAHDIChannel");
15982 const char *number = astman_get_header(m, "Number");
15983 int i;
15984
15985 if (ast_strlen_zero(channel)) {
15986 astman_send_error(s, m, "No channel specified");
15987 return 0;
15988 }
15989 if (ast_strlen_zero(number)) {
15990 astman_send_error(s, m, "No number specified");
15991 return 0;
15992 }
15993 p = find_channel_from_str(channel);
15994 if (!p) {
15995 astman_send_error(s, m, "No such channel");
15996 return 0;
15997 }
15998 if (!p->owner) {
15999 astman_send_error(s, m, "Channel does not have it's owner");
16000 return 0;
16001 }
16002 for (i = 0; i < strlen(number); i++) {
16003 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
16004 dahdi_queue_frame(p, &f);
16005 }
16006 astman_send_ack(s, m, "DAHDIDialOffhook");
16007 return 0;
16008 }
16009
16010 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
16011 {
16012 struct dahdi_pvt *tmp = NULL;
16013 const char *id = astman_get_header(m, "ActionID");
16014 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
16015 char idText[256] = "";
16016 int channels = 0;
16017 int dahdichanquery;
16018
16019 if (!dahdichannel || sscanf(dahdichannel, "%30d", &dahdichanquery) != 1) {
16020
16021 dahdichanquery = -1;
16022 }
16023
16024 astman_send_ack(s, m, "DAHDI channel status will follow");
16025 if (!ast_strlen_zero(id))
16026 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
16027
16028 ast_mutex_lock(&iflock);
16029
16030 for (tmp = iflist; tmp; tmp = tmp->next) {
16031 if (tmp->channel > 0) {
16032 int alm;
16033
16034
16035 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
16036 continue;
16037
16038 alm = get_alarms(tmp);
16039 channels++;
16040 if (tmp->owner) {
16041
16042 astman_append(s,
16043 "Event: DAHDIShowChannels\r\n"
16044 "DAHDIChannel: %d\r\n"
16045 "Channel: %s\r\n"
16046 "Uniqueid: %s\r\n"
16047 "AccountCode: %s\r\n"
16048 "Signalling: %s\r\n"
16049 "SignallingCode: %d\r\n"
16050 "Context: %s\r\n"
16051 "DND: %s\r\n"
16052 "Alarm: %s\r\n"
16053 "%s"
16054 "\r\n",
16055 tmp->channel,
16056 tmp->owner->name,
16057 tmp->owner->uniqueid,
16058 tmp->owner->accountcode,
16059 sig2str(tmp->sig),
16060 tmp->sig,
16061 tmp->context,
16062 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16063 alarm2str(alm), idText);
16064 } else {
16065 astman_append(s,
16066 "Event: DAHDIShowChannels\r\n"
16067 "DAHDIChannel: %d\r\n"
16068 "Signalling: %s\r\n"
16069 "SignallingCode: %d\r\n"
16070 "Context: %s\r\n"
16071 "DND: %s\r\n"
16072 "Alarm: %s\r\n"
16073 "%s"
16074 "\r\n",
16075 tmp->channel, sig2str(tmp->sig), tmp->sig,
16076 tmp->context,
16077 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
16078 alarm2str(alm), idText);
16079 }
16080 }
16081 }
16082
16083 ast_mutex_unlock(&iflock);
16084
16085 astman_append(s,
16086 "Event: DAHDIShowChannelsComplete\r\n"
16087 "%s"
16088 "Items: %d\r\n"
16089 "\r\n",
16090 idText,
16091 channels);
16092 return 0;
16093 }
16094
16095 #if defined(HAVE_SS7)
16096 static int linkset_addsigchan(int sigchan)
16097 {
16098 struct dahdi_ss7 *link;
16099 int res;
16100 int curfd;
16101 struct dahdi_params params;
16102 struct dahdi_bufferinfo bi;
16103 struct dahdi_spaninfo si;
16104
16105 if (sigchan < 0) {
16106 ast_log(LOG_ERROR, "Invalid sigchan!\n");
16107 return -1;
16108 }
16109 if (cur_ss7type < 0) {
16110 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
16111 return -1;
16112 }
16113 if (cur_pointcode < 0) {
16114 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
16115 return -1;
16116 }
16117 if (cur_adjpointcode < 0) {
16118 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
16119 return -1;
16120 }
16121 if (cur_defaultdpc < 0) {
16122 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
16123 return -1;
16124 }
16125 if (cur_networkindicator < 0) {
16126 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
16127 return -1;
16128 }
16129 link = ss7_resolve_linkset(cur_linkset);
16130 if (!link) {
16131 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
16132 return -1;
16133 }
16134 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
16135 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
16136 return -1;
16137 }
16138
16139 curfd = link->ss7.numsigchans;
16140
16141
16142 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
16143 if (link->ss7.fds[curfd] < 0) {
16144 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
16145 strerror(errno));
16146 return -1;
16147 }
16148 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
16149 dahdi_close_ss7_fd(link, curfd);
16150 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
16151 strerror(errno));
16152 return -1;
16153 }
16154
16155
16156 memset(¶ms, 0, sizeof(params));
16157 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
16158 if (res) {
16159 dahdi_close_ss7_fd(link, curfd);
16160 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
16161 strerror(errno));
16162 return -1;
16163 }
16164 if (params.sigtype != DAHDI_SIG_HDLCFCS
16165 && params.sigtype != DAHDI_SIG_HARDHDLC
16166 && params.sigtype != DAHDI_SIG_MTP2) {
16167 dahdi_close_ss7_fd(link, curfd);
16168 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
16169 return -1;
16170 }
16171
16172
16173 memset(&bi, 0, sizeof(bi));
16174 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
16175 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
16176 bi.numbufs = 32;
16177 bi.bufsize = 512;
16178 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
16179 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
16180 sigchan, strerror(errno));
16181 dahdi_close_ss7_fd(link, curfd);
16182 return -1;
16183 }
16184
16185
16186 memset(&si, 0, sizeof(si));
16187 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
16188 if (res) {
16189 dahdi_close_ss7_fd(link, curfd);
16190 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
16191 strerror(errno));
16192 }
16193
16194 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
16195 (params.sigtype == DAHDI_SIG_MTP2)
16196 ? SS7_TRANSPORT_DAHDIMTP2
16197 : SS7_TRANSPORT_DAHDIDCHAN,
16198 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
16199 if (res) {
16200 dahdi_close_ss7_fd(link, curfd);
16201 return -1;
16202 }
16203
16204 ++link->ss7.numsigchans;
16205
16206 return 0;
16207 }
16208 #endif
16209
16210 #if defined(HAVE_SS7)
16211 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16212 {
16213 int span;
16214 switch (cmd) {
16215 case CLI_INIT:
16216 e->command = "ss7 set debug {on|off} linkset";
16217 e->usage =
16218 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
16219 " Enables debugging on a given SS7 linkset\n";
16220 return NULL;
16221 case CLI_GENERATE:
16222 return NULL;
16223 }
16224 if (a->argc < 6)
16225 return CLI_SHOWUSAGE;
16226 span = atoi(a->argv[5]);
16227 if ((span < 1) || (span > NUM_SPANS)) {
16228 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
16229 return CLI_SUCCESS;
16230 }
16231 if (!linksets[span-1].ss7.ss7) {
16232 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
16233 } else {
16234 if (!strcasecmp(a->argv[3], "on")) {
16235 linksets[span - 1].ss7.debug = 1;
16236 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
16237 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
16238 } else {
16239 linksets[span - 1].ss7.debug = 0;
16240 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
16241 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
16242 }
16243 }
16244
16245 return CLI_SUCCESS;
16246 }
16247 #endif
16248
16249 #if defined(HAVE_SS7)
16250 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16251 {
16252 int linkset, cic;
16253 int blocked = -1, i;
16254 switch (cmd) {
16255 case CLI_INIT:
16256 e->command = "ss7 block cic";
16257 e->usage =
16258 "Usage: ss7 block cic <linkset> <CIC>\n"
16259 " Sends a remote blocking request for the given CIC on the specified linkset\n";
16260 return NULL;
16261 case CLI_GENERATE:
16262 return NULL;
16263 }
16264 if (a->argc == 5)
16265 linkset = atoi(a->argv[3]);
16266 else
16267 return CLI_SHOWUSAGE;
16268
16269 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16270 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16271 return CLI_SUCCESS;
16272 }
16273
16274 if (!linksets[linkset-1].ss7.ss7) {
16275 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16276 return CLI_SUCCESS;
16277 }
16278
16279 cic = atoi(a->argv[4]);
16280
16281 if (cic < 1) {
16282 ast_cli(a->fd, "Invalid CIC specified!\n");
16283 return CLI_SUCCESS;
16284 }
16285
16286 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16287 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16288 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16289 if (!blocked) {
16290 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16291 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16292 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16293 }
16294 }
16295 }
16296
16297 if (blocked < 0) {
16298 ast_cli(a->fd, "Invalid CIC specified!\n");
16299 return CLI_SUCCESS;
16300 }
16301
16302 if (!blocked)
16303 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
16304 else
16305 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
16306
16307
16308 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16309
16310 return CLI_SUCCESS;
16311 }
16312 #endif
16313
16314 #if defined(HAVE_SS7)
16315 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16316 {
16317 int linkset;
16318 int i;
16319 switch (cmd) {
16320 case CLI_INIT:
16321 e->command = "ss7 block linkset";
16322 e->usage =
16323 "Usage: ss7 block linkset <linkset number>\n"
16324 " Sends a remote blocking request for all CICs on the given linkset\n";
16325 return NULL;
16326 case CLI_GENERATE:
16327 return NULL;
16328 }
16329 if (a->argc == 4)
16330 linkset = atoi(a->argv[3]);
16331 else
16332 return CLI_SHOWUSAGE;
16333
16334 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16335 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16336 return CLI_SUCCESS;
16337 }
16338
16339 if (!linksets[linkset-1].ss7.ss7) {
16340 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16341 return CLI_SUCCESS;
16342 }
16343
16344 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16345 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16346 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16347 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16348 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16349 }
16350
16351
16352 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16353
16354 return CLI_SUCCESS;
16355 }
16356 #endif
16357
16358 #if defined(HAVE_SS7)
16359 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16360 {
16361 int linkset, cic;
16362 int i, blocked = -1;
16363 switch (cmd) {
16364 case CLI_INIT:
16365 e->command = "ss7 unblock cic";
16366 e->usage =
16367 "Usage: ss7 unblock cic <linkset> <CIC>\n"
16368 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
16369 return NULL;
16370 case CLI_GENERATE:
16371 return NULL;
16372 }
16373
16374 if (a->argc == 5)
16375 linkset = atoi(a->argv[3]);
16376 else
16377 return CLI_SHOWUSAGE;
16378
16379 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16380 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16381 return CLI_SUCCESS;
16382 }
16383
16384 if (!linksets[linkset-1].ss7.ss7) {
16385 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16386 return CLI_SUCCESS;
16387 }
16388
16389 cic = atoi(a->argv[4]);
16390
16391 if (cic < 1) {
16392 ast_cli(a->fd, "Invalid CIC specified!\n");
16393 return CLI_SUCCESS;
16394 }
16395
16396 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16397 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
16398 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
16399 if (blocked) {
16400 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16401 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16402 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16403 }
16404 }
16405 }
16406
16407 if (blocked > 0)
16408 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
16409
16410
16411 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16412
16413 return CLI_SUCCESS;
16414 }
16415 #endif
16416
16417 #if defined(HAVE_SS7)
16418 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16419 {
16420 int linkset;
16421 int i;
16422 switch (cmd) {
16423 case CLI_INIT:
16424 e->command = "ss7 unblock linkset";
16425 e->usage =
16426 "Usage: ss7 unblock linkset <linkset number>\n"
16427 " Sends a remote unblocking request for all CICs on the specified linkset\n";
16428 return NULL;
16429 case CLI_GENERATE:
16430 return NULL;
16431 }
16432
16433 if (a->argc == 4)
16434 linkset = atoi(a->argv[3]);
16435 else
16436 return CLI_SHOWUSAGE;
16437
16438 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16439 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16440 return CLI_SUCCESS;
16441 }
16442
16443 if (!linksets[linkset-1].ss7.ss7) {
16444 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16445 return CLI_SUCCESS;
16446 }
16447
16448 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
16449 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
16450 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
16451 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
16452 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
16453 }
16454
16455
16456 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16457
16458 return CLI_SUCCESS;
16459 }
16460 #endif
16461
16462 #if defined(HAVE_SS7)
16463 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16464 {
16465 int linkset;
16466 struct sig_ss7_linkset *ss7;
16467 switch (cmd) {
16468 case CLI_INIT:
16469 e->command = "ss7 show linkset";
16470 e->usage =
16471 "Usage: ss7 show linkset <span>\n"
16472 " Shows the status of an SS7 linkset.\n";
16473 return NULL;
16474 case CLI_GENERATE:
16475 return NULL;
16476 }
16477
16478 if (a->argc < 4)
16479 return CLI_SHOWUSAGE;
16480 linkset = atoi(a->argv[3]);
16481 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16482 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16483 return CLI_SUCCESS;
16484 }
16485 ss7 = &linksets[linkset - 1].ss7;
16486 if (!ss7->ss7) {
16487 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16488 return CLI_SUCCESS;
16489 }
16490
16491 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16492
16493 return CLI_SUCCESS;
16494 }
16495 #endif
16496
16497 #if defined(HAVE_SS7)
16498 static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16499 {
16500 int linkset;
16501
16502 switch (cmd) {
16503 case CLI_INIT:
16504 e->command = "ss7 show channels";
16505 e->usage =
16506 "Usage: ss7 show channels\n"
16507 " Displays SS7 channel information at a glance.\n";
16508 return NULL;
16509 case CLI_GENERATE:
16510 return NULL;
16511 }
16512
16513 if (a->argc != 3)
16514 return CLI_SHOWUSAGE;
16515
16516 sig_ss7_cli_show_channels_header(a->fd);
16517 for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
16518 if (linksets[linkset].ss7.ss7) {
16519 sig_ss7_cli_show_channels(a->fd, &linksets[linkset].ss7);
16520 }
16521 }
16522 return CLI_SUCCESS;
16523 }
16524 #endif
16525
16526 #if defined(HAVE_SS7)
16527 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16528 {
16529 switch (cmd) {
16530 case CLI_INIT:
16531 e->command = "ss7 show version";
16532 e->usage =
16533 "Usage: ss7 show version\n"
16534 " Show the libss7 version\n";
16535 return NULL;
16536 case CLI_GENERATE:
16537 return NULL;
16538 }
16539
16540 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16541
16542 return CLI_SUCCESS;
16543 }
16544 #endif
16545
16546 #if defined(HAVE_SS7)
16547 static struct ast_cli_entry dahdi_ss7_cli[] = {
16548 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16549 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16550 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16551 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16552 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16553 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16554 AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
16555 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16556 };
16557 #endif
16558
16559 #if defined(HAVE_PRI)
16560 #if defined(HAVE_PRI_CCSS)
16561
16562
16563
16564
16565
16566
16567
16568
16569
16570
16571
16572
16573
16574
16575
16576
16577
16578 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16579 {
16580 struct dahdi_pvt *pvt;
16581 struct sig_pri_chan *pvt_chan;
16582 int res;
16583
16584 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16585
16586 pvt = chan->tech_pvt;
16587 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16588 pvt_chan = pvt->sig_pvt;
16589 } else {
16590 pvt_chan = NULL;
16591 }
16592 if (!pvt_chan) {
16593 return -1;
16594 }
16595
16596 ast_module_ref(ast_module_info->self);
16597
16598 res = sig_pri_cc_agent_init(agent, pvt_chan);
16599 if (res) {
16600 ast_module_unref(ast_module_info->self);
16601 }
16602 return res;
16603 }
16604 #endif
16605 #endif
16606
16607 #if defined(HAVE_PRI)
16608 #if defined(HAVE_PRI_CCSS)
16609
16610
16611
16612
16613
16614
16615
16616
16617
16618
16619
16620
16621
16622 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16623 {
16624 sig_pri_cc_agent_destructor(agent);
16625
16626 ast_module_unref(ast_module_info->self);
16627 }
16628 #endif
16629 #endif
16630
16631 #if defined(HAVE_PRI)
16632 #if defined(HAVE_PRI_CCSS)
16633 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16634 .type = dahdi_pri_cc_type,
16635 .init = dahdi_pri_cc_agent_init,
16636 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16637 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16638 .respond = sig_pri_cc_agent_req_rsp,
16639 .status_request = sig_pri_cc_agent_status_req,
16640 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16641 .party_b_free = sig_pri_cc_agent_party_b_free,
16642 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16643 .callee_available = sig_pri_cc_agent_callee_available,
16644 .destructor = dahdi_pri_cc_agent_destructor,
16645 };
16646 #endif
16647 #endif
16648
16649 #if defined(HAVE_PRI)
16650 #if defined(HAVE_PRI_CCSS)
16651 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16652 .type = dahdi_pri_cc_type,
16653 .request_cc = sig_pri_cc_monitor_req_cc,
16654 .suspend = sig_pri_cc_monitor_suspend,
16655 .unsuspend = sig_pri_cc_monitor_unsuspend,
16656 .status_response = sig_pri_cc_monitor_status_rsp,
16657 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16658 .destructor = sig_pri_cc_monitor_destructor,
16659 };
16660 #endif
16661 #endif
16662
16663 static int __unload_module(void)
16664 {
16665 struct dahdi_pvt *p;
16666 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16667 int i, j;
16668 #endif
16669
16670 #ifdef HAVE_PRI
16671 for (i = 0; i < NUM_SPANS; i++) {
16672 if (pris[i].pri.master != AST_PTHREADT_NULL)
16673 pthread_cancel(pris[i].pri.master);
16674 }
16675 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16676 ast_unregister_application(dahdi_send_keypad_facility_app);
16677 #ifdef HAVE_PRI_PROG_W_CAUSE
16678 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16679 #endif
16680 #endif
16681 #if defined(HAVE_SS7)
16682 for (i = 0; i < NUM_SPANS; i++) {
16683 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16684 pthread_cancel(linksets[i].ss7.master);
16685 }
16686 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16687 #endif
16688 #if defined(HAVE_OPENR2)
16689 dahdi_r2_destroy_links();
16690 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16691 ast_unregister_application(dahdi_accept_r2_call_app);
16692 #endif
16693
16694 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16695 ast_manager_unregister("DAHDIDialOffhook");
16696 ast_manager_unregister("DAHDIHangup");
16697 ast_manager_unregister("DAHDITransfer");
16698 ast_manager_unregister("DAHDIDNDoff");
16699 ast_manager_unregister("DAHDIDNDon");
16700 ast_manager_unregister("DAHDIShowChannels");
16701 ast_manager_unregister("DAHDIRestart");
16702 ast_data_unregister(NULL);
16703 ast_channel_unregister(&dahdi_tech);
16704
16705
16706 ast_mutex_lock(&iflock);
16707 for (p = iflist; p; p = p->next) {
16708 if (p->owner)
16709 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16710 }
16711 ast_mutex_unlock(&iflock);
16712
16713 ast_mutex_lock(&monlock);
16714 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16715 pthread_cancel(monitor_thread);
16716 pthread_kill(monitor_thread, SIGURG);
16717 pthread_join(monitor_thread, NULL);
16718 }
16719 monitor_thread = AST_PTHREADT_STOP;
16720 ast_mutex_unlock(&monlock);
16721
16722 destroy_all_channels();
16723
16724 #if defined(HAVE_PRI)
16725 for (i = 0; i < NUM_SPANS; i++) {
16726 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16727 pthread_join(pris[i].pri.master, NULL);
16728 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16729 dahdi_close_pri_fd(&(pris[i]), j);
16730 }
16731 sig_pri_stop_pri(&pris[i].pri);
16732 }
16733 #if defined(HAVE_PRI_CCSS)
16734 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16735 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16736 #endif
16737 sig_pri_unload();
16738 #endif
16739
16740 #if defined(HAVE_SS7)
16741 for (i = 0; i < NUM_SPANS; i++) {
16742 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16743 pthread_join(linksets[i].ss7.master, NULL);
16744 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16745 dahdi_close_ss7_fd(&(linksets[i]), j);
16746 }
16747 }
16748 #endif
16749 ast_cond_destroy(&ss_thread_complete);
16750 return 0;
16751 }
16752
16753 static int unload_module(void)
16754 {
16755 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16756 int y;
16757 #endif
16758 #ifdef HAVE_PRI
16759 for (y = 0; y < NUM_SPANS; y++)
16760 ast_mutex_destroy(&pris[y].pri.lock);
16761 #endif
16762 #if defined(HAVE_SS7)
16763 for (y = 0; y < NUM_SPANS; y++)
16764 ast_mutex_destroy(&linksets[y].ss7.lock);
16765 #endif
16766 return __unload_module();
16767 }
16768
16769 static void string_replace(char *str, int char1, int char2)
16770 {
16771 for (; *str; str++) {
16772 if (*str == char1) {
16773 *str = char2;
16774 }
16775 }
16776 }
16777
16778 static char *parse_spanchan(char *chanstr, char **subdir)
16779 {
16780 char *p;
16781
16782 if ((p = strrchr(chanstr, '!')) == NULL) {
16783 *subdir = NULL;
16784 return chanstr;
16785 }
16786 *p++ = '\0';
16787 string_replace(chanstr, '!', '/');
16788 *subdir = chanstr;
16789 return p;
16790 }
16791
16792 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16793 {
16794 char *c, *chan;
16795 char *subdir;
16796 int x, start, finish;
16797 struct dahdi_pvt *tmp;
16798
16799 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16800 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16801 return -1;
16802 }
16803
16804 c = ast_strdupa(value);
16805 c = parse_spanchan(c, &subdir);
16806
16807 while ((chan = strsep(&c, ","))) {
16808 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16809
16810 } else if (sscanf(chan, "%30d", &start)) {
16811
16812 finish = start;
16813 } else if (!strcasecmp(chan, "pseudo")) {
16814 finish = start = CHAN_PSEUDO;
16815 if (found_pseudo)
16816 *found_pseudo = 1;
16817 } else {
16818 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16819 return -1;
16820 }
16821 if (finish < start) {
16822 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16823 x = finish;
16824 finish = start;
16825 start = x;
16826 }
16827
16828 for (x = start; x <= finish; x++) {
16829 char fn[PATH_MAX];
16830 int real_channel = x;
16831
16832 if (!ast_strlen_zero(subdir)) {
16833 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16834 if (real_channel < 0) {
16835 if (conf->ignore_failed_channels) {
16836 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16837 subdir, x, real_channel);
16838 continue;
16839 } else {
16840 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16841 subdir, x, real_channel);
16842 return -1;
16843 }
16844 }
16845 }
16846 tmp = mkintf(real_channel, conf, reload);
16847
16848 if (tmp) {
16849 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16850 } else {
16851 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16852 (reload == 1) ? "reconfigure" : "register", value);
16853 return -1;
16854 }
16855 }
16856 }
16857
16858 return 0;
16859 }
16860
16861
16862
16863 #define MAX_CHANLIST_LEN 80
16864
16865 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16866 {
16867 char *parse = ast_strdupa(data);
16868 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16869 unsigned int param_count;
16870 unsigned int x;
16871
16872 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16873 return;
16874
16875 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16876
16877
16878
16879 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16880
16881 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16882 confp->chan.echocancel.head.tap_length = x;
16883 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16884 confp->chan.echocancel.head.tap_length = 128;
16885
16886
16887
16888 for (x = 1; x < param_count; x++) {
16889 struct {
16890 char *name;
16891 char *value;
16892 } param;
16893
16894 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16895 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16896 continue;
16897 }
16898
16899 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16900 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16901 continue;
16902 }
16903
16904 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16905
16906 if (param.value) {
16907 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16908 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16909 continue;
16910 }
16911 }
16912 confp->chan.echocancel.head.param_count++;
16913 }
16914 }
16915
16916
16917 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16918
16919 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16920
16921 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16922 {
16923 struct dahdi_pvt *tmp;
16924 int y;
16925 int found_pseudo = 0;
16926 struct ast_variable *dahdichan = NULL;
16927
16928 for (; v; v = v->next) {
16929 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16930 continue;
16931
16932
16933 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16934 if (options & PROC_DAHDI_OPT_NOCHAN) {
16935 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16936 continue;
16937 }
16938 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16939 if (confp->ignore_failed_channels) {
16940 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16941 continue;
16942 } else {
16943 return -1;
16944 }
16945 }
16946 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16947 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16948 confp->ignore_failed_channels = ast_true(v->value);
16949 } else if (!strcasecmp(v->name, "buffers")) {
16950 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16951 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16952 confp->chan.buf_no = numbufs;
16953 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16954 }
16955 } else if (!strcasecmp(v->name, "faxbuffers")) {
16956 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16957 confp->chan.usefaxbuffers = 1;
16958 }
16959 } else if (!strcasecmp(v->name, "dahdichan")) {
16960
16961 dahdichan = v;
16962 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16963 usedistinctiveringdetection = ast_true(v->value);
16964 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16965 distinctiveringaftercid = ast_true(v->value);
16966 } else if (!strcasecmp(v->name, "dring1context")) {
16967 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16968 } else if (!strcasecmp(v->name, "dring2context")) {
16969 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16970 } else if (!strcasecmp(v->name, "dring3context")) {
16971 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16972 } else if (!strcasecmp(v->name, "dring1range")) {
16973 confp->chan.drings.ringnum[0].range = atoi(v->value);
16974 } else if (!strcasecmp(v->name, "dring2range")) {
16975 confp->chan.drings.ringnum[1].range = atoi(v->value);
16976 } else if (!strcasecmp(v->name, "dring3range")) {
16977 confp->chan.drings.ringnum[2].range = atoi(v->value);
16978 } else if (!strcasecmp(v->name, "dring1")) {
16979 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]);
16980 } else if (!strcasecmp(v->name, "dring2")) {
16981 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]);
16982 } else if (!strcasecmp(v->name, "dring3")) {
16983 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]);
16984 } else if (!strcasecmp(v->name, "usecallerid")) {
16985 confp->chan.use_callerid = ast_true(v->value);
16986 } else if (!strcasecmp(v->name, "cidsignalling")) {
16987 if (!strcasecmp(v->value, "bell"))
16988 confp->chan.cid_signalling = CID_SIG_BELL;
16989 else if (!strcasecmp(v->value, "v23"))
16990 confp->chan.cid_signalling = CID_SIG_V23;
16991 else if (!strcasecmp(v->value, "dtmf"))
16992 confp->chan.cid_signalling = CID_SIG_DTMF;
16993 else if (!strcasecmp(v->value, "smdi"))
16994 confp->chan.cid_signalling = CID_SIG_SMDI;
16995 else if (!strcasecmp(v->value, "v23_jp"))
16996 confp->chan.cid_signalling = CID_SIG_V23_JP;
16997 else if (ast_true(v->value))
16998 confp->chan.cid_signalling = CID_SIG_BELL;
16999 } else if (!strcasecmp(v->name, "cidstart")) {
17000 if (!strcasecmp(v->value, "ring"))
17001 confp->chan.cid_start = CID_START_RING;
17002 else if (!strcasecmp(v->value, "polarity_in"))
17003 confp->chan.cid_start = CID_START_POLARITY_IN;
17004 else if (!strcasecmp(v->value, "polarity"))
17005 confp->chan.cid_start = CID_START_POLARITY;
17006 else if (!strcasecmp(v->value, "dtmf"))
17007 confp->chan.cid_start = CID_START_DTMF_NOALERT;
17008 else if (ast_true(v->value))
17009 confp->chan.cid_start = CID_START_RING;
17010 } else if (!strcasecmp(v->name, "threewaycalling")) {
17011 confp->chan.threewaycalling = ast_true(v->value);
17012 } else if (!strcasecmp(v->name, "cancallforward")) {
17013 confp->chan.cancallforward = ast_true(v->value);
17014 } else if (!strcasecmp(v->name, "relaxdtmf")) {
17015 if (ast_true(v->value))
17016 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
17017 else
17018 confp->chan.dtmfrelax = 0;
17019 } else if (!strcasecmp(v->name, "mailbox")) {
17020 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
17021 } else if (!strcasecmp(v->name, "hasvoicemail")) {
17022 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
17023 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
17024 }
17025 } else if (!strcasecmp(v->name, "adsi")) {
17026 confp->chan.adsi = ast_true(v->value);
17027 } else if (!strcasecmp(v->name, "usesmdi")) {
17028 confp->chan.use_smdi = ast_true(v->value);
17029 } else if (!strcasecmp(v->name, "smdiport")) {
17030 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
17031 } else if (!strcasecmp(v->name, "transfer")) {
17032 confp->chan.transfer = ast_true(v->value);
17033 } else if (!strcasecmp(v->name, "canpark")) {
17034 confp->chan.canpark = ast_true(v->value);
17035 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
17036 confp->chan.echocanbridged = ast_true(v->value);
17037 } else if (!strcasecmp(v->name, "busydetect")) {
17038 confp->chan.busydetect = ast_true(v->value);
17039 } else if (!strcasecmp(v->name, "busycount")) {
17040 confp->chan.busycount = atoi(v->value);
17041 } else if (!strcasecmp(v->name, "busypattern")) {
17042 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
17043 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
17044 }
17045 } else if (!strcasecmp(v->name, "callprogress")) {
17046 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
17047 if (ast_true(v->value))
17048 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
17049 } else if (!strcasecmp(v->name, "waitfordialtone")) {
17050 confp->chan.waitfordialtone = atoi(v->value);
17051 } else if (!strcasecmp(v->name, "faxdetect")) {
17052 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
17053 if (!strcasecmp(v->value, "incoming")) {
17054 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
17055 } else if (!strcasecmp(v->value, "outgoing")) {
17056 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
17057 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
17058 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
17059 } else if (!strcasecmp(v->name, "echocancel")) {
17060 process_echocancel(confp, v->value, v->lineno);
17061 } else if (!strcasecmp(v->name, "echotraining")) {
17062 if (sscanf(v->value, "%30d", &y) == 1) {
17063 if ((y < 10) || (y > 4000)) {
17064 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
17065 } else {
17066 confp->chan.echotraining = y;
17067 }
17068 } else if (ast_true(v->value)) {
17069 confp->chan.echotraining = 400;
17070 } else
17071 confp->chan.echotraining = 0;
17072 } else if (!strcasecmp(v->name, "hidecallerid")) {
17073 confp->chan.hidecallerid = ast_true(v->value);
17074 } else if (!strcasecmp(v->name, "hidecalleridname")) {
17075 confp->chan.hidecalleridname = ast_true(v->value);
17076 } else if (!strcasecmp(v->name, "pulsedial")) {
17077 confp->chan.pulse = ast_true(v->value);
17078 } else if (!strcasecmp(v->name, "callreturn")) {
17079 confp->chan.callreturn = ast_true(v->value);
17080 } else if (!strcasecmp(v->name, "callwaiting")) {
17081 confp->chan.callwaiting = ast_true(v->value);
17082 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
17083 confp->chan.callwaitingcallerid = ast_true(v->value);
17084 } else if (!strcasecmp(v->name, "context")) {
17085 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
17086 } else if (!strcasecmp(v->name, "language")) {
17087 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
17088 } else if (!strcasecmp(v->name, "progzone")) {
17089 ast_copy_string(progzone, v->value, sizeof(progzone));
17090 } else if (!strcasecmp(v->name, "mohinterpret")
17091 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
17092 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
17093 } else if (!strcasecmp(v->name, "mohsuggest")) {
17094 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
17095 } else if (!strcasecmp(v->name, "parkinglot")) {
17096 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
17097 } else if (!strcasecmp(v->name, "stripmsd")) {
17098 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
17099 confp->chan.stripmsd = atoi(v->value);
17100 } else if (!strcasecmp(v->name, "jitterbuffers")) {
17101 numbufs = atoi(v->value);
17102 } else if (!strcasecmp(v->name, "group")) {
17103 confp->chan.group = ast_get_group(v->value);
17104 } else if (!strcasecmp(v->name, "callgroup")) {
17105 if (!strcasecmp(v->value, "none"))
17106 confp->chan.callgroup = 0;
17107 else
17108 confp->chan.callgroup = ast_get_group(v->value);
17109 } else if (!strcasecmp(v->name, "pickupgroup")) {
17110 if (!strcasecmp(v->value, "none"))
17111 confp->chan.pickupgroup = 0;
17112 else
17113 confp->chan.pickupgroup = ast_get_group(v->value);
17114 } else if (!strcasecmp(v->name, "setvar")) {
17115 char *varname = ast_strdupa(v->value), *varval = NULL;
17116 struct ast_variable *tmpvar;
17117 if (varname && (varval = strchr(varname, '='))) {
17118 *varval++ = '\0';
17119 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
17120 tmpvar->next = confp->chan.vars;
17121 confp->chan.vars = tmpvar;
17122 }
17123 }
17124 } else if (!strcasecmp(v->name, "immediate")) {
17125 confp->chan.immediate = ast_true(v->value);
17126 } else if (!strcasecmp(v->name, "transfertobusy")) {
17127 confp->chan.transfertobusy = ast_true(v->value);
17128 } else if (!strcasecmp(v->name, "mwimonitor")) {
17129 confp->chan.mwimonitor_neon = 0;
17130 confp->chan.mwimonitor_fsk = 0;
17131 confp->chan.mwimonitor_rpas = 0;
17132 if (strcasestr(v->value, "fsk")) {
17133 confp->chan.mwimonitor_fsk = 1;
17134 }
17135 if (strcasestr(v->value, "rpas")) {
17136 confp->chan.mwimonitor_rpas = 1;
17137 }
17138 if (strcasestr(v->value, "neon")) {
17139 confp->chan.mwimonitor_neon = 1;
17140 }
17141
17142 if (ast_true(v->value)) {
17143 confp->chan.mwimonitor_fsk = 1;
17144 }
17145 } else if (!strcasecmp(v->name, "cid_rxgain")) {
17146 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
17147 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
17148 }
17149 } else if (!strcasecmp(v->name, "rxgain")) {
17150 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
17151 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
17152 }
17153 } else if (!strcasecmp(v->name, "txgain")) {
17154 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
17155 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
17156 }
17157 } else if (!strcasecmp(v->name, "txdrc")) {
17158 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
17159 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
17160 }
17161 } else if (!strcasecmp(v->name, "rxdrc")) {
17162 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
17163 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
17164 }
17165 } else if (!strcasecmp(v->name, "tonezone")) {
17166 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
17167 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
17168 }
17169 } else if (!strcasecmp(v->name, "callerid")) {
17170 if (!strcasecmp(v->value, "asreceived")) {
17171 confp->chan.cid_num[0] = '\0';
17172 confp->chan.cid_name[0] = '\0';
17173 } else {
17174 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
17175 }
17176 } else if (!strcasecmp(v->name, "fullname")) {
17177 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
17178 } else if (!strcasecmp(v->name, "cid_number")) {
17179 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
17180 } else if (!strcasecmp(v->name, "cid_tag")) {
17181 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
17182 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
17183 confp->chan.dahditrcallerid = ast_true(v->value);
17184 } else if (!strcasecmp(v->name, "restrictcid")) {
17185 confp->chan.restrictcid = ast_true(v->value);
17186 } else if (!strcasecmp(v->name, "usecallingpres")) {
17187 confp->chan.use_callingpres = ast_true(v->value);
17188 } else if (!strcasecmp(v->name, "accountcode")) {
17189 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
17190 } else if (!strcasecmp(v->name, "amaflags")) {
17191 y = ast_cdr_amaflags2int(v->value);
17192 if (y < 0)
17193 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
17194 else
17195 confp->chan.amaflags = y;
17196 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
17197 confp->chan.polarityonanswerdelay = atoi(v->value);
17198 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
17199 confp->chan.answeronpolarityswitch = ast_true(v->value);
17200 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
17201 confp->chan.hanguponpolarityswitch = ast_true(v->value);
17202 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
17203 confp->chan.sendcalleridafter = atoi(v->value);
17204 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
17205 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
17206 } else if (ast_cc_is_config_param(v->name)) {
17207 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
17208 } else if (!strcasecmp(v->name, "mwisendtype")) {
17209 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
17210 if (!strcasecmp(v->value, "rpas")) {
17211 mwisend_rpas = 1;
17212 } else {
17213 mwisend_rpas = 0;
17214 }
17215 #else
17216
17217 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
17218 if (strcasestr(v->value, "nofsk")) {
17219 confp->chan.mwisend_fsk = 0;
17220 } else {
17221 confp->chan.mwisend_fsk = 1;
17222 }
17223 if (strcasestr(v->value, "rpas")) {
17224 confp->chan.mwisend_rpas = 1;
17225 } else {
17226 confp->chan.mwisend_rpas = 0;
17227 }
17228 if (strcasestr(v->value, "lrev")) {
17229 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
17230 }
17231 if (strcasestr(v->value, "hvdc")) {
17232 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
17233 }
17234 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
17235 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
17236 }
17237 #endif
17238 } else if (reload != 1) {
17239 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
17240 int orig_radio = confp->chan.radio;
17241 int orig_outsigmod = confp->chan.outsigmod;
17242 int orig_auto = confp->is_sig_auto;
17243
17244 confp->chan.radio = 0;
17245 confp->chan.outsigmod = -1;
17246 confp->is_sig_auto = 0;
17247 if (!strcasecmp(v->value, "em")) {
17248 confp->chan.sig = SIG_EM;
17249 } else if (!strcasecmp(v->value, "em_e1")) {
17250 confp->chan.sig = SIG_EM_E1;
17251 } else if (!strcasecmp(v->value, "em_w")) {
17252 confp->chan.sig = SIG_EMWINK;
17253 } else if (!strcasecmp(v->value, "fxs_ls")) {
17254 confp->chan.sig = SIG_FXSLS;
17255 } else if (!strcasecmp(v->value, "fxs_gs")) {
17256 confp->chan.sig = SIG_FXSGS;
17257 } else if (!strcasecmp(v->value, "fxs_ks")) {
17258 confp->chan.sig = SIG_FXSKS;
17259 } else if (!strcasecmp(v->value, "fxo_ls")) {
17260 confp->chan.sig = SIG_FXOLS;
17261 } else if (!strcasecmp(v->value, "fxo_gs")) {
17262 confp->chan.sig = SIG_FXOGS;
17263 } else if (!strcasecmp(v->value, "fxo_ks")) {
17264 confp->chan.sig = SIG_FXOKS;
17265 } else if (!strcasecmp(v->value, "fxs_rx")) {
17266 confp->chan.sig = SIG_FXSKS;
17267 confp->chan.radio = 1;
17268 } else if (!strcasecmp(v->value, "fxo_rx")) {
17269 confp->chan.sig = SIG_FXOLS;
17270 confp->chan.radio = 1;
17271 } else if (!strcasecmp(v->value, "fxs_tx")) {
17272 confp->chan.sig = SIG_FXSLS;
17273 confp->chan.radio = 1;
17274 } else if (!strcasecmp(v->value, "fxo_tx")) {
17275 confp->chan.sig = SIG_FXOGS;
17276 confp->chan.radio = 1;
17277 } else if (!strcasecmp(v->value, "em_rx")) {
17278 confp->chan.sig = SIG_EM;
17279 confp->chan.radio = 1;
17280 } else if (!strcasecmp(v->value, "em_tx")) {
17281 confp->chan.sig = SIG_EM;
17282 confp->chan.radio = 1;
17283 } else if (!strcasecmp(v->value, "em_rxtx")) {
17284 confp->chan.sig = SIG_EM;
17285 confp->chan.radio = 2;
17286 } else if (!strcasecmp(v->value, "em_txrx")) {
17287 confp->chan.sig = SIG_EM;
17288 confp->chan.radio = 2;
17289 } else if (!strcasecmp(v->value, "sf")) {
17290 confp->chan.sig = SIG_SF;
17291 } else if (!strcasecmp(v->value, "sf_w")) {
17292 confp->chan.sig = SIG_SFWINK;
17293 } else if (!strcasecmp(v->value, "sf_featd")) {
17294 confp->chan.sig = SIG_FEATD;
17295 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17296 confp->chan.sig = SIG_FEATDMF;
17297 } else if (!strcasecmp(v->value, "sf_featb")) {
17298 confp->chan.sig = SIG_SF_FEATB;
17299 } else if (!strcasecmp(v->value, "sf")) {
17300 confp->chan.sig = SIG_SF;
17301 } else if (!strcasecmp(v->value, "sf_rx")) {
17302 confp->chan.sig = SIG_SF;
17303 confp->chan.radio = 1;
17304 } else if (!strcasecmp(v->value, "sf_tx")) {
17305 confp->chan.sig = SIG_SF;
17306 confp->chan.radio = 1;
17307 } else if (!strcasecmp(v->value, "sf_rxtx")) {
17308 confp->chan.sig = SIG_SF;
17309 confp->chan.radio = 2;
17310 } else if (!strcasecmp(v->value, "sf_txrx")) {
17311 confp->chan.sig = SIG_SF;
17312 confp->chan.radio = 2;
17313 } else if (!strcasecmp(v->value, "featd")) {
17314 confp->chan.sig = SIG_FEATD;
17315 } else if (!strcasecmp(v->value, "featdmf")) {
17316 confp->chan.sig = SIG_FEATDMF;
17317 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17318 confp->chan.sig = SIG_FEATDMF_TA;
17319 } else if (!strcasecmp(v->value, "e911")) {
17320 confp->chan.sig = SIG_E911;
17321 } else if (!strcasecmp(v->value, "fgccama")) {
17322 confp->chan.sig = SIG_FGC_CAMA;
17323 } else if (!strcasecmp(v->value, "fgccamamf")) {
17324 confp->chan.sig = SIG_FGC_CAMAMF;
17325 } else if (!strcasecmp(v->value, "featb")) {
17326 confp->chan.sig = SIG_FEATB;
17327 #ifdef HAVE_PRI
17328 } else if (!strcasecmp(v->value, "pri_net")) {
17329 confp->chan.sig = SIG_PRI;
17330 confp->pri.pri.nodetype = PRI_NETWORK;
17331 } else if (!strcasecmp(v->value, "pri_cpe")) {
17332 confp->chan.sig = SIG_PRI;
17333 confp->pri.pri.nodetype = PRI_CPE;
17334 } else if (!strcasecmp(v->value, "bri_cpe")) {
17335 confp->chan.sig = SIG_BRI;
17336 confp->pri.pri.nodetype = PRI_CPE;
17337 } else if (!strcasecmp(v->value, "bri_net")) {
17338 confp->chan.sig = SIG_BRI;
17339 confp->pri.pri.nodetype = PRI_NETWORK;
17340 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
17341 confp->chan.sig = SIG_BRI_PTMP;
17342 confp->pri.pri.nodetype = PRI_CPE;
17343 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
17344 #if defined(HAVE_PRI_CALL_HOLD)
17345 confp->chan.sig = SIG_BRI_PTMP;
17346 confp->pri.pri.nodetype = PRI_NETWORK;
17347 #else
17348 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
17349 #endif
17350 #endif
17351 #if defined(HAVE_SS7)
17352 } else if (!strcasecmp(v->value, "ss7")) {
17353 confp->chan.sig = SIG_SS7;
17354 #endif
17355 #ifdef HAVE_OPENR2
17356 } else if (!strcasecmp(v->value, "mfcr2")) {
17357 confp->chan.sig = SIG_MFCR2;
17358 #endif
17359 } else if (!strcasecmp(v->value, "auto")) {
17360 confp->is_sig_auto = 1;
17361 } else {
17362 confp->chan.outsigmod = orig_outsigmod;
17363 confp->chan.radio = orig_radio;
17364 confp->is_sig_auto = orig_auto;
17365 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17366 }
17367 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
17368 if (!strcasecmp(v->value, "em")) {
17369 confp->chan.outsigmod = SIG_EM;
17370 } else if (!strcasecmp(v->value, "em_e1")) {
17371 confp->chan.outsigmod = SIG_EM_E1;
17372 } else if (!strcasecmp(v->value, "em_w")) {
17373 confp->chan.outsigmod = SIG_EMWINK;
17374 } else if (!strcasecmp(v->value, "sf")) {
17375 confp->chan.outsigmod = SIG_SF;
17376 } else if (!strcasecmp(v->value, "sf_w")) {
17377 confp->chan.outsigmod = SIG_SFWINK;
17378 } else if (!strcasecmp(v->value, "sf_featd")) {
17379 confp->chan.outsigmod = SIG_FEATD;
17380 } else if (!strcasecmp(v->value, "sf_featdmf")) {
17381 confp->chan.outsigmod = SIG_FEATDMF;
17382 } else if (!strcasecmp(v->value, "sf_featb")) {
17383 confp->chan.outsigmod = SIG_SF_FEATB;
17384 } else if (!strcasecmp(v->value, "sf")) {
17385 confp->chan.outsigmod = SIG_SF;
17386 } else if (!strcasecmp(v->value, "featd")) {
17387 confp->chan.outsigmod = SIG_FEATD;
17388 } else if (!strcasecmp(v->value, "featdmf")) {
17389 confp->chan.outsigmod = SIG_FEATDMF;
17390 } else if (!strcasecmp(v->value, "featdmf_ta")) {
17391 confp->chan.outsigmod = SIG_FEATDMF_TA;
17392 } else if (!strcasecmp(v->value, "e911")) {
17393 confp->chan.outsigmod = SIG_E911;
17394 } else if (!strcasecmp(v->value, "fgccama")) {
17395 confp->chan.outsigmod = SIG_FGC_CAMA;
17396 } else if (!strcasecmp(v->value, "fgccamamf")) {
17397 confp->chan.outsigmod = SIG_FGC_CAMAMF;
17398 } else if (!strcasecmp(v->value, "featb")) {
17399 confp->chan.outsigmod = SIG_FEATB;
17400 } else {
17401 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
17402 }
17403 #ifdef HAVE_PRI
17404 } else if (!strcasecmp(v->name, "pridialplan")) {
17405 if (!strcasecmp(v->value, "national")) {
17406 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
17407 } else if (!strcasecmp(v->value, "unknown")) {
17408 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
17409 } else if (!strcasecmp(v->value, "private")) {
17410 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
17411 } else if (!strcasecmp(v->value, "international")) {
17412 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
17413 } else if (!strcasecmp(v->value, "local")) {
17414 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
17415 } else if (!strcasecmp(v->value, "dynamic")) {
17416 confp->pri.pri.dialplan = -1;
17417 } else if (!strcasecmp(v->value, "redundant")) {
17418 confp->pri.pri.dialplan = -2;
17419 } else {
17420 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
17421 }
17422 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
17423 if (!strcasecmp(v->value, "national")) {
17424 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
17425 } else if (!strcasecmp(v->value, "unknown")) {
17426 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
17427 } else if (!strcasecmp(v->value, "private")) {
17428 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
17429 } else if (!strcasecmp(v->value, "international")) {
17430 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
17431 } else if (!strcasecmp(v->value, "local")) {
17432 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
17433 } else if (!strcasecmp(v->value, "dynamic")) {
17434 confp->pri.pri.localdialplan = -1;
17435 } else if (!strcasecmp(v->value, "redundant")) {
17436 confp->pri.pri.localdialplan = -2;
17437 } else {
17438 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
17439 }
17440 } else if (!strcasecmp(v->name, "switchtype")) {
17441 if (!strcasecmp(v->value, "national"))
17442 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
17443 else if (!strcasecmp(v->value, "ni1"))
17444 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
17445 else if (!strcasecmp(v->value, "dms100"))
17446 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
17447 else if (!strcasecmp(v->value, "4ess"))
17448 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
17449 else if (!strcasecmp(v->value, "5ess"))
17450 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
17451 else if (!strcasecmp(v->value, "euroisdn"))
17452 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
17453 else if (!strcasecmp(v->value, "qsig"))
17454 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
17455 else {
17456 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
17457 return -1;
17458 }
17459 } else if (!strcasecmp(v->name, "msn")) {
17460 ast_copy_string(confp->pri.pri.msn_list, v->value,
17461 sizeof(confp->pri.pri.msn_list));
17462 } else if (!strcasecmp(v->name, "nsf")) {
17463 if (!strcasecmp(v->value, "sdn"))
17464 confp->pri.pri.nsf = PRI_NSF_SDN;
17465 else if (!strcasecmp(v->value, "megacom"))
17466 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
17467 else if (!strcasecmp(v->value, "tollfreemegacom"))
17468 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17469 else if (!strcasecmp(v->value, "accunet"))
17470 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17471 else if (!strcasecmp(v->value, "none"))
17472 confp->pri.pri.nsf = PRI_NSF_NONE;
17473 else {
17474 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17475 confp->pri.pri.nsf = PRI_NSF_NONE;
17476 }
17477 } else if (!strcasecmp(v->name, "priindication")) {
17478 if (!strcasecmp(v->value, "outofband"))
17479 confp->chan.priindication_oob = 1;
17480 else if (!strcasecmp(v->value, "inband"))
17481 confp->chan.priindication_oob = 0;
17482 else
17483 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17484 v->value, v->lineno);
17485 } else if (!strcasecmp(v->name, "priexclusive")) {
17486 confp->chan.priexclusive = ast_true(v->value);
17487 } else if (!strcasecmp(v->name, "internationalprefix")) {
17488 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17489 } else if (!strcasecmp(v->name, "nationalprefix")) {
17490 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17491 } else if (!strcasecmp(v->name, "localprefix")) {
17492 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17493 } else if (!strcasecmp(v->name, "privateprefix")) {
17494 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17495 } else if (!strcasecmp(v->name, "unknownprefix")) {
17496 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17497 } else if (!strcasecmp(v->name, "resetinterval")) {
17498 if (!strcasecmp(v->value, "never"))
17499 confp->pri.pri.resetinterval = -1;
17500 else if (atoi(v->value) >= 60)
17501 confp->pri.pri.resetinterval = atoi(v->value);
17502 else
17503 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17504 v->value, v->lineno);
17505 } else if (!strcasecmp(v->name, "minunused")) {
17506 confp->pri.pri.minunused = atoi(v->value);
17507 } else if (!strcasecmp(v->name, "minidle")) {
17508 confp->pri.pri.minidle = atoi(v->value);
17509 } else if (!strcasecmp(v->name, "idleext")) {
17510 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17511 } else if (!strcasecmp(v->name, "idledial")) {
17512 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17513 } else if (!strcasecmp(v->name, "overlapdial")) {
17514 if (ast_true(v->value)) {
17515 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17516 } else if (!strcasecmp(v->value, "incoming")) {
17517 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17518 } else if (!strcasecmp(v->value, "outgoing")) {
17519 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17520 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17521 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17522 } else {
17523 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17524 }
17525 #ifdef HAVE_PRI_PROG_W_CAUSE
17526 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17527 if (!strcasecmp(v->value, "logical")) {
17528 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17529 } else if (!strcasecmp(v->value, "physical")) {
17530 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17531 } else {
17532 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17533 }
17534 #endif
17535 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17536 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17537 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17538 } else if (!strcasecmp(v->name, "service_message_support")) {
17539
17540 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17541 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17542 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17543 confp->pri.pri.enable_service_message_support = 1;
17544 } else {
17545 confp->pri.pri.enable_service_message_support = 0;
17546 }
17547 #endif
17548 #ifdef HAVE_PRI_INBANDDISCONNECT
17549 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17550 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17551 #endif
17552 } else if (!strcasecmp(v->name, "pritimer")) {
17553 #ifdef PRI_GETSET_TIMERS
17554 char tmp[20];
17555 char *timerc;
17556 char *c;
17557 int timer;
17558 int timeridx;
17559
17560 ast_copy_string(tmp, v->value, sizeof(tmp));
17561 c = tmp;
17562 timerc = strsep(&c, ",");
17563 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17564 timeridx = pri_timer2idx(timerc);
17565 timer = atoi(c);
17566 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17567 ast_log(LOG_WARNING,
17568 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17569 v->lineno);
17570 } else if (!timer) {
17571 ast_log(LOG_WARNING,
17572 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17573 c, timerc, v->lineno);
17574 } else {
17575 confp->pri.pri.pritimers[timeridx] = timer;
17576 }
17577 } else {
17578 ast_log(LOG_WARNING,
17579 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17580 v->value, v->lineno);
17581 }
17582 #endif
17583 } else if (!strcasecmp(v->name, "facilityenable")) {
17584 confp->pri.pri.facilityenable = ast_true(v->value);
17585 #if defined(HAVE_PRI_AOC_EVENTS)
17586 } else if (!strcasecmp(v->name, "aoc_enable")) {
17587 confp->pri.pri.aoc_passthrough_flag = 0;
17588 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17589 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17590 }
17591 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17592 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17593 }
17594 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17595 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17596 }
17597 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17598 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17599 #endif
17600 #if defined(HAVE_PRI_CALL_HOLD)
17601 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17602 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17603 #endif
17604 #if defined(HAVE_PRI_CCSS)
17605 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17606 if (!strcasecmp(v->value, "global")) {
17607 confp->pri.pri.cc_ptmp_recall_mode = 0;
17608 } else if (!strcasecmp(v->value, "specific")) {
17609 confp->pri.pri.cc_ptmp_recall_mode = 1;
17610 } else {
17611 confp->pri.pri.cc_ptmp_recall_mode = 1;
17612 }
17613 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17614 if (!strcasecmp(v->value, "release")) {
17615 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17616 } else if (!strcasecmp(v->value, "retain")) {
17617 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17618 } else if (!strcasecmp(v->value, "do_not_care")) {
17619 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17620 } else {
17621 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17622 }
17623 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17624 if (!strcasecmp(v->value, "release")) {
17625 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17626 } else if (!strcasecmp(v->value, "retain")) {
17627 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17628 } else {
17629 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17630 }
17631 #endif
17632 #if defined(HAVE_PRI_CALL_WAITING)
17633 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17634 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17635 if (confp->pri.pri.max_call_waiting_calls < 0) {
17636
17637 confp->pri.pri.max_call_waiting_calls = 0;
17638 }
17639 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17640 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17641 #endif
17642 #if defined(HAVE_PRI_MWI)
17643 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17644 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17645 sizeof(confp->pri.pri.mwi_mailboxes));
17646 #endif
17647 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17648 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17649 } else if (!strcasecmp(v->name, "layer1_presence")) {
17650 if (!strcasecmp(v->value, "required")) {
17651 confp->pri.pri.layer1_ignored = 0;
17652 } else if (!strcasecmp(v->value, "ignore")) {
17653 confp->pri.pri.layer1_ignored = 1;
17654 } else {
17655
17656 confp->pri.pri.layer1_ignored = 0;
17657 }
17658 #if defined(HAVE_PRI_L2_PERSISTENCE)
17659 } else if (!strcasecmp(v->name, "layer2_persistence")) {
17660 if (!strcasecmp(v->value, "keep_up")) {
17661 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_KEEP_UP;
17662 } else if (!strcasecmp(v->value, "leave_down")) {
17663 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_LEAVE_DOWN;
17664 } else {
17665 confp->pri.pri.l2_persistence = PRI_L2_PERSISTENCE_DEFAULT;
17666 }
17667 #endif
17668 #endif
17669 #if defined(HAVE_SS7)
17670 } else if (!strcasecmp(v->name, "ss7type")) {
17671 if (!strcasecmp(v->value, "itu")) {
17672 cur_ss7type = SS7_ITU;
17673 } else if (!strcasecmp(v->value, "ansi")) {
17674 cur_ss7type = SS7_ANSI;
17675 } else
17676 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17677 } else if (!strcasecmp(v->name, "linkset")) {
17678 cur_linkset = atoi(v->value);
17679 } else if (!strcasecmp(v->name, "pointcode")) {
17680 cur_pointcode = parse_pointcode(v->value);
17681 } else if (!strcasecmp(v->name, "adjpointcode")) {
17682 cur_adjpointcode = parse_pointcode(v->value);
17683 } else if (!strcasecmp(v->name, "defaultdpc")) {
17684 cur_defaultdpc = parse_pointcode(v->value);
17685 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17686 cur_cicbeginswith = atoi(v->value);
17687 } else if (!strcasecmp(v->name, "networkindicator")) {
17688 if (!strcasecmp(v->value, "national"))
17689 cur_networkindicator = SS7_NI_NAT;
17690 else if (!strcasecmp(v->value, "national_spare"))
17691 cur_networkindicator = SS7_NI_NAT_SPARE;
17692 else if (!strcasecmp(v->value, "international"))
17693 cur_networkindicator = SS7_NI_INT;
17694 else if (!strcasecmp(v->value, "international_spare"))
17695 cur_networkindicator = SS7_NI_INT_SPARE;
17696 else
17697 cur_networkindicator = -1;
17698 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17699 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17700 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17701 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17702 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17703 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17704 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17705 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17706 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17707 if (!strcasecmp(v->value, "national")) {
17708 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17709 } else if (!strcasecmp(v->value, "international")) {
17710 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17711 } else if (!strcasecmp(v->value, "subscriber")) {
17712 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17713 } else if (!strcasecmp(v->value, "unknown")) {
17714 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17715 } else if (!strcasecmp(v->value, "dynamic")) {
17716 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17717 } else {
17718 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17719 }
17720 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17721 if (!strcasecmp(v->value, "national")) {
17722 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17723 } else if (!strcasecmp(v->value, "international")) {
17724 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17725 } else if (!strcasecmp(v->value, "subscriber")) {
17726 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17727 } else if (!strcasecmp(v->value, "unknown")) {
17728 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17729 } else if (!strcasecmp(v->value, "dynamic")) {
17730 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17731 } else {
17732 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17733 }
17734 } else if (!strcasecmp(v->name, "sigchan")) {
17735 int sigchan, res;
17736 sigchan = atoi(v->value);
17737 res = linkset_addsigchan(sigchan);
17738 if (res < 0)
17739 return -1;
17740
17741 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17742 struct dahdi_ss7 *link;
17743 link = ss7_resolve_linkset(cur_linkset);
17744 if (!link) {
17745 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17746 return -1;
17747 }
17748 if (ast_true(v->value))
17749 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17750 #endif
17751 #ifdef HAVE_OPENR2
17752 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17753 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17754 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);
17755 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17756 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17757 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17758 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17759 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17760 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17761 confp->mfcr2.variant = OR2_VAR_ITU;
17762 }
17763 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17764 confp->mfcr2.mfback_timeout = atoi(v->value);
17765 if (!confp->mfcr2.mfback_timeout) {
17766 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17767 confp->mfcr2.mfback_timeout = -1;
17768 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17769 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17770 }
17771 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17772 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17773 if (confp->mfcr2.metering_pulse_timeout > 500) {
17774 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17775 }
17776 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17777 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17778 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17779 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17780 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17781 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17782 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17783 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17784 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17785 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17786 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17787 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17788 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17789 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17790 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17791 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17792 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17793 #endif
17794 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17795 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17796 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17797 confp->mfcr2.max_ani = atoi(v->value);
17798 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17799 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17800 }
17801 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17802 confp->mfcr2.max_dnis = atoi(v->value);
17803 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17804 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17805 }
17806 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17807 confp->mfcr2.category = openr2_proto_get_category(v->value);
17808 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17809 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17810 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17811 v->value, v->lineno);
17812 }
17813 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17814 openr2_log_level_t tmplevel;
17815 char *clevel;
17816 char *logval = ast_strdupa(v->value);
17817 while (logval) {
17818 clevel = strsep(&logval,",");
17819 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17820 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17821 continue;
17822 }
17823 confp->mfcr2.loglevel |= tmplevel;
17824 }
17825 #endif
17826 } else if (!strcasecmp(v->name, "cadence")) {
17827
17828 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17829 int i;
17830 struct dahdi_ring_cadence new_cadence;
17831 int cid_location = -1;
17832 int firstcadencepos = 0;
17833 char original_args[80];
17834 int cadence_is_ok = 1;
17835
17836 ast_copy_string(original_args, v->value, sizeof(original_args));
17837
17838 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]);
17839
17840
17841 if (element_count % 2 == 1) {
17842 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17843 cadence_is_ok = 0;
17844 }
17845
17846
17847 for (i = 0; i < element_count; i++) {
17848 if (c[i] == 0) {
17849 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17850 cadence_is_ok = 0;
17851 break;
17852 } else if (c[i] < 0) {
17853 if (i % 2 == 1) {
17854
17855 if (cid_location == -1) {
17856 cid_location = i;
17857 c[i] *= -1;
17858 } else {
17859 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17860 cadence_is_ok = 0;
17861 break;
17862 }
17863 } else {
17864 if (firstcadencepos == 0) {
17865 firstcadencepos = i;
17866
17867 } else {
17868 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17869 cadence_is_ok = 0;
17870 break;
17871 }
17872 }
17873 }
17874 }
17875
17876
17877 for (i = 0; i < 16; i++) {
17878 new_cadence.ringcadence[i] = c[i];
17879 }
17880
17881 if (cadence_is_ok) {
17882
17883 if (element_count < 2) {
17884 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17885 } else {
17886 if (cid_location == -1) {
17887
17888 cid_location = 1;
17889 } else {
17890
17891 cid_location = (cid_location + 1) / 2;
17892 }
17893
17894 if (!user_has_defined_cadences++)
17895
17896 num_cadence = 0;
17897 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17898 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17899 else {
17900 cadences[num_cadence] = new_cadence;
17901 cidrings[num_cadence++] = cid_location;
17902 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17903 }
17904 }
17905 }
17906 } else if (!strcasecmp(v->name, "ringtimeout")) {
17907 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17908 } else if (!strcasecmp(v->name, "prewink")) {
17909 confp->timing.prewinktime = atoi(v->value);
17910 } else if (!strcasecmp(v->name, "preflash")) {
17911 confp->timing.preflashtime = atoi(v->value);
17912 } else if (!strcasecmp(v->name, "wink")) {
17913 confp->timing.winktime = atoi(v->value);
17914 } else if (!strcasecmp(v->name, "flash")) {
17915 confp->timing.flashtime = atoi(v->value);
17916 } else if (!strcasecmp(v->name, "start")) {
17917 confp->timing.starttime = atoi(v->value);
17918 } else if (!strcasecmp(v->name, "rxwink")) {
17919 confp->timing.rxwinktime = atoi(v->value);
17920 } else if (!strcasecmp(v->name, "rxflash")) {
17921 confp->timing.rxflashtime = atoi(v->value);
17922 } else if (!strcasecmp(v->name, "debounce")) {
17923 confp->timing.debouncetime = atoi(v->value);
17924 } else if (!strcasecmp(v->name, "toneduration")) {
17925 int toneduration;
17926 int ctlfd;
17927 int res;
17928 struct dahdi_dialparams dps;
17929
17930 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17931 if (ctlfd == -1) {
17932 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17933 return -1;
17934 }
17935
17936 toneduration = atoi(v->value);
17937 if (toneduration > -1) {
17938 memset(&dps, 0, sizeof(dps));
17939
17940 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17941 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17942 if (res < 0) {
17943 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17944 close(ctlfd);
17945 return -1;
17946 }
17947 }
17948 close(ctlfd);
17949 } else if (!strcasecmp(v->name, "defaultcic")) {
17950 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17951 } else if (!strcasecmp(v->name, "defaultozz")) {
17952 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17953 } else if (!strcasecmp(v->name, "mwilevel")) {
17954 mwilevel = atoi(v->value);
17955 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17956 dtmfcid_level = atoi(v->value);
17957 } else if (!strcasecmp(v->name, "reportalarms")) {
17958 if (!strcasecmp(v->value, "all"))
17959 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17960 if (!strcasecmp(v->value, "none"))
17961 report_alarms = 0;
17962 else if (!strcasecmp(v->value, "channels"))
17963 report_alarms = REPORT_CHANNEL_ALARMS;
17964 else if (!strcasecmp(v->value, "spans"))
17965 report_alarms = REPORT_SPAN_ALARMS;
17966 }
17967 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17968 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17969 }
17970
17971
17972 if (confp->chan.vars) {
17973 ast_variables_destroy(confp->chan.vars);
17974 confp->chan.vars = NULL;
17975 }
17976
17977 if (dahdichan) {
17978
17979 if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
17980 &found_pseudo)) {
17981 if (confp->ignore_failed_channels) {
17982 ast_log(LOG_WARNING,
17983 "Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
17984 dahdichan->value);
17985 } else {
17986 return -1;
17987 }
17988 }
17989 }
17990
17991
17992 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17993 if (!tmp->destroy && tmp->span != y) {
17994 tmp->manages_span_alarms = 1;
17995 y = tmp->span;
17996 } else {
17997 tmp->manages_span_alarms = 0;
17998 }
17999 }
18000
18001
18002
18003 if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
18004
18005
18006
18007
18008 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18009
18010 if (conf.chan.cc_params) {
18011 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
18012 } else {
18013 tmp = NULL;
18014 }
18015 if (tmp) {
18016 ast_verb(3, "Automatically generated pseudo channel\n");
18017 } else {
18018 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
18019 }
18020 ast_cc_config_params_destroy(conf.chan.cc_params);
18021 }
18022 return 0;
18023 }
18024
18025
18026
18027
18028
18029
18030
18031
18032
18033
18034
18035 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
18036 {
18037 struct ast_cc_config_params *cc_params;
18038
18039 cc_params = dest->chan.cc_params;
18040 *dest = *src;
18041 dest->chan.cc_params = cc_params;
18042 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
18043 }
18044
18045
18046
18047
18048
18049
18050
18051
18052
18053
18054
18055
18056
18057 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
18058 {
18059 struct ast_config *cfg;
18060 struct ast_config *ucfg;
18061 struct ast_variable *v;
18062 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
18063 const char *chans;
18064 const char *cat;
18065 int res;
18066
18067 #ifdef HAVE_PRI
18068 char *c;
18069 int spanno;
18070 int i;
18071 int logicalspan;
18072 int trunkgroup;
18073 int dchannels[SIG_PRI_NUM_DCHANS];
18074 #endif
18075 int have_cfg_now;
18076 static int had_cfg_before = 1;
18077
18078 cfg = ast_config_load(config, config_flags);
18079 have_cfg_now = !!cfg;
18080 if (!cfg) {
18081
18082 if (had_cfg_before) {
18083 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
18084 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18085 }
18086 cfg = ast_config_new();
18087 if (!cfg) {
18088 return 0;
18089 }
18090 ucfg = ast_config_load("users.conf", config_flags);
18091 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18092 ast_config_destroy(cfg);
18093 return 0;
18094 }
18095 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18096 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18097 ast_config_destroy(cfg);
18098 return 0;
18099 }
18100 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
18101 ucfg = ast_config_load("users.conf", config_flags);
18102 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
18103 return 0;
18104 }
18105 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18106 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18107 return 0;
18108 }
18109 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18110 cfg = ast_config_load(config, config_flags);
18111 have_cfg_now = !!cfg;
18112 if (!cfg) {
18113 if (had_cfg_before) {
18114
18115 ast_log(LOG_ERROR, "Bad. Unable to load config %s\n", config);
18116 ast_config_destroy(ucfg);
18117 return 0;
18118 }
18119 cfg = ast_config_new();
18120 if (!cfg) {
18121 ast_config_destroy(ucfg);
18122 return 0;
18123 }
18124 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18125 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18126 ast_config_destroy(ucfg);
18127 return 0;
18128 }
18129 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
18130 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
18131 return 0;
18132 } else {
18133 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
18134 ucfg = ast_config_load("users.conf", config_flags);
18135 if (ucfg == CONFIG_STATUS_FILEINVALID) {
18136 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
18137 ast_config_destroy(cfg);
18138 return 0;
18139 }
18140 }
18141 had_cfg_before = have_cfg_now;
18142
18143
18144 ast_mutex_lock(&iflock);
18145 #ifdef HAVE_PRI
18146 if (reload != 1) {
18147
18148 v = ast_variable_browse(cfg, "trunkgroups");
18149 while (v) {
18150 if (!strcasecmp(v->name, "trunkgroup")) {
18151 trunkgroup = atoi(v->value);
18152 if (trunkgroup > 0) {
18153 if ((c = strchr(v->value, ','))) {
18154 i = 0;
18155 memset(dchannels, 0, sizeof(dchannels));
18156 while (c && (i < SIG_PRI_NUM_DCHANS)) {
18157 dchannels[i] = atoi(c + 1);
18158 if (dchannels[i] < 0) {
18159 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);
18160 } else
18161 i++;
18162 c = strchr(c + 1, ',');
18163 }
18164 if (i) {
18165 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
18166 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);
18167 } else
18168 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");
18169 } else
18170 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18171 } else
18172 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
18173 } else
18174 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
18175 } else if (!strcasecmp(v->name, "spanmap")) {
18176 spanno = atoi(v->value);
18177 if (spanno > 0) {
18178 if ((c = strchr(v->value, ','))) {
18179 trunkgroup = atoi(c + 1);
18180 if (trunkgroup > 0) {
18181 if ((c = strchr(c + 1, ',')))
18182 logicalspan = atoi(c + 1);
18183 else
18184 logicalspan = 0;
18185 if (logicalspan >= 0) {
18186 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
18187 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18188 } else
18189 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
18190 } else
18191 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);
18192 } else
18193 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
18194 } else
18195 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
18196 } else
18197 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
18198 } else {
18199 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
18200 }
18201 v = v->next;
18202 }
18203 }
18204 #endif
18205
18206
18207 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
18208
18209 mwimonitornotify[0] = '\0';
18210
18211 v = ast_variable_browse(cfg, "channels");
18212 if ((res = process_dahdi(base_conf,
18213 "" ,
18214 v, reload, 0))) {
18215 ast_mutex_unlock(&iflock);
18216 ast_config_destroy(cfg);
18217 if (ucfg) {
18218 ast_config_destroy(ucfg);
18219 }
18220 return res;
18221 }
18222
18223
18224 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
18225
18226
18227
18228 if (!strcasecmp(cat, "general") ||
18229 !strcasecmp(cat, "trunkgroups") ||
18230 !strcasecmp(cat, "globals") ||
18231 !strcasecmp(cat, "channels")) {
18232 continue;
18233 }
18234
18235 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
18236 if (ast_strlen_zero(chans)) {
18237
18238 continue;
18239 }
18240
18241
18242 deep_copy_dahdi_chan_conf(conf, base_conf);
18243
18244 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
18245 ast_mutex_unlock(&iflock);
18246 ast_config_destroy(cfg);
18247 if (ucfg) {
18248 ast_config_destroy(ucfg);
18249 }
18250 return res;
18251 }
18252 }
18253
18254 ast_config_destroy(cfg);
18255
18256 if (ucfg) {
18257
18258 deep_copy_dahdi_chan_conf(base_conf, default_conf);
18259 process_dahdi(base_conf,
18260 "" ,
18261 ast_variable_browse(ucfg, "general"), 1, 0);
18262
18263 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
18264 if (!strcasecmp(cat, "general")) {
18265 continue;
18266 }
18267
18268 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
18269 if (ast_strlen_zero(chans)) {
18270
18271 continue;
18272 }
18273
18274
18275 deep_copy_dahdi_chan_conf(conf, base_conf);
18276
18277 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
18278 ast_config_destroy(ucfg);
18279 ast_mutex_unlock(&iflock);
18280 return res;
18281 }
18282 }
18283 ast_config_destroy(ucfg);
18284 }
18285 ast_mutex_unlock(&iflock);
18286
18287 #ifdef HAVE_PRI
18288 if (reload != 1) {
18289 int x;
18290 for (x = 0; x < NUM_SPANS; x++) {
18291 if (pris[x].pri.pvts[0]) {
18292 prepare_pri(pris + x);
18293 if (sig_pri_start_pri(&pris[x].pri)) {
18294 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
18295 return -1;
18296 } else
18297 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
18298 }
18299 }
18300 }
18301 #endif
18302 #if defined(HAVE_SS7)
18303 if (reload != 1) {
18304 int x;
18305 for (x = 0; x < NUM_SPANS; x++) {
18306 if (linksets[x].ss7.ss7) {
18307 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
18308 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
18309 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
18310 return -1;
18311 } else
18312 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
18313 }
18314 }
18315 }
18316 #endif
18317 #ifdef HAVE_OPENR2
18318 if (reload != 1) {
18319 int x;
18320 for (x = 0; x < r2links_count; x++) {
18321 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
18322 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
18323 return -1;
18324 } else {
18325 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
18326 }
18327 }
18328 }
18329 #endif
18330
18331 restart_monitor();
18332 return 0;
18333 }
18334
18335
18336
18337
18338
18339
18340
18341
18342
18343
18344 static int setup_dahdi(int reload)
18345 {
18346 int res;
18347 struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
18348 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
18349 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
18350
18351 if (default_conf.chan.cc_params && base_conf.chan.cc_params && conf.chan.cc_params) {
18352 res = setup_dahdi_int(reload, &default_conf, &base_conf, &conf);
18353 } else {
18354 res = -1;
18355 }
18356 ast_cc_config_params_destroy(default_conf.chan.cc_params);
18357 ast_cc_config_params_destroy(base_conf.chan.cc_params);
18358 ast_cc_config_params_destroy(conf.chan.cc_params);
18359
18360 return res;
18361 }
18362
18363
18364
18365
18366
18367
18368
18369
18370 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
18371 struct ast_data *data_root)
18372 {
18373 int ctl, res, span;
18374 struct ast_data *data_span, *data_alarms;
18375 struct dahdi_spaninfo s;
18376
18377 ctl = open("/dev/dahdi/ctl", O_RDWR);
18378 if (ctl < 0) {
18379 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
18380 return -1;
18381 }
18382 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
18383 s.spanno = span;
18384 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
18385 if (res) {
18386 continue;
18387 }
18388
18389 data_span = ast_data_add_node(data_root, "span");
18390 if (!data_span) {
18391 continue;
18392 }
18393 ast_data_add_str(data_span, "description", s.desc);
18394
18395
18396 data_alarms = ast_data_add_node(data_span, "alarms");
18397 if (!data_alarms) {
18398 continue;
18399 }
18400
18401 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
18402 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
18403 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
18404 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
18405 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
18406 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
18407
18408 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
18409 ast_data_add_int(data_span, "bpviol", s.bpvcount);
18410 ast_data_add_int(data_span, "crc4", s.crc4count);
18411 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
18412 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
18413 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
18414 "CAS");
18415 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
18416 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
18417 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
18418 "Unknown");
18419 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
18420 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
18421 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
18422 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
18423
18424
18425 if (!ast_data_search_match(search, data_span)) {
18426 ast_data_remove_node(data_root, data_span);
18427 }
18428 }
18429 close(ctl);
18430
18431 return 0;
18432 }
18433
18434
18435
18436
18437
18438
18439
18440
18441 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
18442 struct ast_data *data_root)
18443 {
18444 struct dahdi_pvt *tmp;
18445 struct ast_data *data_channel;
18446
18447 ast_mutex_lock(&iflock);
18448 for (tmp = iflist; tmp; tmp = tmp->next) {
18449 data_channel = ast_data_add_node(data_root, "channel");
18450 if (!data_channel) {
18451 continue;
18452 }
18453
18454 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
18455
18456
18457 if (!ast_data_search_match(search, data_channel)) {
18458 ast_data_remove_node(data_root, data_channel);
18459 }
18460 }
18461 ast_mutex_unlock(&iflock);
18462
18463 return 0;
18464 }
18465
18466
18467
18468
18469
18470
18471
18472
18473 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
18474 struct ast_data *data_root)
18475 {
18476 int pseudo_fd = -1;
18477 struct dahdi_versioninfo vi = {
18478 .version = "Unknown",
18479 .echo_canceller = "Unknown"
18480 };
18481
18482 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
18483 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
18484 return -1;
18485 }
18486
18487 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
18488 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
18489 }
18490
18491 close(pseudo_fd);
18492
18493 ast_data_add_str(data_root, "value", vi.version);
18494 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
18495
18496 return 0;
18497 }
18498
18499 static const struct ast_data_handler dahdi_status_data_provider = {
18500 .version = AST_DATA_HANDLER_VERSION,
18501 .get = dahdi_status_data_provider_get
18502 };
18503
18504 static const struct ast_data_handler dahdi_channels_data_provider = {
18505 .version = AST_DATA_HANDLER_VERSION,
18506 .get = dahdi_channels_data_provider_get
18507 };
18508
18509 static const struct ast_data_handler dahdi_version_data_provider = {
18510 .version = AST_DATA_HANDLER_VERSION,
18511 .get = dahdi_version_data_provider_get
18512 };
18513
18514 static const struct ast_data_entry dahdi_data_providers[] = {
18515 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
18516 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
18517 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
18518 };
18519
18520 static int load_module(void)
18521 {
18522 int res;
18523 #if defined(HAVE_PRI) || defined(HAVE_SS7)
18524 int y;
18525 #endif
18526
18527 #ifdef HAVE_PRI
18528 memset(pris, 0, sizeof(pris));
18529 for (y = 0; y < NUM_SPANS; y++) {
18530 sig_pri_init_pri(&pris[y].pri);
18531 }
18532 pri_set_error(dahdi_pri_error);
18533 pri_set_message(dahdi_pri_message);
18534 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
18535 #ifdef HAVE_PRI_PROG_W_CAUSE
18536 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
18537 #endif
18538 #if defined(HAVE_PRI_CCSS)
18539 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
18540 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
18541 __unload_module();
18542 return AST_MODULE_LOAD_FAILURE;
18543 }
18544 #endif
18545 if (sig_pri_load(
18546 #if defined(HAVE_PRI_CCSS)
18547 dahdi_pri_cc_type
18548 #else
18549 NULL
18550 #endif
18551 )) {
18552 __unload_module();
18553 return AST_MODULE_LOAD_FAILURE;
18554 }
18555 #endif
18556 #if defined(HAVE_SS7)
18557 memset(linksets, 0, sizeof(linksets));
18558 for (y = 0; y < NUM_SPANS; y++) {
18559 sig_ss7_init_linkset(&linksets[y].ss7);
18560 }
18561 ss7_set_error(dahdi_ss7_error);
18562 ss7_set_message(dahdi_ss7_message);
18563 #endif
18564 res = setup_dahdi(0);
18565
18566 if (res)
18567 return AST_MODULE_LOAD_DECLINE;
18568 if (ast_channel_register(&dahdi_tech)) {
18569 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18570 __unload_module();
18571 return AST_MODULE_LOAD_FAILURE;
18572 }
18573 #ifdef HAVE_PRI
18574 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18575 #endif
18576 #if defined(HAVE_SS7)
18577 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18578 #endif
18579 #ifdef HAVE_OPENR2
18580 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18581 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18582 #endif
18583
18584 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18585
18586 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18587 memset(round_robin, 0, sizeof(round_robin));
18588 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18589 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18590 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18591 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18592 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18593 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18594 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18595
18596 ast_cond_init(&ss_thread_complete, NULL);
18597
18598 return res;
18599 }
18600
18601 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18602 {
18603 #define END_SILENCE_LEN 400
18604 #define HEADER_MS 50
18605 #define TRAILER_MS 5
18606 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18607 #define ASCII_BYTES_PER_CHAR 80
18608
18609 unsigned char *buf,*mybuf;
18610 struct dahdi_pvt *p = c->tech_pvt;
18611 struct pollfd fds[1];
18612 int size,res,fd,len,x;
18613 int bytes=0;
18614
18615 float cr = 1.0;
18616 float ci = 0.0;
18617 float scont = 0.0;
18618 int idx;
18619
18620 idx = dahdi_get_index(c, p, 0);
18621 if (idx < 0) {
18622 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18623 return -1;
18624 }
18625 if (!text[0]) return(0);
18626 if ((!p->tdd) && (!p->mate)) return(0);
18627 if (p->mate)
18628 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18629 else
18630 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18631 if (!buf)
18632 return -1;
18633 mybuf = buf;
18634 if (p->mate) {
18635 int codec = AST_LAW(p);
18636 for (x = 0; x < HEADER_MS; x++) {
18637 PUT_CLID_MARKMS;
18638 }
18639
18640 for (x = 0; text[x]; x++) {
18641 PUT_CLID(text[x]);
18642 }
18643 for (x = 0; x < TRAILER_MS; x++) {
18644 PUT_CLID_MARKMS;
18645 }
18646 len = bytes;
18647 buf = mybuf;
18648 } else {
18649 len = tdd_generate(p->tdd, buf, text);
18650 if (len < 1) {
18651 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18652 ast_free(mybuf);
18653 return -1;
18654 }
18655 }
18656 memset(buf + len, 0x7f, END_SILENCE_LEN);
18657 len += END_SILENCE_LEN;
18658 fd = p->subs[idx].dfd;
18659 while (len) {
18660 if (ast_check_hangup(c)) {
18661 ast_free(mybuf);
18662 return -1;
18663 }
18664 size = len;
18665 if (size > READ_SIZE)
18666 size = READ_SIZE;
18667 fds[0].fd = fd;
18668 fds[0].events = POLLOUT | POLLPRI;
18669 fds[0].revents = 0;
18670 res = poll(fds, 1, -1);
18671 if (!res) {
18672 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18673 continue;
18674 }
18675
18676 if (fds[0].revents & POLLPRI) {
18677 ast_free(mybuf);
18678 return -1;
18679 }
18680 if (!(fds[0].revents & POLLOUT)) {
18681 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18682 continue;
18683 }
18684 res = write(fd, buf, size);
18685 if (res != size) {
18686 if (res == -1) {
18687 ast_free(mybuf);
18688 return -1;
18689 }
18690 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18691 break;
18692 }
18693 len -= size;
18694 buf += size;
18695 }
18696 ast_free(mybuf);
18697 return(0);
18698 }
18699
18700
18701 static int reload(void)
18702 {
18703 int res = 0;
18704
18705 res = setup_dahdi(1);
18706 if (res) {
18707 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18708 return -1;
18709 }
18710 return 0;
18711 }
18712
18713
18714
18715
18716
18717 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18718 .load = load_module,
18719 .unload = unload_module,
18720 .reload = reload,
18721 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18722 .nonoptreq = "res_smdi",
18723 );