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 #include "asterisk.h"
00050
00051 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 301134 $")
00052
00053 #if defined(__NetBSD__) || defined(__FreeBSD__)
00054 #include <pthread.h>
00055 #include <signal.h>
00056 #else
00057 #include <sys/signal.h>
00058 #endif
00059 #include <sys/ioctl.h>
00060 #include <sys/stat.h>
00061 #include <math.h>
00062 #include <ctype.h>
00063
00064 #include <dahdi/user.h>
00065 #include <dahdi/tonezone.h>
00066 #include "sig_analog.h"
00067
00068
00069
00070
00071
00072
00073 #ifdef HAVE_PRI
00074 #include "sig_pri.h"
00075 #endif
00076
00077 #if defined(HAVE_SS7)
00078 #include "sig_ss7.h"
00079 #endif
00080
00081 #ifdef HAVE_OPENR2
00082
00083 #define SIG_MFCR2_MAX_CHANNELS 672
00084 #include <openr2.h>
00085 #endif
00086
00087 #include "asterisk/lock.h"
00088 #include "asterisk/channel.h"
00089 #include "asterisk/config.h"
00090 #include "asterisk/module.h"
00091 #include "asterisk/pbx.h"
00092 #include "asterisk/file.h"
00093 #include "asterisk/ulaw.h"
00094 #include "asterisk/alaw.h"
00095 #include "asterisk/callerid.h"
00096 #include "asterisk/adsi.h"
00097 #include "asterisk/cli.h"
00098 #include "asterisk/cdr.h"
00099 #include "asterisk/cel.h"
00100 #include "asterisk/features.h"
00101 #include "asterisk/musiconhold.h"
00102 #include "asterisk/say.h"
00103 #include "asterisk/tdd.h"
00104 #include "asterisk/app.h"
00105 #include "asterisk/dsp.h"
00106 #include "asterisk/astdb.h"
00107 #include "asterisk/manager.h"
00108 #include "asterisk/causes.h"
00109 #include "asterisk/term.h"
00110 #include "asterisk/utils.h"
00111 #include "asterisk/transcap.h"
00112 #include "asterisk/stringfields.h"
00113 #include "asterisk/abstract_jb.h"
00114 #include "asterisk/smdi.h"
00115 #include "asterisk/astobj.h"
00116 #include "asterisk/event.h"
00117 #include "asterisk/devicestate.h"
00118 #include "asterisk/paths.h"
00119 #include "asterisk/ccss.h"
00120 #include "asterisk/data.h"
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 #define SMDI_MD_WAIT_TIMEOUT 1500
00255
00256 static const char * const lbostr[] = {
00257 "0 db (CSU)/0-133 feet (DSX-1)",
00258 "133-266 feet (DSX-1)",
00259 "266-399 feet (DSX-1)",
00260 "399-533 feet (DSX-1)",
00261 "533-655 feet (DSX-1)",
00262 "-7.5db (CSU)",
00263 "-15db (CSU)",
00264 "-22.5db (CSU)"
00265 };
00266
00267
00268 static struct ast_jb_conf default_jbconf =
00269 {
00270 .flags = 0,
00271 .max_size = -1,
00272 .resync_threshold = -1,
00273 .impl = "",
00274 .target_extra = -1,
00275 };
00276 static struct ast_jb_conf global_jbconf;
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 #define DEFAULT_CIDRINGS 1
00291
00292 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
00293
00294
00295
00296 #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))
00297
00298 static const char tdesc[] = "DAHDI Telephony Driver"
00299 #if defined(HAVE_PRI) || defined(HAVE_SS7) || defined(HAVE_OPENR2)
00300 " w/"
00301 #if defined(HAVE_PRI)
00302 "PRI"
00303 #endif
00304 #if defined(HAVE_SS7)
00305 #if defined(HAVE_PRI)
00306 " & "
00307 #endif
00308 "SS7"
00309 #endif
00310 #if defined(HAVE_OPENR2)
00311 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00312 " & "
00313 #endif
00314 "MFC/R2"
00315 #endif
00316 #endif
00317 ;
00318
00319 static const char config[] = "chan_dahdi.conf";
00320
00321 #define SIG_EM DAHDI_SIG_EM
00322 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
00323 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
00324 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
00325 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
00326 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
00327 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
00328 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
00329 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
00330 #define SIG_FXSLS DAHDI_SIG_FXSLS
00331 #define SIG_FXSGS DAHDI_SIG_FXSGS
00332 #define SIG_FXSKS DAHDI_SIG_FXSKS
00333 #define SIG_FXOLS DAHDI_SIG_FXOLS
00334 #define SIG_FXOGS DAHDI_SIG_FXOGS
00335 #define SIG_FXOKS DAHDI_SIG_FXOKS
00336 #define SIG_PRI DAHDI_SIG_CLEAR
00337 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
00338 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
00339 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
00340 #define SIG_MFCR2 DAHDI_SIG_CAS
00341 #define SIG_SF DAHDI_SIG_SF
00342 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
00343 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
00344 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
00345 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
00346 #define SIG_EM_E1 DAHDI_SIG_EM_E1
00347
00348 #ifdef LOTS_OF_SPANS
00349 #define NUM_SPANS DAHDI_MAX_SPANS
00350 #else
00351 #define NUM_SPANS 32
00352 #endif
00353
00354 #define CHAN_PSEUDO -2
00355
00356 #define CALLPROGRESS_PROGRESS 1
00357 #define CALLPROGRESS_FAX_OUTGOING 2
00358 #define CALLPROGRESS_FAX_INCOMING 4
00359 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
00360
00361 #define NUM_CADENCE_MAX 25
00362 static int num_cadence = 4;
00363 static int user_has_defined_cadences = 0;
00364
00365 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
00366 { { 125, 125, 2000, 4000 } },
00367 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } },
00368 { { 125, 125, 125, 125, 125, 4000 } },
00369 { { 1000, 500, 2500, 5000 } },
00370 };
00371
00372
00373
00374
00375
00376 static int cidrings[NUM_CADENCE_MAX] = {
00377 2,
00378 4,
00379 3,
00380 2,
00381 };
00382
00383
00384 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
00385
00386 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
00387 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
00388
00389 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00390 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) )
00391
00392 static char defaultcic[64] = "";
00393 static char defaultozz[64] = "";
00394
00395 static char parkinglot[AST_MAX_EXTENSION] = "";
00396
00397
00398 static char mwimonitornotify[PATH_MAX] = "";
00399 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
00400 static int mwisend_rpas = 0;
00401 #endif
00402
00403 static char progzone[10] = "";
00404
00405 static int usedistinctiveringdetection = 0;
00406 static int distinctiveringaftercid = 0;
00407
00408 static int numbufs = 4;
00409
00410 static int mwilevel = 512;
00411 static int dtmfcid_level = 256;
00412
00413 #define REPORT_CHANNEL_ALARMS 1
00414 #define REPORT_SPAN_ALARMS 2
00415 static int report_alarms = REPORT_CHANNEL_ALARMS;
00416
00417 #ifdef HAVE_PRI
00418 static int pridebugfd = -1;
00419 static char pridebugfilename[1024] = "";
00420 #endif
00421
00422
00423 static int firstdigittimeout = 16000;
00424
00425
00426 static int gendigittimeout = 8000;
00427
00428
00429 static int matchdigittimeout = 3000;
00430
00431
00432 AST_MUTEX_DEFINE_STATIC(iflock);
00433
00434
00435 static int ifcount = 0;
00436
00437 #ifdef HAVE_PRI
00438 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
00439 #endif
00440
00441
00442
00443 AST_MUTEX_DEFINE_STATIC(monlock);
00444
00445
00446
00447 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00448 static ast_cond_t ss_thread_complete;
00449 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
00450 AST_MUTEX_DEFINE_STATIC(restart_lock);
00451 static int ss_thread_count = 0;
00452 static int num_restart_pending = 0;
00453
00454 static int restart_monitor(void);
00455
00456 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);
00457
00458 static int dahdi_sendtext(struct ast_channel *c, const char *text);
00459
00460 static void mwi_event_cb(const struct ast_event *event, void *userdata)
00461 {
00462
00463
00464
00465
00466 }
00467
00468
00469 static inline int dahdi_get_event(int fd)
00470 {
00471 int j;
00472 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00473 return -1;
00474 return j;
00475 }
00476
00477
00478 static inline int dahdi_wait_event(int fd)
00479 {
00480 int i, j = 0;
00481 i = DAHDI_IOMUX_SIGEVENT;
00482 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00483 return -1;
00484 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00485 return -1;
00486 return j;
00487 }
00488
00489
00490 #define READ_SIZE 160
00491
00492 #define MASK_AVAIL (1 << 0)
00493 #define MASK_INUSE (1 << 1)
00494
00495 #define CALLWAITING_SILENT_SAMPLES ((300 * 8) / READ_SIZE)
00496 #define CALLWAITING_REPEAT_SAMPLES ((10000 * 8) / READ_SIZE)
00497 #define CALLWAITING_SUPPRESS_SAMPLES ((100 * 8) / READ_SIZE)
00498 #define CIDCW_EXPIRE_SAMPLES ((500 * 8) / READ_SIZE)
00499 #define MIN_MS_SINCE_FLASH ((2000) )
00500 #define DEFAULT_RINGT ((8000 * 8) / READ_SIZE)
00501
00502 struct dahdi_pvt;
00503
00504
00505
00506
00507
00508 static int ringt_base = DEFAULT_RINGT;
00509
00510 #if defined(HAVE_SS7)
00511
00512 struct dahdi_ss7 {
00513 struct sig_ss7_linkset ss7;
00514 };
00515
00516 static struct dahdi_ss7 linksets[NUM_SPANS];
00517
00518 static int cur_ss7type = -1;
00519 static int cur_linkset = -1;
00520 static int cur_pointcode = -1;
00521 static int cur_cicbeginswith = -1;
00522 static int cur_adjpointcode = -1;
00523 static int cur_networkindicator = -1;
00524 static int cur_defaultdpc = -1;
00525 #endif
00526
00527 #ifdef HAVE_OPENR2
00528 struct dahdi_mfcr2 {
00529 pthread_t r2master;
00530 openr2_context_t *protocol_context;
00531 struct dahdi_pvt *pvts[SIG_MFCR2_MAX_CHANNELS];
00532 int numchans;
00533 int monitored_count;
00534 };
00535
00536 struct dahdi_mfcr2_conf {
00537 openr2_variant_t variant;
00538 int mfback_timeout;
00539 int metering_pulse_timeout;
00540 int max_ani;
00541 int max_dnis;
00542 signed int get_ani_first:2;
00543 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
00544 signed int skip_category_request:2;
00545 #endif
00546 unsigned int call_files:1;
00547 unsigned int allow_collect_calls:1;
00548 unsigned int charge_calls:1;
00549 unsigned int accept_on_offer:1;
00550 unsigned int forced_release:1;
00551 unsigned int double_answer:1;
00552 signed int immediate_accept:2;
00553 char logdir[OR2_MAX_PATH];
00554 char r2proto_file[OR2_MAX_PATH];
00555 openr2_log_level_t loglevel;
00556 openr2_calling_party_category_t category;
00557 };
00558
00559
00560 static struct dahdi_mfcr2 **r2links;
00561
00562 static int r2links_count = 0;
00563
00564 #endif
00565
00566 #ifdef HAVE_PRI
00567
00568 struct dahdi_pri {
00569 int dchannels[SIG_PRI_NUM_DCHANS];
00570 int mastertrunkgroup;
00571 int prilogicalspan;
00572 struct sig_pri_span pri;
00573 };
00574
00575 static struct dahdi_pri pris[NUM_SPANS];
00576
00577 #if defined(HAVE_PRI_CCSS)
00578
00579 static const char dahdi_pri_cc_type[] = "DAHDI/PRI";
00580 #endif
00581
00582 #else
00583
00584 struct dahdi_pri;
00585 #endif
00586
00587 #define SUB_REAL 0
00588 #define SUB_CALLWAIT 1
00589 #define SUB_THREEWAY 2
00590
00591
00592 #define POLARITY_IDLE 0
00593 #define POLARITY_REV 1
00594
00595
00596 struct distRingData {
00597 int ring[3];
00598 int range;
00599 };
00600 struct ringContextData {
00601 char contextData[AST_MAX_CONTEXT];
00602 };
00603 struct dahdi_distRings {
00604 struct distRingData ringnum[3];
00605 struct ringContextData ringContext[3];
00606 };
00607
00608 static const char * const subnames[] = {
00609 "Real",
00610 "Callwait",
00611 "Threeway"
00612 };
00613
00614 struct dahdi_subchannel {
00615 int dfd;
00616 struct ast_channel *owner;
00617 int chan;
00618 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
00619 struct ast_frame f;
00620 unsigned int needringing:1;
00621 unsigned int needbusy:1;
00622 unsigned int needcongestion:1;
00623 unsigned int needanswer:1;
00624 unsigned int needflash:1;
00625 unsigned int needhold:1;
00626 unsigned int needunhold:1;
00627 unsigned int linear:1;
00628 unsigned int inthreeway:1;
00629 struct dahdi_confinfo curconf;
00630 };
00631
00632 #define CONF_USER_REAL (1 << 0)
00633 #define CONF_USER_THIRDCALL (1 << 1)
00634
00635 #define MAX_SLAVES 4
00636
00637
00638
00639
00640 typedef enum {
00641 MWI_SEND_NULL = 0,
00642 MWI_SEND_SA,
00643 MWI_SEND_SA_WAIT,
00644 MWI_SEND_PAUSE,
00645 MWI_SEND_SPILL,
00646 MWI_SEND_CLEANUP,
00647 MWI_SEND_DONE,
00648 } mwisend_states;
00649
00650 struct mwisend_info {
00651 struct timeval pause;
00652 mwisend_states mwisend_current;
00653 };
00654
00655
00656 enum DAHDI_IFLIST {
00657 DAHDI_IFLIST_NONE,
00658 DAHDI_IFLIST_MAIN,
00659 #if defined(HAVE_PRI)
00660 DAHDI_IFLIST_NO_B_CHAN,
00661 #endif
00662 };
00663
00664 struct dahdi_pvt {
00665 ast_mutex_t lock;
00666 struct callerid_state *cs;
00667 struct ast_channel *owner;
00668
00669
00670 struct dahdi_subchannel sub_unused;
00671 struct dahdi_subchannel subs[3];
00672 struct dahdi_confinfo saveconf;
00673
00674 struct dahdi_pvt *slaves[MAX_SLAVES];
00675 struct dahdi_pvt *master;
00676 int inconference;
00677
00678 int bufsize;
00679 int buf_no;
00680 int buf_policy;
00681 int faxbuf_no;
00682 int faxbuf_policy;
00683 int sig;
00684
00685
00686
00687
00688 int radio;
00689 int outsigmod;
00690 int oprmode;
00691 struct dahdi_pvt *oprpeer;
00692
00693 float cid_rxgain;
00694
00695 float rxgain;
00696
00697 float txgain;
00698
00699 float txdrc;
00700 float rxdrc;
00701
00702 int tonezone;
00703 enum DAHDI_IFLIST which_iflist;
00704 struct dahdi_pvt *next;
00705 struct dahdi_pvt *prev;
00706
00707
00708
00709
00710
00711
00712
00713 unsigned int adsi:1;
00714
00715
00716
00717
00718
00719 unsigned int answeronpolarityswitch:1;
00720
00721
00722
00723
00724
00725 unsigned int busydetect:1;
00726
00727
00728
00729
00730
00731 unsigned int callreturn:1;
00732
00733
00734
00735
00736
00737
00738 unsigned int callwaiting:1;
00739
00740
00741
00742
00743 unsigned int callwaitingcallerid:1;
00744
00745
00746
00747
00748
00749
00750 unsigned int cancallforward:1;
00751
00752
00753
00754
00755 unsigned int canpark:1;
00756
00757 unsigned int confirmanswer:1;
00758
00759
00760
00761
00762 unsigned int destroy:1;
00763 unsigned int didtdd:1;
00764
00765 unsigned int dialednone:1;
00766
00767
00768
00769
00770 unsigned int dialing:1;
00771
00772 unsigned int digital:1;
00773
00774 unsigned int dnd:1;
00775
00776 unsigned int echobreak:1;
00777
00778
00779
00780
00781
00782 unsigned int echocanbridged:1;
00783
00784 unsigned int echocanon:1;
00785
00786 unsigned int faxhandled:1;
00787
00788 unsigned int usefaxbuffers:1;
00789
00790 unsigned int bufferoverrideinuse:1;
00791
00792 unsigned int firstradio:1;
00793
00794
00795
00796
00797 unsigned int hanguponpolarityswitch:1;
00798
00799 unsigned int hardwaredtmf:1;
00800
00801
00802
00803
00804
00805
00806 unsigned int hidecallerid:1;
00807
00808
00809
00810
00811
00812 unsigned int hidecalleridname:1;
00813
00814 unsigned int ignoredtmf:1;
00815
00816
00817
00818
00819
00820 unsigned int immediate:1;
00821
00822 unsigned int inalarm:1;
00823
00824 unsigned int mate:1;
00825
00826 unsigned int outgoing:1;
00827
00828
00829
00830
00831
00832
00833 unsigned int permcallwaiting:1;
00834
00835
00836
00837
00838 unsigned int permhidecallerid:1;
00839
00840
00841
00842
00843 unsigned int priindication_oob:1;
00844
00845
00846
00847
00848 unsigned int priexclusive:1;
00849
00850
00851
00852
00853 unsigned int pulse:1;
00854
00855 unsigned int pulsedial:1;
00856 unsigned int restartpending:1;
00857
00858
00859
00860
00861
00862 unsigned int restrictcid:1;
00863
00864
00865
00866
00867 unsigned int threewaycalling:1;
00868
00869
00870
00871
00872
00873
00874
00875
00876 unsigned int transfer:1;
00877
00878
00879
00880
00881
00882
00883
00884 unsigned int use_callerid:1;
00885
00886
00887
00888
00889
00890
00891 unsigned int use_callingpres:1;
00892
00893
00894
00895
00896
00897 unsigned int usedistinctiveringdetection:1;
00898
00899
00900
00901
00902 unsigned int dahditrcallerid:1;
00903
00904
00905
00906
00907 unsigned int transfertobusy:1;
00908
00909
00910
00911
00912 unsigned int mwimonitor_neon:1;
00913
00914
00915
00916
00917 unsigned int mwimonitor_fsk:1;
00918
00919
00920
00921
00922
00923 unsigned int mwimonitor_rpas:1;
00924
00925 unsigned int mwimonitoractive:1;
00926
00927 unsigned int mwisendactive:1;
00928
00929
00930
00931
00932 unsigned int inservice:1;
00933
00934
00935
00936
00937 unsigned int locallyblocked:1;
00938
00939
00940
00941
00942 unsigned int remotelyblocked:1;
00943
00944
00945
00946
00947 unsigned int manages_span_alarms:1;
00948
00949 #if defined(HAVE_PRI)
00950 struct sig_pri_span *pri;
00951 int logicalspan;
00952 #endif
00953
00954
00955
00956
00957 unsigned int use_smdi:1;
00958 struct mwisend_info mwisend_data;
00959
00960 struct ast_smdi_interface *smdi_iface;
00961
00962
00963 struct dahdi_distRings drings;
00964
00965
00966
00967
00968
00969 char context[AST_MAX_CONTEXT];
00970
00971
00972
00973 char defcontext[AST_MAX_CONTEXT];
00974
00975 char exten[AST_MAX_EXTENSION];
00976
00977
00978
00979
00980 char language[MAX_LANGUAGE];
00981
00982
00983
00984
00985 char mohinterpret[MAX_MUSICCLASS];
00986
00987
00988
00989
00990 char mohsuggest[MAX_MUSICCLASS];
00991 char parkinglot[AST_MAX_EXTENSION];
00992 #if defined(HAVE_PRI) || defined(HAVE_SS7)
00993
00994 char cid_ani[AST_MAX_EXTENSION];
00995 #endif
00996
00997 int cid_ani2;
00998
00999 char cid_num[AST_MAX_EXTENSION];
01000
01001
01002
01003
01004 char cid_tag[AST_MAX_EXTENSION];
01005
01006 int cid_ton;
01007
01008 char cid_name[AST_MAX_EXTENSION];
01009
01010 char cid_subaddr[AST_MAX_EXTENSION];
01011 char *origcid_num;
01012 char *origcid_name;
01013
01014 char callwait_num[AST_MAX_EXTENSION];
01015
01016 char callwait_name[AST_MAX_EXTENSION];
01017
01018 char rdnis[AST_MAX_EXTENSION];
01019
01020 char dnid[AST_MAX_EXTENSION];
01021
01022
01023
01024
01025 ast_group_t group;
01026
01027 int law_default;
01028
01029 int law;
01030 int confno;
01031 int confusers;
01032 int propconfno;
01033
01034
01035
01036
01037 ast_group_t callgroup;
01038
01039
01040
01041
01042 ast_group_t pickupgroup;
01043
01044
01045
01046
01047 struct ast_variable *vars;
01048 int channel;
01049 int span;
01050 time_t guardtime;
01051 int cid_signalling;
01052 int cid_start;
01053 int dtmfcid_holdoff_state;
01054 struct timeval dtmfcid_delay;
01055 int callingpres;
01056 int callwaitingrepeat;
01057 int cidcwexpire;
01058 int cid_suppress_expire;
01059
01060 unsigned char *cidspill;
01061
01062 int cidpos;
01063
01064 int cidlen;
01065
01066 int ringt;
01067
01068
01069
01070
01071 int ringt_base;
01072
01073
01074
01075
01076
01077
01078 int stripmsd;
01079
01080
01081
01082
01083
01084
01085 int callwaitcas;
01086
01087 int callwaitrings;
01088
01089 struct {
01090 struct dahdi_echocanparams head;
01091 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
01092 } echocancel;
01093
01094
01095
01096
01097 int echotraining;
01098
01099 char echorest[20];
01100
01101
01102
01103
01104 int busycount;
01105
01106
01107
01108
01109 int busycompare;
01110
01111
01112
01113
01114 int busytonelength;
01115
01116
01117
01118
01119 int busyquietlength;
01120
01121
01122
01123
01124 int busyfuzziness;
01125
01126
01127
01128
01129 int silencethreshold;
01130
01131
01132
01133
01134 int callprogress;
01135
01136
01137
01138
01139 int waitfordialtone;
01140 struct timeval waitingfordt;
01141 struct timeval flashtime;
01142
01143 struct ast_dsp *dsp;
01144
01145 struct dahdi_dialoperation dop;
01146 int whichwink;
01147
01148 char finaldial[64];
01149 char accountcode[AST_MAX_ACCOUNT_CODE];
01150 int amaflags;
01151 struct tdd_state *tdd;
01152
01153 char call_forward[AST_MAX_EXTENSION];
01154
01155
01156
01157
01158 char mailbox[AST_MAX_EXTENSION];
01159
01160 struct ast_event_sub *mwi_event_sub;
01161
01162 char dialdest[256];
01163 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01164 struct dahdi_vmwi_info mwisend_setting;
01165 unsigned int mwisend_fsk: 1;
01166 unsigned int mwisend_rpas:1;
01167 #endif
01168 int distinctivering;
01169 int dtmfrelax;
01170
01171 int fake_event;
01172
01173
01174
01175
01176 int polarityonanswerdelay;
01177
01178 struct timeval polaritydelaytv;
01179
01180
01181
01182
01183 int sendcalleridafter;
01184
01185 int polarity;
01186
01187 int dsp_features;
01188 #if defined(HAVE_SS7)
01189
01190 struct sig_ss7_linkset *ss7;
01191 #endif
01192 #ifdef HAVE_OPENR2
01193 struct dahdi_mfcr2 *mfcr2;
01194 openr2_chan_t *r2chan;
01195 openr2_calling_party_category_t mfcr2_recvd_category;
01196 openr2_calling_party_category_t mfcr2_category;
01197 int mfcr2_dnis_index;
01198 int mfcr2_ani_index;
01199 int mfcr2call:1;
01200 int mfcr2_answer_pending:1;
01201 int mfcr2_charge_calls:1;
01202 int mfcr2_allow_collect_calls:1;
01203 int mfcr2_forced_release:1;
01204 int mfcr2_dnis_matched:1;
01205 int mfcr2_call_accepted:1;
01206 int mfcr2_progress:1;
01207 int mfcr2_accept_on_offer:1;
01208 #endif
01209
01210 char begindigit;
01211
01212 int muting;
01213 void *sig_pvt;
01214 struct ast_cc_config_params *cc_params;
01215
01216
01217
01218
01219
01220
01221 char dialstring[AST_CHANNEL_NAME];
01222 };
01223
01224 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01225 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01226 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01227 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01228 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01229 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01230 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01231 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01232 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01233 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01234 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01235 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01236 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01237 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01238 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01239 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01240 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01241 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01242 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01271 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01272 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01273 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01274 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01275 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01276 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01277 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01278 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01279 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01280 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01281 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01282 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01283 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01284 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01285 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01286 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01287 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01288 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01289 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01290 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01291 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01292
01293 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01294
01295 static struct dahdi_pvt *iflist = NULL;
01296 static struct dahdi_pvt *ifend = NULL;
01297
01298 #if defined(HAVE_PRI)
01299 static struct dahdi_parms_pseudo {
01300 int buf_no;
01301 int buf_policy;
01302 int faxbuf_no;
01303 int faxbuf_policy;
01304 } dahdi_pseudo_parms;
01305 #endif
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 struct dahdi_chan_conf {
01318 struct dahdi_pvt chan;
01319 #ifdef HAVE_PRI
01320 struct dahdi_pri pri;
01321 #endif
01322
01323 #if defined(HAVE_SS7)
01324 struct dahdi_ss7 ss7;
01325 #endif
01326
01327 #ifdef HAVE_OPENR2
01328 struct dahdi_mfcr2_conf mfcr2;
01329 #endif
01330 struct dahdi_params timing;
01331 int is_sig_auto;
01332
01333 int ignore_failed_channels;
01334
01335
01336
01337
01338
01339 char smdi_port[SMDI_MAX_FILENAME_LEN];
01340 };
01341
01342
01343 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01344 {
01345
01346
01347
01348 struct dahdi_chan_conf conf = {
01349 #ifdef HAVE_PRI
01350 .pri.pri = {
01351 .nsf = PRI_NSF_NONE,
01352 .switchtype = PRI_SWITCH_NI2,
01353 .dialplan = PRI_UNKNOWN + 1,
01354 .localdialplan = PRI_NATIONAL_ISDN + 1,
01355 .nodetype = PRI_CPE,
01356 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01357
01358 #if defined(HAVE_PRI_CCSS)
01359 .cc_ptmp_recall_mode = 1,
01360 .cc_qsig_signaling_link_req = 1,
01361 .cc_qsig_signaling_link_rsp = 1,
01362 #endif
01363
01364 .minunused = 2,
01365 .idleext = "",
01366 .idledial = "",
01367 .internationalprefix = "",
01368 .nationalprefix = "",
01369 .localprefix = "",
01370 .privateprefix = "",
01371 .unknownprefix = "",
01372 .resetinterval = -1,
01373 },
01374 #endif
01375 #if defined(HAVE_SS7)
01376 .ss7.ss7 = {
01377 .called_nai = SS7_NAI_NATIONAL,
01378 .calling_nai = SS7_NAI_NATIONAL,
01379 .internationalprefix = "",
01380 .nationalprefix = "",
01381 .subscriberprefix = "",
01382 .unknownprefix = ""
01383 },
01384 #endif
01385 #ifdef HAVE_OPENR2
01386 .mfcr2 = {
01387 .variant = OR2_VAR_ITU,
01388 .mfback_timeout = -1,
01389 .metering_pulse_timeout = -1,
01390 .max_ani = 10,
01391 .max_dnis = 4,
01392 .get_ani_first = -1,
01393 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01394 .skip_category_request = -1,
01395 #endif
01396 .call_files = 0,
01397 .allow_collect_calls = 0,
01398 .charge_calls = 1,
01399 .accept_on_offer = 1,
01400 .forced_release = 0,
01401 .double_answer = 0,
01402 .immediate_accept = -1,
01403 .logdir = "",
01404 .r2proto_file = "",
01405 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01406 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01407 },
01408 #endif
01409 .chan = {
01410 .context = "default",
01411 .cid_num = "",
01412 .cid_name = "",
01413 .cid_tag = "",
01414 .mohinterpret = "default",
01415 .mohsuggest = "",
01416 .parkinglot = "",
01417 .transfertobusy = 1,
01418
01419 .cid_signalling = CID_SIG_BELL,
01420 .cid_start = CID_START_RING,
01421 .dahditrcallerid = 0,
01422 .use_callerid = 1,
01423 .sig = -1,
01424 .outsigmod = -1,
01425
01426 .cid_rxgain = +5.0,
01427
01428 .tonezone = -1,
01429
01430 .echocancel.head.tap_length = 1,
01431
01432 .busycount = 3,
01433 .busycompare = 0,
01434 .busytonelength = 0,
01435 .busyquietlength = 0,
01436 .busyfuzziness = 0,
01437 .silencethreshold = 0,
01438
01439 .accountcode = "",
01440
01441 .mailbox = "",
01442
01443 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01444 .mwisend_fsk = 1,
01445 #endif
01446 .polarityonanswerdelay = 600,
01447
01448 .sendcalleridafter = DEFAULT_CIDRINGS,
01449
01450 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01451 .buf_no = numbufs,
01452 .usefaxbuffers = 0,
01453 .cc_params = ast_cc_config_params_init(),
01454 },
01455 .timing = {
01456 .prewinktime = -1,
01457 .preflashtime = -1,
01458 .winktime = -1,
01459 .flashtime = -1,
01460 .starttime = -1,
01461 .rxwinktime = -1,
01462 .rxflashtime = -1,
01463 .debouncetime = -1
01464 },
01465 .is_sig_auto = 1,
01466 .smdi_port = "/dev/ttyS0",
01467 };
01468
01469 return conf;
01470 }
01471
01472
01473 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01474 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01475 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01476 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01477 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01478 static int dahdi_hangup(struct ast_channel *ast);
01479 static int dahdi_answer(struct ast_channel *ast);
01480 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01481 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01482 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01483 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01484 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01485 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01486 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01487 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01488 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01489 static int dahdi_devicestate(void *data);
01490 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01491
01492 static const struct ast_channel_tech dahdi_tech = {
01493 .type = "DAHDI",
01494 .description = tdesc,
01495 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01496 .requester = dahdi_request,
01497 .send_digit_begin = dahdi_digit_begin,
01498 .send_digit_end = dahdi_digit_end,
01499 .send_text = dahdi_sendtext,
01500 .call = dahdi_call,
01501 .hangup = dahdi_hangup,
01502 .answer = dahdi_answer,
01503 .read = dahdi_read,
01504 .write = dahdi_write,
01505 .bridge = dahdi_bridge,
01506 .exception = dahdi_exception,
01507 .indicate = dahdi_indicate,
01508 .fixup = dahdi_fixup,
01509 .setoption = dahdi_setoption,
01510 .queryoption = dahdi_queryoption,
01511 .func_channel_read = dahdi_func_read,
01512 .func_channel_write = dahdi_func_write,
01513 .devicestate = dahdi_devicestate,
01514 .cc_callback = dahdi_cc_callback,
01515 };
01516
01517 #define GET_CHANNEL(p) ((p)->channel)
01518
01519 #define SIG_PRI_LIB_HANDLE_CASES \
01520 SIG_PRI: \
01521 case SIG_BRI: \
01522 case SIG_BRI_PTMP
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533 static inline int dahdi_sig_pri_lib_handles(int signaling)
01534 {
01535 int handles;
01536
01537 switch (signaling) {
01538 case SIG_PRI_LIB_HANDLE_CASES:
01539 handles = 1;
01540 break;
01541 default:
01542 handles = 0;
01543 break;
01544 }
01545
01546 return handles;
01547 }
01548
01549 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01550 {
01551 switch (sig) {
01552 case SIG_FXOLS:
01553 return ANALOG_SIG_FXOLS;
01554 case SIG_FXOGS:
01555 return ANALOG_SIG_FXOGS;
01556 case SIG_FXOKS:
01557 return ANALOG_SIG_FXOKS;
01558 case SIG_FXSLS:
01559 return ANALOG_SIG_FXSLS;
01560 case SIG_FXSGS:
01561 return ANALOG_SIG_FXSGS;
01562 case SIG_FXSKS:
01563 return ANALOG_SIG_FXSKS;
01564 case SIG_EMWINK:
01565 return ANALOG_SIG_EMWINK;
01566 case SIG_EM:
01567 return ANALOG_SIG_EM;
01568 case SIG_EM_E1:
01569 return ANALOG_SIG_EM_E1;
01570 case SIG_FEATD:
01571 return ANALOG_SIG_FEATD;
01572 case SIG_FEATDMF:
01573 return ANALOG_SIG_FEATDMF;
01574 case SIG_E911:
01575 return SIG_E911;
01576 case SIG_FGC_CAMA:
01577 return ANALOG_SIG_FGC_CAMA;
01578 case SIG_FGC_CAMAMF:
01579 return ANALOG_SIG_FGC_CAMAMF;
01580 case SIG_FEATB:
01581 return ANALOG_SIG_FEATB;
01582 case SIG_SFWINK:
01583 return ANALOG_SIG_SFWINK;
01584 case SIG_SF:
01585 return ANALOG_SIG_SF;
01586 case SIG_SF_FEATD:
01587 return ANALOG_SIG_SF_FEATD;
01588 case SIG_SF_FEATDMF:
01589 return ANALOG_SIG_SF_FEATDMF;
01590 case SIG_FEATDMF_TA:
01591 return ANALOG_SIG_FEATDMF_TA;
01592 case SIG_SF_FEATB:
01593 return ANALOG_SIG_FEATB;
01594 default:
01595 return -1;
01596 }
01597 }
01598
01599
01600 static int analog_tone_to_dahditone(enum analog_tone tone)
01601 {
01602 switch (tone) {
01603 case ANALOG_TONE_RINGTONE:
01604 return DAHDI_TONE_RINGTONE;
01605 case ANALOG_TONE_STUTTER:
01606 return DAHDI_TONE_STUTTER;
01607 case ANALOG_TONE_CONGESTION:
01608 return DAHDI_TONE_CONGESTION;
01609 case ANALOG_TONE_DIALTONE:
01610 return DAHDI_TONE_DIALTONE;
01611 case ANALOG_TONE_DIALRECALL:
01612 return DAHDI_TONE_DIALRECALL;
01613 case ANALOG_TONE_INFO:
01614 return DAHDI_TONE_INFO;
01615 default:
01616 return -1;
01617 }
01618 }
01619
01620 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01621 {
01622 int index;
01623
01624 switch (analogsub) {
01625 case ANALOG_SUB_REAL:
01626 index = SUB_REAL;
01627 break;
01628 case ANALOG_SUB_CALLWAIT:
01629 index = SUB_CALLWAIT;
01630 break;
01631 case ANALOG_SUB_THREEWAY:
01632 index = SUB_THREEWAY;
01633 break;
01634 default:
01635 ast_log(LOG_ERROR, "Unidentified sub!\n");
01636 index = SUB_REAL;
01637 }
01638
01639 return index;
01640 }
01641
01642 static enum analog_event dahdievent_to_analogevent(int event);
01643 static int bump_gains(struct dahdi_pvt *p);
01644 static int dahdi_setlinear(int dfd, int linear);
01645
01646 static int my_start_cid_detect(void *pvt, int cid_signalling)
01647 {
01648 struct dahdi_pvt *p = pvt;
01649 int index = SUB_REAL;
01650 p->cs = callerid_new(cid_signalling);
01651 if (!p->cs) {
01652 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01653 return -1;
01654 }
01655 bump_gains(p);
01656 dahdi_setlinear(p->subs[index].dfd, 0);
01657
01658 return 0;
01659 }
01660
01661 static int my_stop_cid_detect(void *pvt)
01662 {
01663 struct dahdi_pvt *p = pvt;
01664 int index = SUB_REAL;
01665 if (p->cs)
01666 callerid_free(p->cs);
01667 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01668 return 0;
01669 }
01670
01671 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01672 {
01673 struct dahdi_pvt *p = pvt;
01674 struct analog_pvt *analog_p = p->sig_pvt;
01675 struct pollfd poller;
01676 char *name, *num;
01677 int index = SUB_REAL;
01678 int res;
01679 unsigned char buf[256];
01680 int flags;
01681
01682 poller.fd = p->subs[SUB_REAL].dfd;
01683 poller.events = POLLPRI | POLLIN;
01684 poller.revents = 0;
01685
01686 res = poll(&poller, 1, timeout);
01687
01688 if (poller.revents & POLLPRI) {
01689 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01690 return 1;
01691 }
01692
01693 if (poller.revents & POLLIN) {
01694
01695
01696
01697
01698
01699 res = read(p->subs[index].dfd, buf, sizeof(buf));
01700 if (res < 0) {
01701 if (errno != ELAST) {
01702 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01703 callerid_free(p->cs);
01704 return -1;
01705 }
01706 }
01707
01708 if (analog_p->ringt > 0) {
01709 if (!(--analog_p->ringt)) {
01710
01711 return -1;
01712 }
01713 }
01714
01715 if (p->cid_signalling == CID_SIG_V23_JP) {
01716 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01717 } else {
01718 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01719 }
01720 if (res < 0) {
01721
01722
01723
01724
01725 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01726 return -1;
01727 }
01728
01729 if (res == 1) {
01730 callerid_get(p->cs, &name, &num, &flags);
01731 if (name)
01732 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01733 if (num)
01734 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01735
01736 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01737 return 0;
01738 }
01739 }
01740
01741 *ev = ANALOG_EVENT_NONE;
01742 return 2;
01743 }
01744
01745 static const char *event2str(int event);
01746 static int restore_gains(struct dahdi_pvt *p);
01747
01748 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01749 {
01750 unsigned char buf[256];
01751 int distMatches;
01752 int curRingData[RING_PATTERNS];
01753 int receivedRingT;
01754 int counter1;
01755 int counter;
01756 int i;
01757 int res;
01758 int checkaftercid = 0;
01759
01760 struct dahdi_pvt *p = pvt;
01761 struct analog_pvt *analog_p = p->sig_pvt;
01762
01763 if (ringdata == NULL) {
01764 ringdata = curRingData;
01765 } else {
01766 checkaftercid = 1;
01767 }
01768
01769
01770
01771 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01772
01773 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01774 ringdata[receivedRingT] = 0;
01775 receivedRingT = 0;
01776 if (checkaftercid && distinctiveringaftercid)
01777 ast_verb(3, "Detecting post-CID distinctive ring\n");
01778
01779 else if (strcmp(p->context,p->defcontext) != 0) {
01780 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01781 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01782 }
01783
01784 for (;;) {
01785 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01786 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01787 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01788 ast_hangup(chan);
01789 return 1;
01790 }
01791 if (i & DAHDI_IOMUX_SIGEVENT) {
01792 res = dahdi_get_event(p->subs[idx].dfd);
01793 if (res == DAHDI_EVENT_NOALARM) {
01794 p->inalarm = 0;
01795 analog_p->inalarm = 0;
01796 }
01797 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01798 res = 0;
01799
01800
01801 ringdata[receivedRingT] = analog_p->ringt;
01802
01803 if (analog_p->ringt < analog_p->ringt_base/2)
01804 break;
01805
01806
01807 if (++receivedRingT == RING_PATTERNS)
01808 break;
01809 } else if (i & DAHDI_IOMUX_READ) {
01810 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01811 if (res < 0) {
01812 if (errno != ELAST) {
01813 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01814 ast_hangup(chan);
01815 return 1;
01816 }
01817 break;
01818 }
01819 if (analog_p->ringt > 0) {
01820 if (!(--analog_p->ringt)) {
01821 res = -1;
01822 break;
01823 }
01824 }
01825 }
01826 }
01827 }
01828 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01829
01830 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01831 for (counter = 0; counter < 3; counter++) {
01832
01833 distMatches = 0;
01834
01835 ast_verb(3, "Checking %d,%d,%d\n",
01836 p->drings.ringnum[counter].ring[0],
01837 p->drings.ringnum[counter].ring[1],
01838 p->drings.ringnum[counter].ring[2]);
01839 for (counter1 = 0; counter1 < 3; counter1++) {
01840 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01841 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01842 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01843 ringdata[counter1]);
01844 distMatches++;
01845 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01846 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01847 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01848 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01849 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01850 distMatches++;
01851 }
01852 }
01853
01854 if (distMatches == 3) {
01855
01856 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01857 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01858 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01859 break;
01860 }
01861 }
01862 }
01863
01864 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01865 restore_gains(p);
01866
01867 return 0;
01868 }
01869
01870 static int my_stop_callwait(void *pvt)
01871 {
01872 struct dahdi_pvt *p = pvt;
01873 p->callwaitingrepeat = 0;
01874 p->cidcwexpire = 0;
01875 p->cid_suppress_expire = 0;
01876
01877 return 0;
01878 }
01879
01880 static int send_callerid(struct dahdi_pvt *p);
01881 static int save_conference(struct dahdi_pvt *p);
01882 static int restore_conference(struct dahdi_pvt *p);
01883
01884 static int my_callwait(void *pvt)
01885 {
01886 struct dahdi_pvt *p = pvt;
01887 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01888 if (p->cidspill) {
01889 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01890 ast_free(p->cidspill);
01891 }
01892
01893
01894
01895
01896
01897 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01898 return -1;
01899 save_conference(p);
01900
01901 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01902 if (!p->callwaitrings && p->callwaitingcallerid) {
01903 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01904 p->callwaitcas = 1;
01905 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01906 } else {
01907 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01908 p->callwaitcas = 0;
01909 p->cidlen = 2400 + READ_SIZE * 4;
01910 }
01911 p->cidpos = 0;
01912 send_callerid(p);
01913
01914 return 0;
01915 }
01916
01917 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01918 {
01919 struct dahdi_pvt *p = pvt;
01920
01921 ast_debug(2, "Starting cid spill\n");
01922
01923 if (p->cidspill) {
01924 ast_log(LOG_WARNING, "cidspill already exists??\n");
01925 ast_free(p->cidspill);
01926 }
01927
01928 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01929 if (cwcid == 0) {
01930 p->cidlen = ast_callerid_generate(p->cidspill,
01931 caller->id.name.str,
01932 caller->id.number.str,
01933 AST_LAW(p));
01934 } else {
01935 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01936 caller->id.name.str, caller->id.number.str);
01937 p->callwaitcas = 0;
01938 p->cidcwexpire = 0;
01939 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01940 caller->id.name.str,
01941 caller->id.number.str,
01942 AST_LAW(p));
01943 p->cidlen += READ_SIZE * 4;
01944 }
01945 p->cidpos = 0;
01946 p->cid_suppress_expire = 0;
01947 send_callerid(p);
01948 }
01949 return 0;
01950 }
01951
01952 static int my_dsp_reset_and_flush_digits(void *pvt)
01953 {
01954 struct dahdi_pvt *p = pvt;
01955 if (p->dsp)
01956 ast_dsp_digitreset(p->dsp);
01957
01958 return 0;
01959 }
01960
01961 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01962 {
01963 struct dahdi_pvt *p = pvt;
01964
01965 if (p->channel == CHAN_PSEUDO)
01966 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01967
01968 if (mode == ANALOG_DIGITMODE_DTMF) {
01969
01970 if (p->hardwaredtmf) {
01971 if (p->dsp) {
01972 ast_dsp_free(p->dsp);
01973 p->dsp = NULL;
01974 }
01975 return 0;
01976 }
01977
01978 if (!p->dsp) {
01979 p->dsp = ast_dsp_new();
01980 if (!p->dsp) {
01981 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01982 return -1;
01983 }
01984 }
01985
01986 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01987 } else if (mode == ANALOG_DIGITMODE_MF) {
01988 if (!p->dsp) {
01989 p->dsp = ast_dsp_new();
01990 if (!p->dsp) {
01991 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01992 return -1;
01993 }
01994 }
01995 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01996 }
01997 return 0;
01998 }
01999
02000 static int dahdi_wink(struct dahdi_pvt *p, int index);
02001
02002 static int my_wink(void *pvt, enum analog_sub sub)
02003 {
02004 struct dahdi_pvt *p = pvt;
02005 int index = analogsub_to_dahdisub(sub);
02006 if (index != SUB_REAL) {
02007 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
02008 }
02009 return dahdi_wink(p, index);
02010 }
02011
02012 static void wakeup_sub(struct dahdi_pvt *p, int a);
02013
02014 static int reset_conf(struct dahdi_pvt *p);
02015
02016 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
02017
02018 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
02019 {
02020 struct ast_frame *f = *dest;
02021 struct dahdi_pvt *p = pvt;
02022 int idx = analogsub_to_dahdisub(analog_index);
02023
02024 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02025 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02026 f->subclass.integer, f->subclass.integer, ast->name);
02027
02028 if (f->subclass.integer == 'f') {
02029 if (f->frametype == AST_FRAME_DTMF_END) {
02030
02031 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02032
02033 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02034 struct dahdi_bufferinfo bi = {
02035 .txbufpolicy = p->faxbuf_policy,
02036 .bufsize = p->bufsize,
02037 .numbufs = p->faxbuf_no
02038 };
02039 int res;
02040
02041 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02042 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02043 } else {
02044 p->bufferoverrideinuse = 1;
02045 }
02046 }
02047 p->faxhandled = 1;
02048 if (p->dsp) {
02049 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02050 ast_dsp_set_features(p->dsp, p->dsp_features);
02051 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02052 }
02053 if (strcmp(ast->exten, "fax")) {
02054 const char *target_context = S_OR(ast->macrocontext, ast->context);
02055
02056
02057
02058
02059
02060 ast_mutex_unlock(&p->lock);
02061 ast_channel_unlock(ast);
02062 if (ast_exists_extension(ast, target_context, "fax", 1,
02063 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02064 ast_channel_lock(ast);
02065 ast_mutex_lock(&p->lock);
02066 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02067
02068 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02069 if (ast_async_goto(ast, target_context, "fax", 1))
02070 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02071 } else {
02072 ast_channel_lock(ast);
02073 ast_mutex_lock(&p->lock);
02074 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02075 }
02076 } else {
02077 ast_debug(1, "Already in a fax extension, not redirecting\n");
02078 }
02079 } else {
02080 ast_debug(1, "Fax already handled\n");
02081 }
02082 dahdi_confmute(p, 0);
02083 }
02084 p->subs[idx].f.frametype = AST_FRAME_NULL;
02085 p->subs[idx].f.subclass.integer = 0;
02086 *dest = &p->subs[idx].f;
02087 }
02088 }
02089
02090 static void my_lock_private(void *pvt)
02091 {
02092 struct dahdi_pvt *p = pvt;
02093 ast_mutex_lock(&p->lock);
02094 }
02095
02096 static void my_unlock_private(void *pvt)
02097 {
02098 struct dahdi_pvt *p = pvt;
02099 ast_mutex_unlock(&p->lock);
02100 }
02101
02102 static void my_deadlock_avoidance_private(void *pvt)
02103 {
02104 struct dahdi_pvt *p = pvt;
02105
02106 DEADLOCK_AVOIDANCE(&p->lock);
02107 }
02108
02109
02110
02111
02112 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02113 {
02114 struct dahdi_pvt *p = pvt;
02115 int oldval;
02116 int idx = analogsub_to_dahdisub(sub);
02117
02118 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02119 oldval = p->subs[idx].linear;
02120 p->subs[idx].linear = linear_mode ? 1 : 0;
02121 return oldval;
02122 }
02123
02124 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02125 {
02126 struct dahdi_pvt *p = pvt;
02127 int idx = analogsub_to_dahdisub(sub);
02128
02129 p->subs[idx].inthreeway = inthreeway;
02130 }
02131
02132 static int get_alarms(struct dahdi_pvt *p);
02133 static void handle_alarms(struct dahdi_pvt *p, int alms);
02134 static void my_get_and_handle_alarms(void *pvt)
02135 {
02136 int res;
02137 struct dahdi_pvt *p = pvt;
02138
02139 res = get_alarms(p);
02140 handle_alarms(p, res);
02141 }
02142
02143 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02144 {
02145 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02146 if (p)
02147 return p->sig_pvt;
02148 else
02149 return NULL;
02150 }
02151
02152 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02153 {
02154 struct dahdi_pvt *p = pvt;
02155 int dahdi_sub = analogsub_to_dahdisub(sub);
02156 return p->subs[dahdi_sub].dfd;
02157 }
02158
02159 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02160 {
02161 struct dahdi_pvt *p = pvt;
02162
02163
02164 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02165 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02166 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02167 *cidrings = cidrings[p->distinctivering - 1];
02168 } else {
02169 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02170 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02171 *cidrings = p->sendcalleridafter;
02172 }
02173 }
02174
02175 static void my_set_alarm(void *pvt, int in_alarm)
02176 {
02177 struct dahdi_pvt *p = pvt;
02178
02179 p->inalarm = in_alarm;
02180 }
02181
02182 static void my_set_dialing(void *pvt, int is_dialing)
02183 {
02184 struct dahdi_pvt *p = pvt;
02185
02186 p->dialing = is_dialing;
02187 }
02188
02189 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02190 static void my_set_digital(void *pvt, int is_digital)
02191 {
02192 struct dahdi_pvt *p = pvt;
02193
02194 p->digital = is_digital;
02195 }
02196 #endif
02197
02198 #if defined(HAVE_SS7)
02199 static void my_set_inservice(void *pvt, int is_inservice)
02200 {
02201 struct dahdi_pvt *p = pvt;
02202
02203 p->inservice = is_inservice;
02204 }
02205 #endif
02206
02207 #if defined(HAVE_SS7)
02208 static void my_set_locallyblocked(void *pvt, int is_blocked)
02209 {
02210 struct dahdi_pvt *p = pvt;
02211
02212 p->locallyblocked = is_blocked;
02213 }
02214 #endif
02215
02216 #if defined(HAVE_SS7)
02217 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02218 {
02219 struct dahdi_pvt *p = pvt;
02220
02221 p->remotelyblocked = is_blocked;
02222 }
02223 #endif
02224
02225 static void my_set_ringtimeout(void *pvt, int ringt)
02226 {
02227 struct dahdi_pvt *p = pvt;
02228 p->ringt = ringt;
02229 }
02230
02231 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02232 {
02233 struct dahdi_pvt *p = pvt;
02234
02235 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02236 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02237 gettimeofday(&p->waitingfordt, NULL);
02238 ast_setstate(ast, AST_STATE_OFFHOOK);
02239 }
02240 }
02241
02242 static int my_check_waitingfordt(void *pvt)
02243 {
02244 struct dahdi_pvt *p = pvt;
02245
02246 if (p->waitingfordt.tv_usec) {
02247 return 1;
02248 }
02249
02250 return 0;
02251 }
02252
02253 static void my_set_confirmanswer(void *pvt, int flag)
02254 {
02255 struct dahdi_pvt *p = pvt;
02256 p->confirmanswer = flag;
02257 }
02258
02259 static int my_check_confirmanswer(void *pvt)
02260 {
02261 struct dahdi_pvt *p = pvt;
02262 if (p->confirmanswer) {
02263 return 1;
02264 }
02265
02266 return 0;
02267 }
02268
02269 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02270 {
02271 struct dahdi_pvt *p = pvt;
02272
02273 p->callwaiting = callwaiting_enable;
02274 }
02275
02276 static void my_cancel_cidspill(void *pvt)
02277 {
02278 struct dahdi_pvt *p = pvt;
02279
02280 ast_free(p->cidspill);
02281 p->cidspill = NULL;
02282 restore_conference(p);
02283 }
02284
02285 static int my_confmute(void *pvt, int mute)
02286 {
02287 struct dahdi_pvt *p = pvt;
02288 return dahdi_confmute(p, mute);
02289 }
02290
02291 static void my_set_pulsedial(void *pvt, int flag)
02292 {
02293 struct dahdi_pvt *p = pvt;
02294 p->pulsedial = flag;
02295 }
02296
02297 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02298 {
02299 struct dahdi_pvt *p = pvt;
02300
02301 p->owner = new_owner;
02302 }
02303
02304 static const char *my_get_orig_dialstring(void *pvt)
02305 {
02306 struct dahdi_pvt *p = pvt;
02307
02308 return p->dialstring;
02309 }
02310
02311 static void my_increase_ss_count(void)
02312 {
02313 ast_mutex_lock(&ss_thread_lock);
02314 ss_thread_count++;
02315 ast_mutex_unlock(&ss_thread_lock);
02316 }
02317
02318 static void my_decrease_ss_count(void)
02319 {
02320 ast_mutex_lock(&ss_thread_lock);
02321 ss_thread_count--;
02322 ast_cond_signal(&ss_thread_complete);
02323 ast_mutex_unlock(&ss_thread_lock);
02324 }
02325
02326 static void my_all_subchannels_hungup(void *pvt)
02327 {
02328 struct dahdi_pvt *p = pvt;
02329 int res, law;
02330
02331 p->faxhandled = 0;
02332 p->didtdd = 0;
02333
02334 if (p->dsp) {
02335 ast_dsp_free(p->dsp);
02336 p->dsp = NULL;
02337 }
02338
02339 p->law = p->law_default;
02340 law = p->law_default;
02341 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02342 if (res < 0)
02343 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02344
02345 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02346
02347 #if 1
02348 {
02349 int i;
02350 p->owner = NULL;
02351
02352 for (i = 0; i < 3; i++) {
02353 p->subs[i].owner = NULL;
02354 }
02355 }
02356 #endif
02357
02358 reset_conf(p);
02359 if (num_restart_pending == 0) {
02360 restart_monitor();
02361 }
02362 }
02363
02364 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02365
02366 static int my_conf_del(void *pvt, enum analog_sub sub)
02367 {
02368 struct dahdi_pvt *p = pvt;
02369 int x = analogsub_to_dahdisub(sub);
02370
02371 return conf_del(p, &p->subs[x], x);
02372 }
02373
02374 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02375
02376 static int my_conf_add(void *pvt, enum analog_sub sub)
02377 {
02378 struct dahdi_pvt *p = pvt;
02379 int x = analogsub_to_dahdisub(sub);
02380
02381 return conf_add(p, &p->subs[x], x, 0);
02382 }
02383
02384 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02385
02386 static int my_complete_conference_update(void *pvt, int needconference)
02387 {
02388 struct dahdi_pvt *p = pvt;
02389 int needconf = needconference;
02390 int x;
02391 int useslavenative;
02392 struct dahdi_pvt *slave = NULL;
02393
02394 useslavenative = isslavenative(p, &slave);
02395
02396
02397
02398 for (x = 0; x < MAX_SLAVES; x++) {
02399 if (p->slaves[x]) {
02400 if (useslavenative)
02401 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02402 else {
02403 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02404 needconf++;
02405 }
02406 }
02407 }
02408
02409 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02410 if (useslavenative)
02411 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02412 else {
02413 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02414 needconf++;
02415 }
02416 }
02417
02418 if (p->master) {
02419 if (isslavenative(p->master, NULL)) {
02420 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02421 } else {
02422 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02423 }
02424 }
02425 if (!needconf) {
02426
02427
02428 p->confno = -1;
02429 }
02430
02431 return 0;
02432 }
02433
02434 static int check_for_conference(struct dahdi_pvt *p);
02435
02436 static int my_check_for_conference(void *pvt)
02437 {
02438 struct dahdi_pvt *p = pvt;
02439 return check_for_conference(p);
02440 }
02441
02442 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)
02443 {
02444 struct dahdi_pvt *p = pvt;
02445 int da, db;
02446 int tchan;
02447 int tinthreeway;
02448
02449 da = analogsub_to_dahdisub(a);
02450 db = analogsub_to_dahdisub(b);
02451
02452 tchan = p->subs[da].chan;
02453 p->subs[da].chan = p->subs[db].chan;
02454 p->subs[db].chan = tchan;
02455
02456 tinthreeway = p->subs[da].inthreeway;
02457 p->subs[da].inthreeway = p->subs[db].inthreeway;
02458 p->subs[db].inthreeway = tinthreeway;
02459
02460 p->subs[da].owner = ast_a;
02461 p->subs[db].owner = ast_b;
02462
02463 if (ast_a)
02464 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02465 if (ast_b)
02466 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02467
02468 wakeup_sub(p, a);
02469 wakeup_sub(p, b);
02470
02471 return;
02472 }
02473
02474 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02475
02476 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02477 {
02478 struct dahdi_pvt *p = pvt;
02479 int dsub = analogsub_to_dahdisub(sub);
02480
02481 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02482 }
02483
02484 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02485 static int dahdi_setlaw(int dfd, int law)
02486 {
02487 int res;
02488 res = ioctl(dfd, DAHDI_SETLAW, &law);
02489 if (res)
02490 return res;
02491 return 0;
02492 }
02493 #endif
02494
02495 #if defined(HAVE_PRI)
02496 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)
02497 {
02498 struct dahdi_pvt *p = pvt;
02499 int audio;
02500 int newlaw = -1;
02501
02502 switch (p->sig) {
02503 case SIG_PRI_LIB_HANDLE_CASES:
02504 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02505
02506 break;
02507 }
02508
02509 default:
02510
02511 audio = 1;
02512 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02513 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02514 p->channel, audio, strerror(errno));
02515 }
02516 break;
02517 }
02518
02519 if (law != SIG_PRI_DEFLAW) {
02520 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02521 }
02522
02523 ast_copy_string(p->exten, exten, sizeof(p->exten));
02524
02525 switch (law) {
02526 case SIG_PRI_DEFLAW:
02527 newlaw = 0;
02528 break;
02529 case SIG_PRI_ALAW:
02530 newlaw = DAHDI_LAW_ALAW;
02531 break;
02532 case SIG_PRI_ULAW:
02533 newlaw = DAHDI_LAW_MULAW;
02534 break;
02535 }
02536 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02537 }
02538 #endif
02539
02540 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02541
02542 #if defined(HAVE_PRI)
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552 static void my_pri_open_media(void *p)
02553 {
02554 struct dahdi_pvt *pvt = p;
02555 int res;
02556 int dfd;
02557 int set_val;
02558
02559 dfd = pvt->subs[SUB_REAL].dfd;
02560
02561
02562 set_val = 1;
02563 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02564 if (res < 0) {
02565 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02566 pvt->channel, strerror(errno));
02567 }
02568
02569
02570 res = dahdi_setlaw(dfd, pvt->law);
02571 if (res < 0) {
02572 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02573 }
02574
02575
02576 if (pvt->digital) {
02577 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02578 } else {
02579 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02580 pvt->law);
02581 }
02582 if (res < 0) {
02583 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02584 }
02585
02586 if (pvt->dsp_features && pvt->dsp) {
02587 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02588 pvt->dsp_features = 0;
02589 }
02590 }
02591 #endif
02592
02593 static int unalloc_sub(struct dahdi_pvt *p, int x);
02594
02595 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02596 {
02597 struct dahdi_pvt *p = pvt;
02598
02599 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02600 }
02601
02602 static int alloc_sub(struct dahdi_pvt *p, int x);
02603
02604 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02605 {
02606 struct dahdi_pvt *p = pvt;
02607
02608 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02609 }
02610
02611 static int has_voicemail(struct dahdi_pvt *p);
02612
02613 static int my_has_voicemail(void *pvt)
02614 {
02615 struct dahdi_pvt *p = pvt;
02616
02617 return has_voicemail(p);
02618 }
02619
02620 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02621 {
02622 struct dahdi_pvt *p = pvt;
02623 int index;
02624
02625 index = analogsub_to_dahdisub(sub);
02626
02627 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02628 }
02629
02630 static enum analog_event dahdievent_to_analogevent(int event)
02631 {
02632 enum analog_event res;
02633
02634 switch (event) {
02635 case DAHDI_EVENT_ONHOOK:
02636 res = ANALOG_EVENT_ONHOOK;
02637 break;
02638 case DAHDI_EVENT_RINGOFFHOOK:
02639 res = ANALOG_EVENT_RINGOFFHOOK;
02640 break;
02641 case DAHDI_EVENT_WINKFLASH:
02642 res = ANALOG_EVENT_WINKFLASH;
02643 break;
02644 case DAHDI_EVENT_ALARM:
02645 res = ANALOG_EVENT_ALARM;
02646 break;
02647 case DAHDI_EVENT_NOALARM:
02648 res = ANALOG_EVENT_NOALARM;
02649 break;
02650 case DAHDI_EVENT_DIALCOMPLETE:
02651 res = ANALOG_EVENT_DIALCOMPLETE;
02652 break;
02653 case DAHDI_EVENT_RINGERON:
02654 res = ANALOG_EVENT_RINGERON;
02655 break;
02656 case DAHDI_EVENT_RINGEROFF:
02657 res = ANALOG_EVENT_RINGEROFF;
02658 break;
02659 case DAHDI_EVENT_HOOKCOMPLETE:
02660 res = ANALOG_EVENT_HOOKCOMPLETE;
02661 break;
02662 case DAHDI_EVENT_PULSE_START:
02663 res = ANALOG_EVENT_PULSE_START;
02664 break;
02665 case DAHDI_EVENT_POLARITY:
02666 res = ANALOG_EVENT_POLARITY;
02667 break;
02668 case DAHDI_EVENT_RINGBEGIN:
02669 res = ANALOG_EVENT_RINGBEGIN;
02670 break;
02671 case DAHDI_EVENT_EC_DISABLED:
02672 res = ANALOG_EVENT_EC_DISABLED;
02673 break;
02674 case DAHDI_EVENT_REMOVED:
02675 res = ANALOG_EVENT_REMOVED;
02676 break;
02677 case DAHDI_EVENT_NEONMWI_ACTIVE:
02678 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02679 break;
02680 case DAHDI_EVENT_NEONMWI_INACTIVE:
02681 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02682 break;
02683 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02684 case DAHDI_EVENT_TX_CED_DETECTED:
02685 res = ANALOG_EVENT_TX_CED_DETECTED;
02686 break;
02687 case DAHDI_EVENT_RX_CED_DETECTED:
02688 res = ANALOG_EVENT_RX_CED_DETECTED;
02689 break;
02690 case DAHDI_EVENT_EC_NLP_DISABLED:
02691 res = ANALOG_EVENT_EC_NLP_DISABLED;
02692 break;
02693 case DAHDI_EVENT_EC_NLP_ENABLED:
02694 res = ANALOG_EVENT_EC_NLP_ENABLED;
02695 break;
02696 #endif
02697 case DAHDI_EVENT_PULSEDIGIT:
02698 res = ANALOG_EVENT_PULSEDIGIT;
02699 break;
02700 case DAHDI_EVENT_DTMFDOWN:
02701 res = ANALOG_EVENT_DTMFDOWN;
02702 break;
02703 case DAHDI_EVENT_DTMFUP:
02704 res = ANALOG_EVENT_DTMFUP;
02705 break;
02706 default:
02707 switch(event & 0xFFFF0000) {
02708 case DAHDI_EVENT_PULSEDIGIT:
02709 case DAHDI_EVENT_DTMFDOWN:
02710 case DAHDI_EVENT_DTMFUP:
02711
02712
02713
02714
02715 return event;
02716 }
02717
02718 res = ANALOG_EVENT_ERROR;
02719 break;
02720 }
02721
02722 return res;
02723 }
02724
02725 static inline int dahdi_wait_event(int fd);
02726
02727 static int my_wait_event(void *pvt)
02728 {
02729 struct dahdi_pvt *p = pvt;
02730
02731 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02732 }
02733
02734 static int my_get_event(void *pvt)
02735 {
02736 struct dahdi_pvt *p = pvt;
02737 int res;
02738
02739 if (p->fake_event) {
02740 res = p->fake_event;
02741 p->fake_event = 0;
02742 } else
02743 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02744
02745 return dahdievent_to_analogevent(res);
02746 }
02747
02748 static int my_is_off_hook(void *pvt)
02749 {
02750 struct dahdi_pvt *p = pvt;
02751 int res;
02752 struct dahdi_params par;
02753
02754 memset(&par, 0, sizeof(par));
02755
02756 if (p->subs[SUB_REAL].dfd > -1)
02757 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02758 else {
02759
02760 res = 0;
02761 par.rxisoffhook = 0;
02762 }
02763 if (res) {
02764 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02765 }
02766
02767 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02768
02769
02770
02771 return (par.rxbits > -1) || par.rxisoffhook;
02772 }
02773
02774 return par.rxisoffhook;
02775 }
02776
02777 static void dahdi_enable_ec(struct dahdi_pvt *p);
02778 static void dahdi_disable_ec(struct dahdi_pvt *p);
02779
02780 static int my_set_echocanceller(void *pvt, int enable)
02781 {
02782 struct dahdi_pvt *p = pvt;
02783
02784 if (enable)
02785 dahdi_enable_ec(p);
02786 else
02787 dahdi_disable_ec(p);
02788
02789 return 0;
02790 }
02791
02792 static int dahdi_ring_phone(struct dahdi_pvt *p);
02793
02794 static int my_ring(void *pvt)
02795 {
02796 struct dahdi_pvt *p = pvt;
02797
02798 return dahdi_ring_phone(p);
02799 }
02800
02801 static int my_flash(void *pvt)
02802 {
02803 struct dahdi_pvt *p = pvt;
02804 int func = DAHDI_FLASH;
02805 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02806 }
02807
02808 static inline int dahdi_set_hook(int fd, int hs);
02809
02810 static int my_off_hook(void *pvt)
02811 {
02812 struct dahdi_pvt *p = pvt;
02813 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02814 }
02815
02816 static void my_set_needringing(void *pvt, int value)
02817 {
02818 struct dahdi_pvt *p = pvt;
02819 p->subs[SUB_REAL].needringing = value;
02820 }
02821
02822 static void my_set_polarity(void *pvt, int value)
02823 {
02824 struct dahdi_pvt *p = pvt;
02825
02826 if (p->channel == CHAN_PSEUDO) {
02827 return;
02828 }
02829 p->polarity = value;
02830 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02831 }
02832
02833 static void my_start_polarityswitch(void *pvt)
02834 {
02835 struct dahdi_pvt *p = pvt;
02836
02837 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02838 my_set_polarity(pvt, 0);
02839 }
02840 }
02841
02842 static void my_answer_polarityswitch(void *pvt)
02843 {
02844 struct dahdi_pvt *p = pvt;
02845
02846 if (!p->answeronpolarityswitch) {
02847 return;
02848 }
02849
02850 my_set_polarity(pvt, 1);
02851 }
02852
02853 static void my_hangup_polarityswitch(void *pvt)
02854 {
02855 struct dahdi_pvt *p = pvt;
02856
02857 if (!p->hanguponpolarityswitch) {
02858 return;
02859 }
02860
02861 if (p->answeronpolarityswitch) {
02862 my_set_polarity(pvt, 0);
02863 } else {
02864 my_set_polarity(pvt, 1);
02865 }
02866 }
02867
02868 static int my_start(void *pvt)
02869 {
02870 struct dahdi_pvt *p = pvt;
02871 int x = DAHDI_START;
02872
02873 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02874 }
02875
02876 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02877 {
02878 int index = analogsub_to_dahdisub(sub);
02879 int res;
02880 struct dahdi_pvt *p = pvt;
02881 struct dahdi_dialoperation ddop;
02882
02883 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02884 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02885 return -1;
02886 }
02887
02888 if (sub != ANALOG_SUB_REAL)
02889 printf("Trying to dial digits on sub %d\n", sub);
02890
02891 ddop.op = DAHDI_DIAL_OP_REPLACE;
02892 strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02893
02894 printf("Dialing %s on %d\n", ddop.dialstr, p->channel);
02895
02896 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02897
02898 if (res == -1)
02899 ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02900
02901 return res;
02902 }
02903
02904 static void dahdi_train_ec(struct dahdi_pvt *p);
02905
02906 static int my_train_echocanceller(void *pvt)
02907 {
02908 struct dahdi_pvt *p = pvt;
02909
02910 dahdi_train_ec(p);
02911
02912 return 0;
02913 }
02914
02915 static int my_is_dialing(void *pvt, enum analog_sub sub)
02916 {
02917 struct dahdi_pvt *p = pvt;
02918 int index;
02919 int x;
02920
02921 index = analogsub_to_dahdisub(sub);
02922
02923 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02924 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02925 return -1;
02926 }
02927
02928 return x;
02929 }
02930
02931 static int my_on_hook(void *pvt)
02932 {
02933 struct dahdi_pvt *p = pvt;
02934 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02935 }
02936
02937 #if defined(HAVE_PRI)
02938 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02939 {
02940 struct dahdi_pvt *old_chan = chan_old;
02941 struct dahdi_pvt *new_chan = chan_new;
02942
02943 new_chan->owner = old_chan->owner;
02944 old_chan->owner = NULL;
02945 if (new_chan->owner) {
02946 new_chan->owner->tech_pvt = new_chan;
02947 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
02948 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
02949 old_chan->subs[SUB_REAL].owner = NULL;
02950 }
02951
02952 new_chan->dsp = old_chan->dsp;
02953 new_chan->dsp_features = old_chan->dsp_features;
02954 old_chan->dsp = NULL;
02955 old_chan->dsp_features = 0;
02956
02957
02958 new_chan->dialing = old_chan->dialing;
02959 new_chan->digital = old_chan->digital;
02960 new_chan->outgoing = old_chan->outgoing;
02961 old_chan->dialing = 0;
02962 old_chan->digital = 0;
02963 old_chan->outgoing = 0;
02964
02965
02966 new_chan->law = old_chan->law;
02967 strcpy(new_chan->dialstring, old_chan->dialstring);
02968 }
02969 #endif
02970
02971 #if defined(HAVE_PRI)
02972 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
02973 {
02974 switch (tone) {
02975 case SIG_PRI_TONE_RINGTONE:
02976 return DAHDI_TONE_RINGTONE;
02977 case SIG_PRI_TONE_STUTTER:
02978 return DAHDI_TONE_STUTTER;
02979 case SIG_PRI_TONE_CONGESTION:
02980 return DAHDI_TONE_CONGESTION;
02981 case SIG_PRI_TONE_DIALTONE:
02982 return DAHDI_TONE_DIALTONE;
02983 case SIG_PRI_TONE_DIALRECALL:
02984 return DAHDI_TONE_DIALRECALL;
02985 case SIG_PRI_TONE_INFO:
02986 return DAHDI_TONE_INFO;
02987 case SIG_PRI_TONE_BUSY:
02988 return DAHDI_TONE_BUSY;
02989 default:
02990 return -1;
02991 }
02992 }
02993 #endif
02994
02995 #if defined(HAVE_PRI)
02996 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
02997 {
02998 int x, res;
02999
03000 res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
03001 if (x) {
03002 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
03003 }
03004
03005 switch (x) {
03006 case DAHDI_EVENT_ALARM:
03007 pri_event_alarm(pri, index, 0);
03008 break;
03009 case DAHDI_EVENT_NOALARM:
03010 pri_event_noalarm(pri, index, 0);
03011 break;
03012 default:
03013 break;
03014 }
03015 }
03016 #endif
03017
03018 #if defined(HAVE_PRI)
03019 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03020 {
03021 struct dahdi_pvt *p = pvt;
03022
03023 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03024 }
03025 #endif
03026
03027 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03039 {
03040 struct dahdi_pvt *p = pvt;
03041
03042 ast_copy_string(p->cid_num,
03043 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03044 sizeof(p->cid_num));
03045 ast_copy_string(p->cid_name,
03046 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03047 sizeof(p->cid_name));
03048 ast_copy_string(p->cid_subaddr,
03049 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03050 sizeof(p->cid_subaddr));
03051 p->cid_ton = caller->id.number.plan;
03052 p->callingpres = ast_party_id_presentation(&caller->id);
03053 if (caller->id.tag) {
03054 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03055 }
03056 ast_copy_string(p->cid_ani,
03057 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03058 sizeof(p->cid_ani));
03059 p->cid_ani2 = caller->ani2;
03060 }
03061 #endif
03062
03063 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074 static void my_set_dnid(void *pvt, const char *dnid)
03075 {
03076 struct dahdi_pvt *p = pvt;
03077
03078 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03079 }
03080 #endif
03081
03082 #if defined(HAVE_PRI)
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093 static void my_set_rdnis(void *pvt, const char *rdnis)
03094 {
03095 struct dahdi_pvt *p = pvt;
03096
03097 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03098 }
03099 #endif
03100
03101 #if defined(HAVE_PRI)
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03127 {
03128 char *dial;
03129 struct dahdi_pvt *pvt;
03130 AST_DECLARE_APP_ARGS(args,
03131 AST_APP_ARG(tech);
03132 AST_APP_ARG(group);
03133
03134
03135
03136 );
03137
03138 pvt = priv;
03139 dial = ast_strdupa(pvt->dialstring);
03140 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03141 if (!args.tech) {
03142 ast_copy_string(buf, pvt->dialstring, buf_size);
03143 return;
03144 }
03145 if (!args.group) {
03146
03147 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03148 return;
03149 }
03150 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03151
03152
03153 ast_copy_string(buf, pvt->dialstring, buf_size);
03154 return;
03155 }
03156
03157 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03158 }
03159 #endif
03160
03161 #if defined(HAVE_PRI)
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03174 {
03175 unsigned idx;
03176 unsigned num_b_chans;
03177 unsigned in_use;
03178 unsigned in_alarm;
03179 enum ast_device_state new_state;
03180
03181
03182 num_b_chans = 0;
03183 in_use = 0;
03184 in_alarm = 1;
03185 for (idx = pri->numchans; idx--;) {
03186 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03187
03188 ++num_b_chans;
03189 if (pri->pvts[idx]->owner
03190 #if defined(HAVE_PRI_SERVICE_MESSAGES)
03191
03192 || pri->pvts[idx]->service_status
03193 #endif
03194 ) {
03195 ++in_use;
03196 }
03197 if (!pri->pvts[idx]->inalarm) {
03198
03199 in_alarm = 0;
03200 }
03201 }
03202 }
03203
03204
03205 if (in_alarm) {
03206 new_state = AST_DEVICE_UNAVAILABLE;
03207 } else {
03208 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03209 }
03210 if (pri->congestion_devstate != new_state) {
03211 pri->congestion_devstate = new_state;
03212 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03213 }
03214 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03215
03216 if (in_alarm) {
03217 new_state = AST_DEVICE_UNAVAILABLE;
03218 } else if (!in_use) {
03219 new_state = AST_DEVICE_NOT_INUSE;
03220 } else if (!pri->user_busy_threshold) {
03221 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03222 } else {
03223 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03224 : AST_DEVICE_BUSY;
03225 }
03226 if (pri->threshold_devstate != new_state) {
03227 pri->threshold_devstate = new_state;
03228 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03229 }
03230 #endif
03231 }
03232 #endif
03233
03234 #if defined(HAVE_PRI)
03235
03236
03237
03238
03239
03240
03241
03242 static void my_module_ref(void)
03243 {
03244 ast_module_ref(ast_module_info->self);
03245 }
03246 #endif
03247
03248 #if defined(HAVE_PRI)
03249
03250
03251
03252
03253
03254
03255
03256 static void my_module_unref(void)
03257 {
03258 ast_module_unref(ast_module_info->self);
03259 }
03260 #endif
03261
03262 #if defined(HAVE_PRI)
03263 #if defined(HAVE_PRI_CALL_WAITING)
03264 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03265 #endif
03266 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03267
03268 static struct sig_pri_callback dahdi_pri_callbacks =
03269 {
03270 .handle_dchan_exception = my_handle_dchan_exception,
03271 .play_tone = my_pri_play_tone,
03272 .set_echocanceller = my_set_echocanceller,
03273 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03274 .lock_private = my_lock_private,
03275 .unlock_private = my_unlock_private,
03276 .new_ast_channel = my_new_pri_ast_channel,
03277 .fixup_chans = my_pri_fixup_chans,
03278 .set_alarm = my_set_alarm,
03279 .set_dialing = my_set_dialing,
03280 .set_digital = my_set_digital,
03281 .set_callerid = my_set_callerid,
03282 .set_dnid = my_set_dnid,
03283 .set_rdnis = my_set_rdnis,
03284 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03285 #if defined(HAVE_PRI_CALL_WAITING)
03286 .init_config = my_pri_init_config,
03287 #endif
03288 .get_orig_dialstring = my_get_orig_dialstring,
03289 .make_cc_dialstring = my_pri_make_cc_dialstring,
03290 .update_span_devstate = dahdi_pri_update_span_devstate,
03291 .module_ref = my_module_ref,
03292 .module_unref = my_module_unref,
03293 .open_media = my_pri_open_media,
03294 };
03295 #endif
03296
03297 #if defined(HAVE_SS7)
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03309 {
03310 int event;
03311
03312 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03313 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03314 linkset->span, which);
03315 return;
03316 }
03317 switch (event) {
03318 case DAHDI_EVENT_NONE:
03319 break;
03320 case DAHDI_EVENT_ALARM:
03321 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03322 event2str(event), event, linkset->span, which);
03323 sig_ss7_link_alarm(linkset, which);
03324 break;
03325 case DAHDI_EVENT_NOALARM:
03326 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03327 event2str(event), event, linkset->span, which);
03328 sig_ss7_link_noalarm(linkset, which);
03329 break;
03330 default:
03331 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03332 event2str(event), event, linkset->span, which);
03333 break;
03334 }
03335 }
03336 #endif
03337
03338 #if defined(HAVE_SS7)
03339 static void my_ss7_set_loopback(void *pvt, int enable)
03340 {
03341 struct dahdi_pvt *p = pvt;
03342
03343 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03344 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03345 strerror(errno));
03346 }
03347 }
03348 #endif
03349
03350 #if defined(HAVE_SS7)
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365 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)
03366 {
03367 struct dahdi_pvt *p = pvt;
03368 int audio;
03369 int newlaw;
03370
03371
03372 audio = 1;
03373 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03374 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03375 p->channel, audio, strerror(errno));
03376
03377 if (law != SIG_SS7_DEFLAW) {
03378 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03379 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03380 }
03381
03382 ast_copy_string(p->exten, exten, sizeof(p->exten));
03383
03384 newlaw = -1;
03385 switch (law) {
03386 case SIG_SS7_DEFLAW:
03387 newlaw = 0;
03388 break;
03389 case SIG_SS7_ALAW:
03390 newlaw = DAHDI_LAW_ALAW;
03391 break;
03392 case SIG_SS7_ULAW:
03393 newlaw = DAHDI_LAW_MULAW;
03394 break;
03395 }
03396 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03397 }
03398 #endif
03399
03400 #if defined(HAVE_SS7)
03401 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03402 {
03403 switch (tone) {
03404 case SIG_SS7_TONE_RINGTONE:
03405 return DAHDI_TONE_RINGTONE;
03406 case SIG_SS7_TONE_STUTTER:
03407 return DAHDI_TONE_STUTTER;
03408 case SIG_SS7_TONE_CONGESTION:
03409 return DAHDI_TONE_CONGESTION;
03410 case SIG_SS7_TONE_DIALTONE:
03411 return DAHDI_TONE_DIALTONE;
03412 case SIG_SS7_TONE_DIALRECALL:
03413 return DAHDI_TONE_DIALRECALL;
03414 case SIG_SS7_TONE_INFO:
03415 return DAHDI_TONE_INFO;
03416 case SIG_SS7_TONE_BUSY:
03417 return DAHDI_TONE_BUSY;
03418 default:
03419 return -1;
03420 }
03421 }
03422 #endif
03423
03424 #if defined(HAVE_SS7)
03425 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03426 {
03427 struct dahdi_pvt *p = pvt;
03428
03429 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03430 }
03431 #endif
03432
03433 #if defined(HAVE_SS7)
03434 static struct sig_ss7_callback dahdi_ss7_callbacks =
03435 {
03436 .lock_private = my_lock_private,
03437 .unlock_private = my_unlock_private,
03438
03439 .set_echocanceller = my_set_echocanceller,
03440 .set_loopback = my_ss7_set_loopback,
03441
03442 .new_ast_channel = my_new_ss7_ast_channel,
03443 .play_tone = my_ss7_play_tone,
03444
03445 .handle_link_exception = my_handle_link_exception,
03446 .set_alarm = my_set_alarm,
03447 .set_dialing = my_set_dialing,
03448 .set_digital = my_set_digital,
03449 .set_inservice = my_set_inservice,
03450 .set_locallyblocked = my_set_locallyblocked,
03451 .set_remotelyblocked = my_set_remotelyblocked,
03452 .set_callerid = my_set_callerid,
03453 .set_dnid = my_set_dnid,
03454 };
03455 #endif
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475 static void notify_message(char *mailbox_full, int thereornot)
03476 {
03477 char s[sizeof(mwimonitornotify) + 80];
03478 struct ast_event *event;
03479 char *mailbox, *context;
03480
03481
03482 context = mailbox = ast_strdupa(mailbox_full);
03483 strsep(&context, "@");
03484 if (ast_strlen_zero(context))
03485 context = "default";
03486
03487 if (!(event = ast_event_new(AST_EVENT_MWI,
03488 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03489 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03490 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03491 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03492 AST_EVENT_IE_END))) {
03493 return;
03494 }
03495
03496 ast_event_queue_and_cache(event);
03497
03498 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03499 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03500 ast_safe_system(s);
03501 }
03502 }
03503
03504 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03505 {
03506 struct dahdi_pvt *p = pvt;
03507
03508 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03509 return;
03510
03511 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03512 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03513 notify_message(p->mailbox, 1);
03514 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03515 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03516 notify_message(p->mailbox, 0);
03517 }
03518
03519
03520 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03521 ast_hangup(chan);
03522 return;
03523 }
03524 }
03525
03526
03527
03528 static struct analog_callback dahdi_analog_callbacks =
03529 {
03530 .play_tone = my_play_tone,
03531 .get_event = my_get_event,
03532 .wait_event = my_wait_event,
03533 .is_off_hook = my_is_off_hook,
03534 .set_echocanceller = my_set_echocanceller,
03535 .ring = my_ring,
03536 .flash = my_flash,
03537 .off_hook = my_off_hook,
03538 .dial_digits = my_dial_digits,
03539 .train_echocanceller = my_train_echocanceller,
03540 .on_hook = my_on_hook,
03541 .is_dialing = my_is_dialing,
03542 .allocate_sub = my_allocate_sub,
03543 .unallocate_sub = my_unallocate_sub,
03544 .swap_subs = my_swap_subchannels,
03545 .has_voicemail = my_has_voicemail,
03546 .check_for_conference = my_check_for_conference,
03547 .conf_add = my_conf_add,
03548 .conf_del = my_conf_del,
03549 .complete_conference_update = my_complete_conference_update,
03550 .start = my_start,
03551 .all_subchannels_hungup = my_all_subchannels_hungup,
03552 .lock_private = my_lock_private,
03553 .unlock_private = my_unlock_private,
03554 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03555 .handle_dtmf = my_handle_dtmf,
03556 .wink = my_wink,
03557 .new_ast_channel = my_new_analog_ast_channel,
03558 .dsp_set_digitmode = my_dsp_set_digitmode,
03559 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03560 .send_callerid = my_send_callerid,
03561 .callwait = my_callwait,
03562 .stop_callwait = my_stop_callwait,
03563 .get_callerid = my_get_callerid,
03564 .start_cid_detect = my_start_cid_detect,
03565 .stop_cid_detect = my_stop_cid_detect,
03566 .handle_notify_message = my_handle_notify_message,
03567 .increase_ss_count = my_increase_ss_count,
03568 .decrease_ss_count = my_decrease_ss_count,
03569 .distinctive_ring = my_distinctive_ring,
03570 .set_linear_mode = my_set_linear_mode,
03571 .set_inthreeway = my_set_inthreeway,
03572 .get_and_handle_alarms = my_get_and_handle_alarms,
03573 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03574 .get_sub_fd = my_get_sub_fd,
03575 .set_cadence = my_set_cadence,
03576 .set_alarm = my_set_alarm,
03577 .set_dialing = my_set_dialing,
03578 .set_ringtimeout = my_set_ringtimeout,
03579 .set_waitingfordt = my_set_waitingfordt,
03580 .check_waitingfordt = my_check_waitingfordt,
03581 .set_confirmanswer = my_set_confirmanswer,
03582 .check_confirmanswer = my_check_confirmanswer,
03583 .set_callwaiting = my_set_callwaiting,
03584 .cancel_cidspill = my_cancel_cidspill,
03585 .confmute = my_confmute,
03586 .set_pulsedial = my_set_pulsedial,
03587 .set_new_owner = my_set_new_owner,
03588 .get_orig_dialstring = my_get_orig_dialstring,
03589 .set_needringing = my_set_needringing,
03590 .set_polarity = my_set_polarity,
03591 .start_polarityswitch = my_start_polarityswitch,
03592 .answer_polarityswitch = my_answer_polarityswitch,
03593 .hangup_polarityswitch = my_hangup_polarityswitch,
03594 };
03595
03596
03597 static struct dahdi_pvt *round_robin[32];
03598
03599 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03600 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03601 {
03602 int res;
03603 if (p->subs[SUB_REAL].owner == ast)
03604 res = 0;
03605 else if (p->subs[SUB_CALLWAIT].owner == ast)
03606 res = 1;
03607 else if (p->subs[SUB_THREEWAY].owner == ast)
03608 res = 2;
03609 else {
03610 res = -1;
03611 if (!nullok)
03612 ast_log(LOG_WARNING,
03613 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03614 ast ? ast->name : "", p->channel, fname, line);
03615 }
03616 return res;
03617 }
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03635 {
03636 for (;;) {
03637 if (!pvt->subs[sub_idx].owner) {
03638
03639 break;
03640 }
03641 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03642
03643 break;
03644 }
03645
03646 DEADLOCK_AVOIDANCE(&pvt->lock);
03647 }
03648 }
03649
03650 static void wakeup_sub(struct dahdi_pvt *p, int a)
03651 {
03652 dahdi_lock_sub_owner(p, a);
03653 if (p->subs[a].owner) {
03654 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03655 ast_channel_unlock(p->subs[a].owner);
03656 }
03657 }
03658
03659 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03660 {
03661 for (;;) {
03662 if (p->owner) {
03663 if (ast_channel_trylock(p->owner)) {
03664 DEADLOCK_AVOIDANCE(&p->lock);
03665 } else {
03666 ast_queue_frame(p->owner, f);
03667 ast_channel_unlock(p->owner);
03668 break;
03669 }
03670 } else
03671 break;
03672 }
03673 }
03674
03675 static void handle_clear_alarms(struct dahdi_pvt *p)
03676 {
03677 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03678 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03679 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03680 }
03681 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03682 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03683 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03684 }
03685 }
03686
03687 #ifdef HAVE_OPENR2
03688
03689 static int dahdi_r2_answer(struct dahdi_pvt *p)
03690 {
03691 int res = 0;
03692
03693
03694
03695 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03696 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03697 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03698 if (!double_answer) {
03699
03700
03701 res = openr2_chan_answer_call(p->r2chan);
03702 } else if (wants_double_answer) {
03703 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03704 } else {
03705 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03706 }
03707 #else
03708 res = openr2_chan_answer_call(p->r2chan);
03709 #endif
03710 return res;
03711 }
03712
03713
03714
03715
03716 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03717 {
03718 openr2_calling_party_category_t cat;
03719 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03720 struct dahdi_pvt *p = c->tech_pvt;
03721 if (ast_strlen_zero(catstr)) {
03722 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03723 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03724 return p->mfcr2_category;
03725 }
03726 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03727 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03728 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03729 return p->mfcr2_category;
03730 }
03731 ast_debug(1, "Using category %s\n", catstr);
03732 return cat;
03733 }
03734
03735 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03736 {
03737 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03738 ast_mutex_lock(&p->lock);
03739 if (p->mfcr2call) {
03740 ast_mutex_unlock(&p->lock);
03741
03742
03743
03744
03745
03746 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03747 return;
03748 }
03749 p->mfcr2call = 1;
03750
03751 p->cid_name[0] = '\0';
03752 p->cid_num[0] = '\0';
03753 p->cid_subaddr[0] = '\0';
03754 p->rdnis[0] = '\0';
03755 p->exten[0] = '\0';
03756 p->mfcr2_ani_index = '\0';
03757 p->mfcr2_dnis_index = '\0';
03758 p->mfcr2_dnis_matched = 0;
03759 p->mfcr2_answer_pending = 0;
03760 p->mfcr2_call_accepted = 0;
03761 ast_mutex_unlock(&p->lock);
03762 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03763 }
03764
03765 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03766 {
03767 int res;
03768 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03769 ast_mutex_lock(&p->lock);
03770 p->inalarm = alarm ? 1 : 0;
03771 if (p->inalarm) {
03772 res = get_alarms(p);
03773 handle_alarms(p, res);
03774 } else {
03775 handle_clear_alarms(p);
03776 }
03777 ast_mutex_unlock(&p->lock);
03778 }
03779
03780 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03781 {
03782 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03783 }
03784
03785 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03786 {
03787 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03788 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03789 if (p->owner) {
03790 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03791 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03792 }
03793 ast_mutex_lock(&p->lock);
03794 p->mfcr2call = 0;
03795 ast_mutex_unlock(&p->lock);
03796 }
03797
03798 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03799 {
03800 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03801 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03802 p->channel, openr2_proto_get_disconnect_string(cause));
03803
03804 openr2_chan_set_idle(p->r2chan);
03805 ast_mutex_lock(&p->lock);
03806 p->mfcr2call = 0;
03807 ast_mutex_unlock(&p->lock);
03808 }
03809 }
03810
03811 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03812 {
03813 struct dahdi_pvt *p;
03814 struct ast_channel *c;
03815 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03816 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03817 openr2_proto_get_category_string(category));
03818 p = openr2_chan_get_client_data(r2chan);
03819
03820 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03821 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03822 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03823 return;
03824 }
03825 ast_mutex_lock(&p->lock);
03826 p->mfcr2_recvd_category = category;
03827
03828 if (!p->use_callerid) {
03829 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03830 p->cid_num[0] = 0;
03831 p->cid_name[0] = 0;
03832 }
03833
03834 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03835 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03836 p->exten[0] = 's';
03837 p->exten[1] = 0;
03838 }
03839 ast_mutex_unlock(&p->lock);
03840 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03841 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03842 p->channel, p->exten, p->context);
03843 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03844 return;
03845 }
03846 if (!p->mfcr2_accept_on_offer) {
03847
03848 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03849 if (c) {
03850
03851
03852
03853 return;
03854 }
03855 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03856 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03857 } else if (p->mfcr2_charge_calls) {
03858 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03859 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03860 } else {
03861 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03862 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03863 }
03864 }
03865
03866 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03867 {
03868 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03869 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03870 ast_mutex_lock(&p->lock);
03871 p->mfcr2call = 0;
03872 ast_mutex_unlock(&p->lock);
03873 }
03874
03875 static void dahdi_enable_ec(struct dahdi_pvt *p);
03876 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03877 {
03878 struct dahdi_pvt *p = NULL;
03879 struct ast_channel *c = NULL;
03880 p = openr2_chan_get_client_data(r2chan);
03881 dahdi_enable_ec(p);
03882 p->mfcr2_call_accepted = 1;
03883
03884 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03885 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03886
03887
03888
03889
03890 if (!p->mfcr2_accept_on_offer) {
03891 openr2_chan_disable_read(r2chan);
03892 if (p->mfcr2_answer_pending) {
03893 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03894 dahdi_r2_answer(p);
03895 }
03896 return;
03897 }
03898 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03899 if (c) {
03900
03901
03902 openr2_chan_disable_read(r2chan);
03903 return;
03904 }
03905 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03906
03907 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03908 return;
03909 }
03910
03911 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03912 p->subs[SUB_REAL].needringing = 1;
03913 p->dialing = 0;
03914
03915 openr2_chan_disable_read(r2chan);
03916 }
03917
03918 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03919 {
03920 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03921 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03922 p->subs[SUB_REAL].needanswer = 1;
03923 }
03924
03925 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03926 {
03927
03928 }
03929
03930 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03931 {
03932 switch (cause) {
03933 case OR2_CAUSE_BUSY_NUMBER:
03934 return AST_CAUSE_BUSY;
03935 case OR2_CAUSE_NETWORK_CONGESTION:
03936 return AST_CAUSE_CONGESTION;
03937 case OR2_CAUSE_OUT_OF_ORDER:
03938 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03939 case OR2_CAUSE_UNALLOCATED_NUMBER:
03940 return AST_CAUSE_UNREGISTERED;
03941 case OR2_CAUSE_NO_ANSWER:
03942 return AST_CAUSE_NO_ANSWER;
03943 case OR2_CAUSE_NORMAL_CLEARING:
03944 return AST_CAUSE_NORMAL_CLEARING;
03945 case OR2_CAUSE_UNSPECIFIED:
03946 default:
03947 return AST_CAUSE_NOTDEFINED;
03948 }
03949 }
03950
03951 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
03952 {
03953 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03954 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
03955 ast_mutex_lock(&p->lock);
03956 if (!p->owner) {
03957 ast_mutex_unlock(&p->lock);
03958
03959 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
03960 return;
03961 }
03962
03963
03964 if (p->owner->_state == AST_STATE_UP) {
03965 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03966 ast_mutex_unlock(&p->lock);
03967 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
03968
03969 switch (cause) {
03970 case OR2_CAUSE_BUSY_NUMBER:
03971 p->subs[SUB_REAL].needbusy = 1;
03972 break;
03973 case OR2_CAUSE_NETWORK_CONGESTION:
03974 case OR2_CAUSE_OUT_OF_ORDER:
03975 case OR2_CAUSE_UNALLOCATED_NUMBER:
03976 case OR2_CAUSE_NO_ANSWER:
03977 case OR2_CAUSE_UNSPECIFIED:
03978 case OR2_CAUSE_NORMAL_CLEARING:
03979 p->subs[SUB_REAL].needcongestion = 1;
03980 break;
03981 default:
03982 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03983 }
03984 ast_mutex_unlock(&p->lock);
03985 } else {
03986 ast_mutex_unlock(&p->lock);
03987
03988
03989 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
03990 }
03991 }
03992
03993 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
03994 {
03995 switch (level) {
03996 case OR2_LOG_NOTICE:
03997 ast_verbose("%s", logmessage);
03998 break;
03999 case OR2_LOG_WARNING:
04000 ast_log(LOG_WARNING, "%s", logmessage);
04001 break;
04002 case OR2_LOG_ERROR:
04003 ast_log(LOG_ERROR, "%s", logmessage);
04004 break;
04005 case OR2_LOG_STACK_TRACE:
04006 case OR2_LOG_MF_TRACE:
04007 case OR2_LOG_CAS_TRACE:
04008 case OR2_LOG_DEBUG:
04009 case OR2_LOG_EX_DEBUG:
04010 ast_log(LOG_DEBUG, "%s", logmessage);
04011 break;
04012 default:
04013 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
04014 ast_log(LOG_DEBUG, "%s", logmessage);
04015 break;
04016 }
04017 }
04018
04019 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04020 {
04021 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04022 ast_mutex_lock(&p->lock);
04023 p->remotelyblocked = 1;
04024 ast_mutex_unlock(&p->lock);
04025 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04026 }
04027
04028 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04029 {
04030 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04031 ast_mutex_lock(&p->lock);
04032 p->remotelyblocked = 0;
04033 ast_mutex_unlock(&p->lock);
04034 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04035 }
04036
04037 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04038 __attribute__((format (printf, 3, 0)));
04039 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04040 {
04041 #define CONTEXT_TAG "Context - "
04042 char logmsg[256];
04043 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04044 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04045 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04046 dahdi_r2_write_log(level, completemsg);
04047 #undef CONTEXT_TAG
04048 }
04049
04050 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04051 __attribute__((format (printf, 3, 0)));
04052 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04053 {
04054 #define CHAN_TAG "Chan "
04055 char logmsg[256];
04056 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04057 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04058 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04059 dahdi_r2_write_log(level, completemsg);
04060 }
04061
04062 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04063 {
04064 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04065
04066 if (p->immediate) {
04067 return 0;
04068 }
04069 p->exten[p->mfcr2_dnis_index] = digit;
04070 p->rdnis[p->mfcr2_dnis_index] = digit;
04071 p->mfcr2_dnis_index++;
04072 p->exten[p->mfcr2_dnis_index] = 0;
04073 p->rdnis[p->mfcr2_dnis_index] = 0;
04074
04075 if ((p->mfcr2_dnis_matched ||
04076 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04077 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04078 return 0;
04079 }
04080
04081 return 1;
04082 }
04083
04084 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04085 {
04086 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04087 p->cid_num[p->mfcr2_ani_index] = digit;
04088 p->cid_name[p->mfcr2_ani_index] = digit;
04089 p->mfcr2_ani_index++;
04090 p->cid_num[p->mfcr2_ani_index] = 0;
04091 p->cid_name[p->mfcr2_ani_index] = 0;
04092 }
04093
04094 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04095 {
04096 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04097 }
04098
04099 static openr2_event_interface_t dahdi_r2_event_iface = {
04100 .on_call_init = dahdi_r2_on_call_init,
04101 .on_call_offered = dahdi_r2_on_call_offered,
04102 .on_call_accepted = dahdi_r2_on_call_accepted,
04103 .on_call_answered = dahdi_r2_on_call_answered,
04104 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04105 .on_call_end = dahdi_r2_on_call_end,
04106 .on_call_read = dahdi_r2_on_call_read,
04107 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04108 .on_os_error = dahdi_r2_on_os_error,
04109 .on_protocol_error = dahdi_r2_on_protocol_error,
04110 .on_line_blocked = dahdi_r2_on_line_blocked,
04111 .on_line_idle = dahdi_r2_on_line_idle,
04112
04113 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04114 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04115 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04116
04117 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04118 };
04119
04120 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04121 {
04122 return AST_ALAW(sample);
04123 }
04124
04125 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04126 {
04127 return AST_LIN2A(sample);
04128 }
04129
04130 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04131 dahdi_r2_alaw_to_linear,
04132 dahdi_r2_linear_to_alaw
04133 };
04134
04135 #endif
04136
04137 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04138 {
04139 int tchan;
04140 int tinthreeway;
04141 struct ast_channel *towner;
04142
04143 ast_debug(1, "Swapping %d and %d\n", a, b);
04144
04145 tchan = p->subs[a].chan;
04146 towner = p->subs[a].owner;
04147 tinthreeway = p->subs[a].inthreeway;
04148
04149 p->subs[a].chan = p->subs[b].chan;
04150 p->subs[a].owner = p->subs[b].owner;
04151 p->subs[a].inthreeway = p->subs[b].inthreeway;
04152
04153 p->subs[b].chan = tchan;
04154 p->subs[b].owner = towner;
04155 p->subs[b].inthreeway = tinthreeway;
04156
04157 if (p->subs[a].owner)
04158 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04159 if (p->subs[b].owner)
04160 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04161 wakeup_sub(p, a);
04162 wakeup_sub(p, b);
04163 }
04164
04165 static int dahdi_open(char *fn)
04166 {
04167 int fd;
04168 int isnum;
04169 int chan = 0;
04170 int bs;
04171 int x;
04172 isnum = 1;
04173 for (x = 0; x < strlen(fn); x++) {
04174 if (!isdigit(fn[x])) {
04175 isnum = 0;
04176 break;
04177 }
04178 }
04179 if (isnum) {
04180 chan = atoi(fn);
04181 if (chan < 1) {
04182 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04183 return -1;
04184 }
04185 fn = "/dev/dahdi/channel";
04186 }
04187 fd = open(fn, O_RDWR | O_NONBLOCK);
04188 if (fd < 0) {
04189 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04190 return -1;
04191 }
04192 if (chan) {
04193 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04194 x = errno;
04195 close(fd);
04196 errno = x;
04197 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04198 return -1;
04199 }
04200 }
04201 bs = READ_SIZE;
04202 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04203 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04204 x = errno;
04205 close(fd);
04206 errno = x;
04207 return -1;
04208 }
04209 return fd;
04210 }
04211
04212 static void dahdi_close(int fd)
04213 {
04214 if (fd > 0)
04215 close(fd);
04216 }
04217
04218 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04219 {
04220 dahdi_close(chan_pvt->subs[sub_num].dfd);
04221 chan_pvt->subs[sub_num].dfd = -1;
04222 }
04223
04224 #if defined(HAVE_PRI)
04225 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04226 {
04227 dahdi_close(pri->pri.fds[fd_num]);
04228 pri->pri.fds[fd_num] = -1;
04229 }
04230 #endif
04231
04232 #if defined(HAVE_SS7)
04233 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04234 {
04235 dahdi_close(ss7->ss7.fds[fd_num]);
04236 ss7->ss7.fds[fd_num] = -1;
04237 }
04238 #endif
04239
04240 static int dahdi_setlinear(int dfd, int linear)
04241 {
04242 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04243 }
04244
04245
04246 static int alloc_sub(struct dahdi_pvt *p, int x)
04247 {
04248 struct dahdi_bufferinfo bi;
04249 int res;
04250 if (p->subs[x].dfd >= 0) {
04251 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04252 return -1;
04253 }
04254
04255 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04256 if (p->subs[x].dfd <= -1) {
04257 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04258 return -1;
04259 }
04260
04261 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04262 if (!res) {
04263 bi.txbufpolicy = p->buf_policy;
04264 bi.rxbufpolicy = p->buf_policy;
04265 bi.numbufs = p->buf_no;
04266 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04267 if (res < 0) {
04268 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04269 }
04270 } else
04271 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04272
04273 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04274 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04275 dahdi_close_sub(p, x);
04276 p->subs[x].dfd = -1;
04277 return -1;
04278 }
04279 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04280 return 0;
04281 }
04282
04283 static int unalloc_sub(struct dahdi_pvt *p, int x)
04284 {
04285 if (!x) {
04286 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04287 return -1;
04288 }
04289 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04290 dahdi_close_sub(p, x);
04291 p->subs[x].linear = 0;
04292 p->subs[x].chan = 0;
04293 p->subs[x].owner = NULL;
04294 p->subs[x].inthreeway = 0;
04295 p->polarity = POLARITY_IDLE;
04296 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04297 return 0;
04298 }
04299
04300 static int digit_to_dtmfindex(char digit)
04301 {
04302 if (isdigit(digit))
04303 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04304 else if (digit >= 'A' && digit <= 'D')
04305 return DAHDI_TONE_DTMF_A + (digit - 'A');
04306 else if (digit >= 'a' && digit <= 'd')
04307 return DAHDI_TONE_DTMF_A + (digit - 'a');
04308 else if (digit == '*')
04309 return DAHDI_TONE_DTMF_s;
04310 else if (digit == '#')
04311 return DAHDI_TONE_DTMF_p;
04312 else
04313 return -1;
04314 }
04315
04316 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04317 {
04318 struct dahdi_pvt *pvt;
04319 int idx;
04320 int dtmf = -1;
04321 int res;
04322
04323 pvt = chan->tech_pvt;
04324
04325 ast_mutex_lock(&pvt->lock);
04326
04327 idx = dahdi_get_index(chan, pvt, 0);
04328
04329 if ((idx != SUB_REAL) || !pvt->owner)
04330 goto out;
04331
04332 #ifdef HAVE_PRI
04333 switch (pvt->sig) {
04334 case SIG_PRI_LIB_HANDLE_CASES:
04335 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04336 if (!res)
04337 goto out;
04338 break;
04339 default:
04340 break;
04341 }
04342 #endif
04343 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04344 goto out;
04345
04346 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04347 struct dahdi_dialoperation zo = {
04348 .op = DAHDI_DIAL_OP_APPEND,
04349 };
04350
04351 zo.dialstr[0] = 'T';
04352 zo.dialstr[1] = digit;
04353 zo.dialstr[2] = '\0';
04354 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04355 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04356 else
04357 pvt->dialing = 1;
04358 } else {
04359 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04360 pvt->dialing = 1;
04361 pvt->begindigit = digit;
04362 }
04363
04364 out:
04365 ast_mutex_unlock(&pvt->lock);
04366
04367 return 0;
04368 }
04369
04370 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04371 {
04372 struct dahdi_pvt *pvt;
04373 int res = 0;
04374 int idx;
04375 int x;
04376
04377 pvt = chan->tech_pvt;
04378
04379 ast_mutex_lock(&pvt->lock);
04380
04381 idx = dahdi_get_index(chan, pvt, 0);
04382
04383 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04384 goto out;
04385
04386 #ifdef HAVE_PRI
04387
04388 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04389 goto out;
04390 }
04391 #endif
04392
04393 if (pvt->begindigit) {
04394 x = -1;
04395 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04396 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04397 pvt->dialing = 0;
04398 pvt->begindigit = 0;
04399 }
04400
04401 out:
04402 ast_mutex_unlock(&pvt->lock);
04403
04404 return res;
04405 }
04406
04407 static const char * const events[] = {
04408 "No event",
04409 "On hook",
04410 "Ring/Answered",
04411 "Wink/Flash",
04412 "Alarm",
04413 "No more alarm",
04414 "HDLC Abort",
04415 "HDLC Overrun",
04416 "HDLC Bad FCS",
04417 "Dial Complete",
04418 "Ringer On",
04419 "Ringer Off",
04420 "Hook Transition Complete",
04421 "Bits Changed",
04422 "Pulse Start",
04423 "Timer Expired",
04424 "Timer Ping",
04425 "Polarity Reversal",
04426 "Ring Begin",
04427 };
04428
04429 static struct {
04430 int alarm;
04431 char *name;
04432 } alarms[] = {
04433 { DAHDI_ALARM_RED, "Red Alarm" },
04434 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04435 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04436 { DAHDI_ALARM_RECOVER, "Recovering" },
04437 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04438 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04439 { DAHDI_ALARM_NONE, "None" },
04440 };
04441
04442 static char *alarm2str(int alm)
04443 {
04444 int x;
04445 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04446 if (alarms[x].alarm & alm)
04447 return alarms[x].name;
04448 }
04449 return alm ? "Unknown Alarm" : "No Alarm";
04450 }
04451
04452 static const char *event2str(int event)
04453 {
04454 static char buf[256];
04455 if ((event < (ARRAY_LEN(events))) && (event > -1))
04456 return events[event];
04457 sprintf(buf, "Event %d", event);
04458 return buf;
04459 }
04460
04461 static char *dahdi_sig2str(int sig)
04462 {
04463 static char buf[256];
04464 switch (sig) {
04465 case SIG_EM:
04466 return "E & M Immediate";
04467 case SIG_EMWINK:
04468 return "E & M Wink";
04469 case SIG_EM_E1:
04470 return "E & M E1";
04471 case SIG_FEATD:
04472 return "Feature Group D (DTMF)";
04473 case SIG_FEATDMF:
04474 return "Feature Group D (MF)";
04475 case SIG_FEATDMF_TA:
04476 return "Feature Groud D (MF) Tandem Access";
04477 case SIG_FEATB:
04478 return "Feature Group B (MF)";
04479 case SIG_E911:
04480 return "E911 (MF)";
04481 case SIG_FGC_CAMA:
04482 return "FGC/CAMA (Dialpulse)";
04483 case SIG_FGC_CAMAMF:
04484 return "FGC/CAMA (MF)";
04485 case SIG_FXSLS:
04486 return "FXS Loopstart";
04487 case SIG_FXSGS:
04488 return "FXS Groundstart";
04489 case SIG_FXSKS:
04490 return "FXS Kewlstart";
04491 case SIG_FXOLS:
04492 return "FXO Loopstart";
04493 case SIG_FXOGS:
04494 return "FXO Groundstart";
04495 case SIG_FXOKS:
04496 return "FXO Kewlstart";
04497 case SIG_PRI:
04498 return "ISDN PRI";
04499 case SIG_BRI:
04500 return "ISDN BRI Point to Point";
04501 case SIG_BRI_PTMP:
04502 return "ISDN BRI Point to MultiPoint";
04503 case SIG_SS7:
04504 return "SS7";
04505 case SIG_MFCR2:
04506 return "MFC/R2";
04507 case SIG_SF:
04508 return "SF (Tone) Immediate";
04509 case SIG_SFWINK:
04510 return "SF (Tone) Wink";
04511 case SIG_SF_FEATD:
04512 return "SF (Tone) with Feature Group D (DTMF)";
04513 case SIG_SF_FEATDMF:
04514 return "SF (Tone) with Feature Group D (MF)";
04515 case SIG_SF_FEATB:
04516 return "SF (Tone) with Feature Group B (MF)";
04517 case 0:
04518 return "Pseudo";
04519 default:
04520 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04521 return buf;
04522 }
04523 }
04524
04525 #define sig2str dahdi_sig2str
04526
04527 static int analog_lib_handles(int signalling, int radio, int oprmode)
04528 {
04529 switch (signalling) {
04530 case SIG_FXOLS:
04531 case SIG_FXOGS:
04532 case SIG_FXOKS:
04533 case SIG_FXSLS:
04534 case SIG_FXSGS:
04535 case SIG_FXSKS:
04536 case SIG_EMWINK:
04537 case SIG_EM:
04538 case SIG_EM_E1:
04539 case SIG_FEATD:
04540 case SIG_FEATDMF:
04541 case SIG_E911:
04542 case SIG_FGC_CAMA:
04543 case SIG_FGC_CAMAMF:
04544 case SIG_FEATB:
04545 case SIG_SFWINK:
04546 case SIG_SF:
04547 case SIG_SF_FEATD:
04548 case SIG_SF_FEATDMF:
04549 case SIG_FEATDMF_TA:
04550 case SIG_SF_FEATB:
04551 break;
04552 default:
04553
04554 return 0;
04555 }
04556
04557 if (radio)
04558 return 0;
04559
04560 if (oprmode)
04561 return 0;
04562
04563 return 1;
04564 }
04565
04566 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04567 {
04568
04569
04570 struct dahdi_confinfo zi;
04571
04572 memset(&zi, 0, sizeof(zi));
04573 zi.chan = 0;
04574
04575 if (slavechannel > 0) {
04576
04577 zi.confmode = DAHDI_CONF_DIGITALMON;
04578 zi.confno = slavechannel;
04579 } else {
04580 if (!idx) {
04581
04582 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04583 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04584 } else
04585 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04586 zi.confno = p->confno;
04587 }
04588 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04589 return 0;
04590 if (c->dfd < 0)
04591 return 0;
04592 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04593 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04594 return -1;
04595 }
04596 if (slavechannel < 1) {
04597 p->confno = zi.confno;
04598 }
04599 c->curconf = zi;
04600 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04601 return 0;
04602 }
04603
04604 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04605 {
04606
04607 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04608 return 1;
04609
04610 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04611 return 1;
04612 return 0;
04613 }
04614
04615 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04616 {
04617 struct dahdi_confinfo zi;
04618 if (
04619 (c->dfd < 0) ||
04620
04621 !isourconf(p, c)
04622
04623 ) return 0;
04624 memset(&zi, 0, sizeof(zi));
04625 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04626 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04627 return -1;
04628 }
04629 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04630 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04631 return 0;
04632 }
04633
04634 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04635 {
04636 int x;
04637 int useslavenative;
04638 struct dahdi_pvt *slave = NULL;
04639
04640 useslavenative = 1;
04641
04642 for (x = 0; x < 3; x++) {
04643
04644
04645 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04646 useslavenative = 0;
04647 }
04648
04649
04650 if (useslavenative) {
04651 for (x = 0; x < MAX_SLAVES; x++) {
04652 if (p->slaves[x]) {
04653 if (slave) {
04654
04655
04656 slave = NULL;
04657 useslavenative = 0;
04658 break;
04659 } else {
04660
04661 slave = p->slaves[x];
04662 }
04663 }
04664 }
04665 }
04666
04667 if (!slave)
04668 useslavenative = 0;
04669 else if (slave->law != p->law) {
04670 useslavenative = 0;
04671 slave = NULL;
04672 }
04673 if (out)
04674 *out = slave;
04675 return useslavenative;
04676 }
04677
04678 static int reset_conf(struct dahdi_pvt *p)
04679 {
04680 p->confno = -1;
04681 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04682 if (p->subs[SUB_REAL].dfd > -1) {
04683 struct dahdi_confinfo zi;
04684
04685 memset(&zi, 0, sizeof(zi));
04686 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04687 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04688 }
04689 return 0;
04690 }
04691
04692 static int update_conf(struct dahdi_pvt *p)
04693 {
04694 int needconf = 0;
04695 int x;
04696 int useslavenative;
04697 struct dahdi_pvt *slave = NULL;
04698
04699 useslavenative = isslavenative(p, &slave);
04700
04701 for (x = 0; x < 3; x++) {
04702
04703 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04704 conf_add(p, &p->subs[x], x, 0);
04705 needconf++;
04706 } else {
04707 conf_del(p, &p->subs[x], x);
04708 }
04709 }
04710
04711
04712 for (x = 0; x < MAX_SLAVES; x++) {
04713 if (p->slaves[x]) {
04714 if (useslavenative)
04715 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04716 else {
04717 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04718 needconf++;
04719 }
04720 }
04721 }
04722
04723 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04724 if (useslavenative)
04725 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04726 else {
04727 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04728 needconf++;
04729 }
04730 }
04731
04732 if (p->master) {
04733 if (isslavenative(p->master, NULL)) {
04734 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04735 } else {
04736 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04737 }
04738 }
04739 if (!needconf) {
04740
04741
04742 p->confno = -1;
04743 }
04744 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04745 return 0;
04746 }
04747
04748 static void dahdi_enable_ec(struct dahdi_pvt *p)
04749 {
04750 int res;
04751 if (!p)
04752 return;
04753 if (p->echocanon) {
04754 ast_debug(1, "Echo cancellation already on\n");
04755 return;
04756 }
04757 if (p->digital) {
04758 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04759 return;
04760 }
04761 if (p->echocancel.head.tap_length) {
04762 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04763 switch (p->sig) {
04764 #if defined(HAVE_PRI)
04765 case SIG_PRI_LIB_HANDLE_CASES:
04766 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04767
04768
04769
04770
04771 return;
04772 }
04773
04774 #endif
04775 #if defined(HAVE_SS7)
04776 case SIG_SS7:
04777 #endif
04778 {
04779 int x = 1;
04780
04781 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04782 if (res)
04783 ast_log(LOG_WARNING,
04784 "Unable to enable audio mode on channel %d (%s)\n",
04785 p->channel, strerror(errno));
04786 }
04787 break;
04788 default:
04789 break;
04790 }
04791 #endif
04792 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04793 if (res) {
04794 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04795 } else {
04796 p->echocanon = 1;
04797 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04798 }
04799 } else
04800 ast_debug(1, "No echo cancellation requested\n");
04801 }
04802
04803 static void dahdi_train_ec(struct dahdi_pvt *p)
04804 {
04805 int x;
04806 int res;
04807
04808 if (p && p->echocanon && p->echotraining) {
04809 x = p->echotraining;
04810 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04811 if (res)
04812 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04813 else
04814 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04815 } else {
04816 ast_debug(1, "No echo training requested\n");
04817 }
04818 }
04819
04820 static void dahdi_disable_ec(struct dahdi_pvt *p)
04821 {
04822 int res;
04823
04824 if (p->echocanon) {
04825 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04826
04827 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04828
04829 if (res)
04830 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04831 else
04832 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04833 }
04834
04835 p->echocanon = 0;
04836 }
04837
04838
04839 static int drc_sample(int sample, float drc)
04840 {
04841 float neg;
04842 float shallow, steep;
04843 float max = SHRT_MAX;
04844
04845 neg = (sample < 0 ? -1 : 1);
04846 steep = drc*sample;
04847 shallow = neg*(max-max/drc)+(float)sample/drc;
04848 if (abs(steep) < abs(shallow)) {
04849 sample = steep;
04850 }
04851 else {
04852 sample = shallow;
04853 }
04854
04855 return sample;
04856 }
04857
04858
04859 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04860 {
04861 int j;
04862 int k;
04863
04864 float linear_gain = pow(10.0, gain / 20.0);
04865
04866 switch (law) {
04867 case DAHDI_LAW_ALAW:
04868 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04869 if (gain || drc) {
04870 k = AST_ALAW(j);
04871 if (drc) {
04872 k = drc_sample(k, drc);
04873 }
04874 k = (float)k*linear_gain;
04875 if (k > 32767) k = 32767;
04876 if (k < -32767) k = -32767;
04877 g->txgain[j] = AST_LIN2A(k);
04878 } else {
04879 g->txgain[j] = j;
04880 }
04881 }
04882 break;
04883 case DAHDI_LAW_MULAW:
04884 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04885 if (gain || drc) {
04886 k = AST_MULAW(j);
04887 if (drc) {
04888 k = drc_sample(k, drc);
04889 }
04890 k = (float)k*linear_gain;
04891 if (k > 32767) k = 32767;
04892 if (k < -32767) k = -32767;
04893 g->txgain[j] = AST_LIN2MU(k);
04894
04895 } else {
04896 g->txgain[j] = j;
04897 }
04898 }
04899 break;
04900 }
04901 }
04902
04903 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04904 {
04905 int j;
04906 int k;
04907 float linear_gain = pow(10.0, gain / 20.0);
04908
04909 switch (law) {
04910 case DAHDI_LAW_ALAW:
04911 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04912 if (gain || drc) {
04913 k = AST_ALAW(j);
04914 if (drc) {
04915 k = drc_sample(k, drc);
04916 }
04917 k = (float)k*linear_gain;
04918 if (k > 32767) k = 32767;
04919 if (k < -32767) k = -32767;
04920 g->rxgain[j] = AST_LIN2A(k);
04921 } else {
04922 g->rxgain[j] = j;
04923 }
04924 }
04925 break;
04926 case DAHDI_LAW_MULAW:
04927 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04928 if (gain || drc) {
04929 k = AST_MULAW(j);
04930 if (drc) {
04931 k = drc_sample(k, drc);
04932 }
04933 k = (float)k*linear_gain;
04934 if (k > 32767) k = 32767;
04935 if (k < -32767) k = -32767;
04936 g->rxgain[j] = AST_LIN2MU(k);
04937 } else {
04938 g->rxgain[j] = j;
04939 }
04940 }
04941 break;
04942 }
04943 }
04944
04945 static int set_actual_txgain(int fd, float gain, float drc, int law)
04946 {
04947 struct dahdi_gains g;
04948 int res;
04949
04950 memset(&g, 0, sizeof(g));
04951 res = ioctl(fd, DAHDI_GETGAINS, &g);
04952 if (res) {
04953 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04954 return res;
04955 }
04956
04957 fill_txgain(&g, gain, drc, law);
04958
04959 return ioctl(fd, DAHDI_SETGAINS, &g);
04960 }
04961
04962 static int set_actual_rxgain(int fd, float gain, float drc, int law)
04963 {
04964 struct dahdi_gains g;
04965 int res;
04966
04967 memset(&g, 0, sizeof(g));
04968 res = ioctl(fd, DAHDI_GETGAINS, &g);
04969 if (res) {
04970 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04971 return res;
04972 }
04973
04974 fill_rxgain(&g, gain, drc, law);
04975
04976 return ioctl(fd, DAHDI_SETGAINS, &g);
04977 }
04978
04979 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
04980 {
04981 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04982 }
04983
04984 static int bump_gains(struct dahdi_pvt *p)
04985 {
04986 int res;
04987
04988
04989 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04990 if (res) {
04991 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04992 return -1;
04993 }
04994
04995 return 0;
04996 }
04997
04998 static int restore_gains(struct dahdi_pvt *p)
04999 {
05000 int res;
05001
05002 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05003 if (res) {
05004 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
05005 return -1;
05006 }
05007
05008 return 0;
05009 }
05010
05011 static inline int dahdi_set_hook(int fd, int hs)
05012 {
05013 int x, res;
05014
05015 x = hs;
05016 res = ioctl(fd, DAHDI_HOOK, &x);
05017
05018 if (res < 0) {
05019 if (errno == EINPROGRESS)
05020 return 0;
05021 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05022
05023 }
05024
05025 return res;
05026 }
05027
05028 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05029 {
05030 int x, res;
05031
05032 x = muted;
05033 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05034 switch (p->sig) {
05035 #if defined(HAVE_PRI)
05036 case SIG_PRI_LIB_HANDLE_CASES:
05037 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05038
05039 break;
05040 }
05041
05042 #endif
05043 #if defined(HAVE_SS7)
05044 case SIG_SS7:
05045 #endif
05046 {
05047 int y = 1;
05048
05049 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05050 if (res)
05051 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05052 p->channel, strerror(errno));
05053 }
05054 break;
05055 default:
05056 break;
05057 }
05058 #endif
05059 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05060 if (res < 0)
05061 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05062 return res;
05063 }
05064
05065 static int save_conference(struct dahdi_pvt *p)
05066 {
05067 struct dahdi_confinfo c;
05068 int res;
05069 if (p->saveconf.confmode) {
05070 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05071 return -1;
05072 }
05073 p->saveconf.chan = 0;
05074 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05075 if (res) {
05076 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05077 p->saveconf.confmode = 0;
05078 return -1;
05079 }
05080 memset(&c, 0, sizeof(c));
05081 c.confmode = DAHDI_CONF_NORMAL;
05082 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05083 if (res) {
05084 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05085 return -1;
05086 }
05087 ast_debug(1, "Disabled conferencing\n");
05088 return 0;
05089 }
05090
05091 static int restore_conference(struct dahdi_pvt *p)
05092 {
05093 int res;
05094 if (p->saveconf.confmode) {
05095 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05096 p->saveconf.confmode = 0;
05097 if (res) {
05098 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05099 return -1;
05100 }
05101 ast_debug(1, "Restored conferencing\n");
05102 }
05103 return 0;
05104 }
05105
05106 static int send_cwcidspill(struct dahdi_pvt *p)
05107 {
05108 p->callwaitcas = 0;
05109 p->cidcwexpire = 0;
05110 p->cid_suppress_expire = 0;
05111 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05112 return -1;
05113 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05114
05115 p->cidlen += READ_SIZE * 4;
05116 p->cidpos = 0;
05117 send_callerid(p);
05118 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05119 return 0;
05120 }
05121
05122 static int has_voicemail(struct dahdi_pvt *p)
05123 {
05124 int new_msgs;
05125 struct ast_event *event;
05126 char *mailbox, *context;
05127
05128 mailbox = context = ast_strdupa(p->mailbox);
05129 strsep(&context, "@");
05130 if (ast_strlen_zero(context))
05131 context = "default";
05132
05133 event = ast_event_get_cached(AST_EVENT_MWI,
05134 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05135 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05136 AST_EVENT_IE_END);
05137
05138 if (event) {
05139 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05140 ast_event_destroy(event);
05141 } else
05142 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05143
05144 return new_msgs;
05145 }
05146
05147
05148
05149 static int send_callerid(struct dahdi_pvt *p)
05150 {
05151
05152 int res;
05153
05154 if (p->subs[SUB_REAL].linear) {
05155 p->subs[SUB_REAL].linear = 0;
05156 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05157 }
05158 while (p->cidpos < p->cidlen) {
05159 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05160 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05161 if (res < 0) {
05162 if (errno == EAGAIN)
05163 return 0;
05164 else {
05165 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05166 return -1;
05167 }
05168 }
05169 if (!res)
05170 return 0;
05171 p->cidpos += res;
05172 }
05173 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05174 ast_free(p->cidspill);
05175 p->cidspill = NULL;
05176 if (p->callwaitcas) {
05177
05178 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05179 p->cid_suppress_expire = p->cidcwexpire;
05180 } else
05181 restore_conference(p);
05182 return 0;
05183 }
05184
05185 static int dahdi_callwait(struct ast_channel *ast)
05186 {
05187 struct dahdi_pvt *p = ast->tech_pvt;
05188 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05189 if (p->cidspill) {
05190 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05191 ast_free(p->cidspill);
05192 }
05193
05194
05195
05196
05197
05198 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05199 return -1;
05200 save_conference(p);
05201
05202 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05203 if (!p->callwaitrings && p->callwaitingcallerid) {
05204 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05205 p->callwaitcas = 1;
05206 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05207 } else {
05208 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05209 p->callwaitcas = 0;
05210 p->cidlen = 2400 + READ_SIZE * 4;
05211 }
05212 p->cidpos = 0;
05213 send_callerid(p);
05214
05215 return 0;
05216 }
05217
05218 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05219 {
05220 struct dahdi_pvt *p = ast->tech_pvt;
05221 int x, res, mysig;
05222 char dest[256];
05223
05224 ast_mutex_lock(&p->lock);
05225 ast_copy_string(dest, rdest, sizeof(dest));
05226 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05227 if ((ast->_state == AST_STATE_BUSY)) {
05228 p->subs[SUB_REAL].needbusy = 1;
05229 ast_mutex_unlock(&p->lock);
05230 return 0;
05231 }
05232 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05233 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05234 ast_mutex_unlock(&p->lock);
05235 return -1;
05236 }
05237 p->waitingfordt.tv_sec = 0;
05238 p->dialednone = 0;
05239 if ((p->radio || (p->oprmode < 0)))
05240 {
05241
05242 ast_setstate(ast, AST_STATE_UP);
05243 ast_mutex_unlock(&p->lock);
05244 return 0;
05245 }
05246 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05247 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05248 if (res)
05249 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05250 p->outgoing = 1;
05251
05252 if (IS_DIGITAL(ast->transfercapability)){
05253 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05254 } else {
05255 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05256 }
05257
05258 #ifdef HAVE_PRI
05259 if (dahdi_sig_pri_lib_handles(p->sig)) {
05260 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05261 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05262 ast_mutex_unlock(&p->lock);
05263 return res;
05264 }
05265 #endif
05266
05267 #if defined(HAVE_SS7)
05268 if (p->sig == SIG_SS7) {
05269 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05270 ast_mutex_unlock(&p->lock);
05271 return res;
05272 }
05273 #endif
05274
05275
05276 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05277 p->callwaitrings = 0;
05278 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05279 ast_mutex_unlock(&p->lock);
05280 return res;
05281 }
05282
05283 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05284 switch (mysig) {
05285 case 0:
05286
05287 ast_setstate(ast, AST_STATE_UP);
05288 break;
05289 case SIG_MFCR2:
05290 break;
05291 default:
05292 ast_debug(1, "not yet implemented\n");
05293 ast_mutex_unlock(&p->lock);
05294 return -1;
05295 }
05296
05297 #ifdef HAVE_OPENR2
05298 if (p->mfcr2) {
05299 openr2_calling_party_category_t chancat;
05300 int callres = 0;
05301 char *c, *l;
05302
05303
05304 p->dialdest[0] = '\0';
05305
05306 c = strchr(dest, '/');
05307 if (c) {
05308 c++;
05309 } else {
05310 c = "";
05311 }
05312 if (!p->hidecallerid) {
05313 l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
05314 } else {
05315 l = NULL;
05316 }
05317 if (strlen(c) < p->stripmsd) {
05318 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05319 ast_mutex_unlock(&p->lock);
05320 return -1;
05321 }
05322 p->dialing = 1;
05323 chancat = dahdi_r2_get_channel_category(ast);
05324 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05325 if (-1 == callres) {
05326 ast_mutex_unlock(&p->lock);
05327 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05328 return -1;
05329 }
05330 p->mfcr2_call_accepted = 0;
05331 p->mfcr2_progress = 0;
05332 ast_setstate(ast, AST_STATE_DIALING);
05333 }
05334 #endif
05335 ast_mutex_unlock(&p->lock);
05336 return 0;
05337 }
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05355 {
05356 struct dahdi_pvt *cur;
05357
05358 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05359
05360
05361 for (cur = iflist; cur; cur = cur->next) {
05362 if (pvt->channel < cur->channel) {
05363
05364 pvt->prev = cur->prev;
05365 pvt->next = cur;
05366 if (cur->prev) {
05367
05368 cur->prev->next = pvt;
05369 } else {
05370
05371 iflist = pvt;
05372 }
05373 cur->prev = pvt;
05374 return;
05375 }
05376 }
05377
05378
05379 pvt->prev = ifend;
05380 pvt->next = NULL;
05381 if (ifend) {
05382 ifend->next = pvt;
05383 }
05384 ifend = pvt;
05385 if (!iflist) {
05386
05387 iflist = pvt;
05388 }
05389 }
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05405 {
05406
05407 if (pvt->prev) {
05408 pvt->prev->next = pvt->next;
05409 } else if (iflist == pvt) {
05410
05411 iflist = pvt->next;
05412 }
05413
05414
05415 if (pvt->next) {
05416 pvt->next->prev = pvt->prev;
05417 } else if (ifend == pvt) {
05418
05419 ifend = pvt->prev;
05420 }
05421
05422
05423 pvt->which_iflist = DAHDI_IFLIST_NONE;
05424 pvt->prev = NULL;
05425 pvt->next = NULL;
05426 }
05427
05428 #if defined(HAVE_PRI)
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05446 {
05447 struct dahdi_pvt *cur;
05448
05449 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05450
05451
05452 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05453 if (pvt->channel < cur->channel) {
05454
05455 pvt->prev = cur->prev;
05456 pvt->next = cur;
05457 if (cur->prev) {
05458
05459 cur->prev->next = pvt;
05460 } else {
05461
05462 pri->no_b_chan_iflist = pvt;
05463 }
05464 cur->prev = pvt;
05465 return;
05466 }
05467 }
05468
05469
05470 pvt->prev = pri->no_b_chan_end;
05471 pvt->next = NULL;
05472 if (pri->no_b_chan_end) {
05473 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05474 }
05475 pri->no_b_chan_end = pvt;
05476 if (!pri->no_b_chan_iflist) {
05477
05478 pri->no_b_chan_iflist = pvt;
05479 }
05480 }
05481 #endif
05482
05483 #if defined(HAVE_PRI)
05484
05485
05486
05487
05488
05489
05490
05491
05492
05493
05494
05495
05496
05497
05498 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05499 {
05500
05501 if (pvt->prev) {
05502 pvt->prev->next = pvt->next;
05503 } else if (pri->no_b_chan_iflist == pvt) {
05504
05505 pri->no_b_chan_iflist = pvt->next;
05506 }
05507
05508
05509 if (pvt->next) {
05510 pvt->next->prev = pvt->prev;
05511 } else if (pri->no_b_chan_end == pvt) {
05512
05513 pri->no_b_chan_end = pvt->prev;
05514 }
05515
05516
05517 pvt->which_iflist = DAHDI_IFLIST_NONE;
05518 pvt->prev = NULL;
05519 pvt->next = NULL;
05520 }
05521 #endif
05522
05523 #if defined(HAVE_PRI)
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05534 {
05535 unsigned idx;
05536 struct sig_pri_span *pri;
05537
05538 pri = pvt->pri;
05539 if (!pri) {
05540
05541 return;
05542 }
05543 ast_mutex_lock(&pri->lock);
05544 for (idx = 0; idx < pri->numchans; ++idx) {
05545 if (pri->pvts[idx] == pvt->sig_pvt) {
05546 pri->pvts[idx] = NULL;
05547 ast_mutex_unlock(&pri->lock);
05548 return;
05549 }
05550 }
05551 ast_mutex_unlock(&pri->lock);
05552 }
05553 #endif
05554
05555 #if defined(HAVE_SS7)
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05566 {
05567 unsigned idx;
05568 struct sig_ss7_linkset *ss7;
05569
05570 ss7 = pvt->ss7;
05571 if (!ss7) {
05572
05573 return;
05574 }
05575 ast_mutex_lock(&ss7->lock);
05576 for (idx = 0; idx < ss7->numchans; ++idx) {
05577 if (ss7->pvts[idx] == pvt->sig_pvt) {
05578 ss7->pvts[idx] = NULL;
05579 ast_mutex_unlock(&ss7->lock);
05580 return;
05581 }
05582 }
05583 ast_mutex_unlock(&ss7->lock);
05584 }
05585 #endif
05586
05587 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05588 {
05589 if (cur->next && cur->next->span == cur->span) {
05590 return cur->next;
05591 } else if (cur->prev && cur->prev->span == cur->span) {
05592 return cur->prev;
05593 }
05594
05595 return NULL;
05596 }
05597
05598 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05599 {
05600 struct dahdi_pvt *p = pvt;
05601
05602 if (p->manages_span_alarms) {
05603 struct dahdi_pvt *next = find_next_iface_in_span(p);
05604 if (next) {
05605 next->manages_span_alarms = 1;
05606 }
05607 }
05608
05609
05610 #if defined(HAVE_PRI)
05611 dahdi_unlink_pri_pvt(p);
05612 #endif
05613 #if defined(HAVE_SS7)
05614 dahdi_unlink_ss7_pvt(p);
05615 #endif
05616 switch (pvt->which_iflist) {
05617 case DAHDI_IFLIST_NONE:
05618 break;
05619 case DAHDI_IFLIST_MAIN:
05620 dahdi_iflist_extract(p);
05621 break;
05622 #if defined(HAVE_PRI)
05623 case DAHDI_IFLIST_NO_B_CHAN:
05624 if (p->pri) {
05625 dahdi_nobch_extract(p->pri, p);
05626 }
05627 break;
05628 #endif
05629 }
05630
05631 if (p->sig_pvt) {
05632 if (analog_lib_handles(p->sig, 0, 0)) {
05633 analog_delete(p->sig_pvt);
05634 }
05635 switch (p->sig) {
05636 #if defined(HAVE_PRI)
05637 case SIG_PRI_LIB_HANDLE_CASES:
05638 sig_pri_chan_delete(p->sig_pvt);
05639 break;
05640 #endif
05641 #if defined(HAVE_SS7)
05642 case SIG_SS7:
05643 sig_ss7_chan_delete(p->sig_pvt);
05644 break;
05645 #endif
05646 default:
05647 break;
05648 }
05649 }
05650 ast_free(p->cidspill);
05651 if (p->use_smdi)
05652 ast_smdi_interface_unref(p->smdi_iface);
05653 if (p->mwi_event_sub)
05654 ast_event_unsubscribe(p->mwi_event_sub);
05655 if (p->vars) {
05656 ast_variables_destroy(p->vars);
05657 }
05658 if (p->cc_params) {
05659 ast_cc_config_params_destroy(p->cc_params);
05660 }
05661 ast_mutex_destroy(&p->lock);
05662 dahdi_close_sub(p, SUB_REAL);
05663 if (p->owner)
05664 p->owner->tech_pvt = NULL;
05665 ast_free(p);
05666 }
05667
05668 static void destroy_channel(struct dahdi_pvt *cur, int now)
05669 {
05670 int i;
05671
05672 if (!now) {
05673
05674 if (cur->owner) {
05675 return;
05676 }
05677 for (i = 0; i < 3; i++) {
05678 if (cur->subs[i].owner) {
05679 return;
05680 }
05681 }
05682 }
05683 destroy_dahdi_pvt(cur);
05684 }
05685
05686 static void destroy_all_channels(void)
05687 {
05688 int chan;
05689 #if defined(HAVE_PRI)
05690 unsigned span;
05691 struct sig_pri_span *pri;
05692 #endif
05693 struct dahdi_pvt *p;
05694
05695 while (num_restart_pending) {
05696 usleep(1);
05697 }
05698
05699 ast_mutex_lock(&iflock);
05700
05701 while (iflist) {
05702 p = iflist;
05703
05704 chan = p->channel;
05705 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05706 {
05707 char db_chan_name[20];
05708 char db_answer[5];
05709 char state;
05710 int why = -1;
05711
05712 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05713 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05714 sscanf(db_answer, "%1c:%30d", &state, &why);
05715 }
05716 if (!why) {
05717
05718 ast_db_del(db_chan_name, SRVST_DBKEY);
05719 }
05720 }
05721 #endif
05722
05723 destroy_dahdi_pvt(p);
05724 ast_verb(3, "Unregistered channel %d\n", chan);
05725 }
05726 ifcount = 0;
05727 ast_mutex_unlock(&iflock);
05728
05729 #if defined(HAVE_PRI)
05730
05731 for (span = 0; span < NUM_SPANS; ++span) {
05732 if (!pris[span].dchannels[0]) {
05733 break;
05734 }
05735 pri = &pris[span].pri;
05736 ast_mutex_lock(&pri->lock);
05737 while (pri->no_b_chan_iflist) {
05738 p = pri->no_b_chan_iflist;
05739
05740
05741 destroy_dahdi_pvt(p);
05742 }
05743 ast_mutex_unlock(&pri->lock);
05744 }
05745 #endif
05746 }
05747
05748 #if defined(HAVE_PRI)
05749 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05750
05751 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05752 {
05753
05754 struct dahdi_pvt *p;
05755
05756 if (ast_strlen_zero(digits)) {
05757 ast_debug(1, "No digit string sent to application!\n");
05758 return -1;
05759 }
05760
05761 p = (struct dahdi_pvt *)chan->tech_pvt;
05762
05763 if (!p) {
05764 ast_debug(1, "Unable to find technology private\n");
05765 return -1;
05766 }
05767
05768 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05769
05770 return 0;
05771 }
05772 #endif
05773
05774 #if defined(HAVE_PRI)
05775 #if defined(HAVE_PRI_PROG_W_CAUSE)
05776 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05777
05778 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05779 {
05780
05781 struct dahdi_pvt *pvt;
05782 char *parse;
05783 int res = -1;
05784 AST_DECLARE_APP_ARGS(args,
05785 AST_APP_ARG(destination);
05786 AST_APP_ARG(original);
05787 AST_APP_ARG(reason);
05788 );
05789
05790 if (ast_strlen_zero(data)) {
05791 ast_log(LOG_DEBUG, "No data sent to application!\n");
05792 return -1;
05793 }
05794 if (chan->tech != &dahdi_tech) {
05795 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05796 return -1;
05797 }
05798 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05799 if (!pvt) {
05800 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05801 return -1;
05802 }
05803 switch (pvt->sig) {
05804 case SIG_PRI_LIB_HANDLE_CASES:
05805 break;
05806 default:
05807 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05808 chan->name);
05809 return -1;
05810 }
05811
05812 parse = ast_strdupa(data);
05813 AST_STANDARD_APP_ARGS(args, parse);
05814
05815 if (ast_strlen_zero(args.destination)) {
05816 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05817 return -1;
05818 }
05819
05820 if (ast_strlen_zero(args.original)) {
05821 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05822 args.original = NULL;
05823 }
05824
05825 if (ast_strlen_zero(args.reason)) {
05826 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05827 args.reason = NULL;
05828 }
05829
05830 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05831 args.original, args.reason);
05832
05833 return res;
05834 }
05835 #endif
05836 #endif
05837
05838 #if defined(HAVE_OPENR2)
05839 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05840
05841 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05842 {
05843
05844 openr2_call_mode_t accept_mode;
05845 int res, timeout, maxloops;
05846 struct ast_frame *f;
05847 struct dahdi_pvt *p;
05848 char *parse;
05849 AST_DECLARE_APP_ARGS(args,
05850 AST_APP_ARG(charge);
05851 );
05852
05853 if (ast_strlen_zero(data)) {
05854 ast_log(LOG_DEBUG, "No data sent to application!\n");
05855 return -1;
05856 }
05857
05858 if (chan->tech != &dahdi_tech) {
05859 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05860 return -1;
05861 }
05862
05863 p = (struct dahdi_pvt *)chan->tech_pvt;
05864 if (!p) {
05865 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05866 return -1;
05867 }
05868
05869 parse = ast_strdupa(data);
05870 AST_STANDARD_APP_ARGS(args, parse);
05871
05872 if (ast_strlen_zero(args.charge)) {
05873 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05874 return -1;
05875 }
05876
05877 ast_mutex_lock(&p->lock);
05878 if (!p->mfcr2 || !p->mfcr2call) {
05879 ast_mutex_unlock(&p->lock);
05880 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05881 return -1;
05882 }
05883
05884 if (p->mfcr2_call_accepted) {
05885 ast_mutex_unlock(&p->lock);
05886 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05887 return 0;
05888 }
05889 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05890 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05891 ast_mutex_unlock(&p->lock);
05892 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05893 return -1;
05894 }
05895 ast_mutex_unlock(&p->lock);
05896
05897 res = 0;
05898 timeout = 100;
05899 maxloops = 50;
05900
05901 while (maxloops > 0) {
05902 maxloops--;
05903 if (ast_check_hangup(chan)) {
05904 break;
05905 }
05906 res = ast_waitfor(chan, timeout);
05907 if (res < 0) {
05908 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05909 res = -1;
05910 break;
05911 }
05912 if (res == 0) {
05913 continue;
05914 }
05915 f = ast_read(chan);
05916 if (!f) {
05917 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05918 res = -1;
05919 break;
05920 }
05921 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05922 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05923 ast_frfree(f);
05924 res = -1;
05925 break;
05926 }
05927 ast_frfree(f);
05928 ast_mutex_lock(&p->lock);
05929 if (p->mfcr2_call_accepted) {
05930 ast_mutex_unlock(&p->lock);
05931 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05932 break;
05933 }
05934 ast_mutex_unlock(&p->lock);
05935 }
05936 if (res == -1) {
05937 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05938 }
05939 return res;
05940 }
05941
05942 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05943 {
05944 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05945 switch (cause) {
05946 case AST_CAUSE_USER_BUSY:
05947 case AST_CAUSE_CALL_REJECTED:
05948 case AST_CAUSE_INTERWORKING:
05949 r2cause = OR2_CAUSE_BUSY_NUMBER;
05950 break;
05951
05952 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05953 case AST_CAUSE_SWITCH_CONGESTION:
05954 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
05955 break;
05956
05957 case AST_CAUSE_UNALLOCATED:
05958 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
05959 break;
05960
05961 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
05962 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
05963 r2cause = OR2_CAUSE_OUT_OF_ORDER;
05964 break;
05965
05966 case AST_CAUSE_NO_ANSWER:
05967 case AST_CAUSE_NO_USER_RESPONSE:
05968 r2cause = OR2_CAUSE_NO_ANSWER;
05969 break;
05970
05971 default:
05972 r2cause = OR2_CAUSE_NORMAL_CLEARING;
05973 break;
05974 }
05975 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
05976 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
05977 return r2cause;
05978 }
05979 #endif
05980
05981 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
05982 {
05983 if (p->bufferoverrideinuse) {
05984
05985 struct dahdi_bufferinfo bi = {
05986 .txbufpolicy = p->buf_policy,
05987 .rxbufpolicy = p->buf_policy,
05988 .bufsize = p->bufsize,
05989 .numbufs = p->buf_no
05990 };
05991 int bpres;
05992
05993 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05994 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
05995 }
05996 p->bufferoverrideinuse = 0;
05997 return bpres;
05998 }
05999
06000 return -1;
06001 }
06002
06003 static int dahdi_hangup(struct ast_channel *ast)
06004 {
06005 int res = 0;
06006 int idx,x;
06007 int law;
06008
06009 struct dahdi_pvt *p = ast->tech_pvt;
06010 struct dahdi_params par;
06011
06012 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
06013 if (!ast->tech_pvt) {
06014 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06015 return 0;
06016 }
06017
06018 ast_mutex_lock(&p->lock);
06019 p->exten[0] = '\0';
06020 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06021 dahdi_confmute(p, 0);
06022 restore_gains(p);
06023 p->ignoredtmf = 0;
06024 p->waitingfordt.tv_sec = 0;
06025
06026 res = analog_hangup(p->sig_pvt, ast);
06027 revert_fax_buffers(p, ast);
06028
06029 goto hangup_out;
06030 } else {
06031 p->cid_num[0] = '\0';
06032 p->cid_name[0] = '\0';
06033 p->cid_subaddr[0] = '\0';
06034 }
06035
06036 #ifdef HAVE_PRI
06037 if (dahdi_sig_pri_lib_handles(p->sig)) {
06038 x = 1;
06039 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06040 dahdi_confmute(p, 0);
06041 p->muting = 0;
06042 restore_gains(p);
06043 if (p->dsp) {
06044 ast_dsp_free(p->dsp);
06045 p->dsp = NULL;
06046 }
06047 p->ignoredtmf = 0;
06048 revert_fax_buffers(p, ast);
06049 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06050 p->law = p->law_default;
06051 law = p->law_default;
06052 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06053 dahdi_disable_ec(p);
06054 update_conf(p);
06055 reset_conf(p);
06056 sig_pri_hangup(p->sig_pvt, ast);
06057 p->subs[SUB_REAL].owner = NULL;
06058 p->subs[SUB_REAL].needbusy = 0;
06059 p->owner = NULL;
06060 p->cid_tag[0] = '\0';
06061 p->ringt = 0;
06062 p->distinctivering = 0;
06063 p->confirmanswer = 0;
06064 p->outgoing = 0;
06065 p->digital = 0;
06066 p->faxhandled = 0;
06067 p->pulsedial = 0;
06068 goto hangup_out;
06069 }
06070 #endif
06071
06072 #if defined(HAVE_SS7)
06073 if (p->sig == SIG_SS7) {
06074 x = 1;
06075 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06076
06077 dahdi_confmute(p, 0);
06078 p->muting = 0;
06079 restore_gains(p);
06080 if (p->dsp) {
06081 ast_dsp_free(p->dsp);
06082 p->dsp = NULL;
06083 }
06084 p->ignoredtmf = 0;
06085
06086
06087 p->subs[SUB_REAL].owner = NULL;
06088 p->subs[SUB_REAL].needbusy = 0;
06089 p->polarity = POLARITY_IDLE;
06090 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06091
06092 p->owner = NULL;
06093 p->ringt = 0;
06094 p->distinctivering = 0;
06095 p->confirmanswer = 0;
06096 p->outgoing = 0;
06097 p->digital = 0;
06098 p->faxhandled = 0;
06099 p->pulsedial = 0;
06100
06101 revert_fax_buffers(p, ast);
06102
06103 p->law = p->law_default;
06104 law = p->law_default;
06105 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06106 if (res < 0)
06107 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06108
06109 sig_ss7_hangup(p->sig_pvt, ast);
06110
06111 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06112 dahdi_disable_ec(p);
06113 x = 0;
06114 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06115 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06116 p->didtdd = 0;
06117 update_conf(p);
06118 reset_conf(p);
06119
06120
06121 x = 0;
06122 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06123
06124 if (num_restart_pending == 0)
06125 restart_monitor();
06126
06127 ast->tech_pvt = NULL;
06128 goto hangup_out;
06129 }
06130 #endif
06131
06132 idx = dahdi_get_index(ast, p, 1);
06133
06134 dahdi_confmute(p, 0);
06135 p->muting = 0;
06136 restore_gains(p);
06137 if (p->origcid_num) {
06138 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06139 ast_free(p->origcid_num);
06140 p->origcid_num = NULL;
06141 }
06142 if (p->origcid_name) {
06143 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06144 ast_free(p->origcid_name);
06145 p->origcid_name = NULL;
06146 }
06147 if (p->dsp)
06148 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06149
06150 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06151 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06152 p->ignoredtmf = 0;
06153
06154 if (idx > -1) {
06155
06156 p->subs[idx].owner = NULL;
06157 p->subs[idx].needanswer = 0;
06158 p->subs[idx].needflash = 0;
06159 p->subs[idx].needringing = 0;
06160 p->subs[idx].needbusy = 0;
06161 p->subs[idx].needcongestion = 0;
06162 p->subs[idx].linear = 0;
06163 p->polarity = POLARITY_IDLE;
06164 dahdi_setlinear(p->subs[idx].dfd, 0);
06165 if (idx == SUB_REAL) {
06166 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06167 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06168 if (p->subs[SUB_CALLWAIT].inthreeway) {
06169
06170 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06171
06172 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06173 unalloc_sub(p, SUB_CALLWAIT);
06174 p->owner = NULL;
06175 } else {
06176
06177 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06178 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06179 unalloc_sub(p, SUB_THREEWAY);
06180 if (p->subs[SUB_REAL].inthreeway) {
06181
06182
06183 ast_debug(1, "Call was complete, setting owner to former third call\n");
06184 p->owner = p->subs[SUB_REAL].owner;
06185 } else {
06186
06187 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06188 p->owner = NULL;
06189 }
06190 p->subs[SUB_REAL].inthreeway = 0;
06191 }
06192 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06193
06194 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06195 unalloc_sub(p, SUB_CALLWAIT);
06196 p->owner = p->subs[SUB_REAL].owner;
06197 if (p->owner->_state != AST_STATE_UP)
06198 p->subs[SUB_REAL].needanswer = 1;
06199 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06200 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06201 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06202 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06203 unalloc_sub(p, SUB_THREEWAY);
06204 if (p->subs[SUB_REAL].inthreeway) {
06205
06206
06207 ast_debug(1, "Call was complete, setting owner to former third call\n");
06208 p->owner = p->subs[SUB_REAL].owner;
06209 } else {
06210
06211 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06212 p->owner = NULL;
06213 }
06214 p->subs[SUB_REAL].inthreeway = 0;
06215 }
06216 } else if (idx == SUB_CALLWAIT) {
06217
06218 if (p->subs[SUB_CALLWAIT].inthreeway) {
06219
06220
06221 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06222 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06223 S_OR(p->mohsuggest, NULL),
06224 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06225 }
06226 p->subs[SUB_THREEWAY].inthreeway = 0;
06227
06228 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06229 unalloc_sub(p, SUB_THREEWAY);
06230 } else
06231 unalloc_sub(p, SUB_CALLWAIT);
06232 } else if (idx == SUB_THREEWAY) {
06233 if (p->subs[SUB_CALLWAIT].inthreeway) {
06234
06235
06236 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06237 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06238 S_OR(p->mohsuggest, NULL),
06239 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06240 }
06241 p->subs[SUB_CALLWAIT].inthreeway = 0;
06242 }
06243 p->subs[SUB_REAL].inthreeway = 0;
06244
06245
06246 unalloc_sub(p, SUB_THREEWAY);
06247 } else {
06248
06249 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06250 }
06251 }
06252
06253 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06254 p->owner = NULL;
06255 p->ringt = 0;
06256 p->distinctivering = 0;
06257 p->confirmanswer = 0;
06258 p->outgoing = 0;
06259 p->digital = 0;
06260 p->faxhandled = 0;
06261 p->pulsedial = 0;
06262 if (p->dsp) {
06263 ast_dsp_free(p->dsp);
06264 p->dsp = NULL;
06265 }
06266
06267 revert_fax_buffers(p, ast);
06268
06269 p->law = p->law_default;
06270 law = p->law_default;
06271 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06272 if (res < 0)
06273 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06274
06275 #ifdef HAVE_OPENR2
06276 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06277 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06278
06279 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06280 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06281 } else {
06282 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06283 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06284 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06285 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06286 dahdi_r2_disconnect_call(p, r2cause);
06287 }
06288 } else if (p->mfcr2call) {
06289 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06290
06291
06292
06293
06294 p->mfcr2call = 0;
06295 }
06296 #endif
06297 switch (p->sig) {
06298 case SIG_SS7:
06299 case SIG_MFCR2:
06300 case SIG_PRI_LIB_HANDLE_CASES:
06301 case 0:
06302 break;
06303 default:
06304 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06305 break;
06306 }
06307 if (res < 0) {
06308 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06309 }
06310 switch (p->sig) {
06311 case SIG_FXOGS:
06312 case SIG_FXOLS:
06313 case SIG_FXOKS:
06314 memset(&par, 0, sizeof(par));
06315 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06316 if (!res) {
06317 struct analog_pvt *analog_p = p->sig_pvt;
06318 #if 0
06319 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06320 #endif
06321
06322 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06323 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06324 else
06325 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06326 analog_p->fxsoffhookstate = par.rxisoffhook;
06327 }
06328 break;
06329 case SIG_FXSGS:
06330 case SIG_FXSLS:
06331 case SIG_FXSKS:
06332
06333
06334 if (ast->_state != AST_STATE_RESERVED) {
06335 time(&p->guardtime);
06336 p->guardtime += 2;
06337 }
06338 break;
06339 default:
06340 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06341 }
06342 if (p->sig)
06343 dahdi_disable_ec(p);
06344 x = 0;
06345 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06346 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06347 p->didtdd = 0;
06348 p->callwaitcas = 0;
06349 p->callwaiting = p->permcallwaiting;
06350 p->hidecallerid = p->permhidecallerid;
06351 p->waitingfordt.tv_sec = 0;
06352 p->dialing = 0;
06353 p->rdnis[0] = '\0';
06354 update_conf(p);
06355 reset_conf(p);
06356
06357 switch (p->sig) {
06358 case SIG_PRI_LIB_HANDLE_CASES:
06359 case SIG_SS7:
06360 x = 0;
06361 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06362 break;
06363 default:
06364 break;
06365 }
06366 if (num_restart_pending == 0)
06367 restart_monitor();
06368 }
06369
06370 p->callwaitingrepeat = 0;
06371 p->cidcwexpire = 0;
06372 p->cid_suppress_expire = 0;
06373 p->oprmode = 0;
06374 ast->tech_pvt = NULL;
06375 hangup_out:
06376 ast_free(p->cidspill);
06377 p->cidspill = NULL;
06378
06379 ast_mutex_unlock(&p->lock);
06380 ast_module_unref(ast_module_info->self);
06381 ast_verb(3, "Hungup '%s'\n", ast->name);
06382
06383 ast_mutex_lock(&iflock);
06384
06385 if (p->restartpending) {
06386 num_restart_pending--;
06387 }
06388
06389 if (p->destroy) {
06390 destroy_channel(p, 0);
06391 }
06392 ast_mutex_unlock(&iflock);
06393 return 0;
06394 }
06395
06396 static int dahdi_answer(struct ast_channel *ast)
06397 {
06398 struct dahdi_pvt *p = ast->tech_pvt;
06399 int res = 0;
06400 int idx;
06401 ast_setstate(ast, AST_STATE_UP);
06402 ast_mutex_lock(&p->lock);
06403 idx = dahdi_get_index(ast, p, 0);
06404 if (idx < 0)
06405 idx = SUB_REAL;
06406
06407 if ((p->radio || (p->oprmode < 0))) {
06408 ast_mutex_unlock(&p->lock);
06409 return 0;
06410 }
06411
06412 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06413 res = analog_answer(p->sig_pvt, ast);
06414 ast_mutex_unlock(&p->lock);
06415 return res;
06416 }
06417
06418 switch (p->sig) {
06419 #if defined(HAVE_PRI)
06420 case SIG_PRI_LIB_HANDLE_CASES:
06421 res = sig_pri_answer(p->sig_pvt, ast);
06422 break;
06423 #endif
06424 #if defined(HAVE_SS7)
06425 case SIG_SS7:
06426 res = sig_ss7_answer(p->sig_pvt, ast);
06427 break;
06428 #endif
06429 #ifdef HAVE_OPENR2
06430 case SIG_MFCR2:
06431 if (!p->mfcr2_call_accepted) {
06432
06433
06434 p->mfcr2_answer_pending = 1;
06435 if (p->mfcr2_charge_calls) {
06436 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06437 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06438 } else {
06439 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06440 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06441 }
06442 } else {
06443 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06444 dahdi_r2_answer(p);
06445 }
06446 break;
06447 #endif
06448 case 0:
06449 ast_mutex_unlock(&p->lock);
06450 return 0;
06451 default:
06452 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06453 res = -1;
06454 break;
06455 }
06456 ast_mutex_unlock(&p->lock);
06457 return res;
06458 }
06459
06460 static void disable_dtmf_detect(struct dahdi_pvt *p)
06461 {
06462 int val = 0;
06463
06464 p->ignoredtmf = 1;
06465
06466 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06467
06468 if (!p->hardwaredtmf && p->dsp) {
06469 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06470 ast_dsp_set_features(p->dsp, p->dsp_features);
06471 }
06472 }
06473
06474 static void enable_dtmf_detect(struct dahdi_pvt *p)
06475 {
06476 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06477
06478 if (p->channel == CHAN_PSEUDO)
06479 return;
06480
06481 p->ignoredtmf = 0;
06482
06483 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06484
06485 if (!p->hardwaredtmf && p->dsp) {
06486 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06487 ast_dsp_set_features(p->dsp, p->dsp_features);
06488 }
06489 }
06490
06491 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06492 {
06493 char *cp;
06494 struct dahdi_pvt *p = chan->tech_pvt;
06495
06496
06497 if (!data || (*datalen < 1)) {
06498 errno = EINVAL;
06499 return -1;
06500 }
06501
06502 switch (option) {
06503 case AST_OPTION_DIGIT_DETECT:
06504 cp = (char *) data;
06505 *cp = p->ignoredtmf ? 0 : 1;
06506 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06507 break;
06508 case AST_OPTION_FAX_DETECT:
06509 cp = (char *) data;
06510 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06511 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06512 break;
06513 case AST_OPTION_CC_AGENT_TYPE:
06514 #if defined(HAVE_PRI)
06515 #if defined(HAVE_PRI_CCSS)
06516 if (dahdi_sig_pri_lib_handles(p->sig)) {
06517 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06518 break;
06519 }
06520 #endif
06521 #endif
06522 return -1;
06523 default:
06524 return -1;
06525 }
06526
06527 errno = 0;
06528
06529 return 0;
06530 }
06531
06532 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06533 {
06534 char *cp;
06535 signed char *scp;
06536 int x;
06537 int idx;
06538 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06539 struct oprmode *oprmode;
06540
06541
06542
06543 if (!data || (datalen < 1)) {
06544 errno = EINVAL;
06545 return -1;
06546 }
06547
06548 switch (option) {
06549 case AST_OPTION_TXGAIN:
06550 scp = (signed char *) data;
06551 idx = dahdi_get_index(chan, p, 0);
06552 if (idx < 0) {
06553 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06554 return -1;
06555 }
06556 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06557 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06558 case AST_OPTION_RXGAIN:
06559 scp = (signed char *) data;
06560 idx = dahdi_get_index(chan, p, 0);
06561 if (idx < 0) {
06562 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06563 return -1;
06564 }
06565 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06566 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06567 case AST_OPTION_TONE_VERIFY:
06568 if (!p->dsp)
06569 break;
06570 cp = (char *) data;
06571 switch (*cp) {
06572 case 1:
06573 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06574 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06575 break;
06576 case 2:
06577 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06578 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06579 break;
06580 default:
06581 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06582 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06583 break;
06584 }
06585 break;
06586 case AST_OPTION_TDD:
06587
06588 cp = (char *) data;
06589 p->mate = 0;
06590 if (!*cp) {
06591 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06592 if (p->tdd)
06593 tdd_free(p->tdd);
06594 p->tdd = 0;
06595 break;
06596 }
06597 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06598 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06599 dahdi_disable_ec(p);
06600
06601 if (!p->didtdd) {
06602 unsigned char mybuf[41000];
06603 unsigned char *buf;
06604 int size, res, fd, len;
06605 struct pollfd fds[1];
06606
06607 buf = mybuf;
06608 memset(buf, 0x7f, sizeof(mybuf));
06609 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06610 len = 40000;
06611 idx = dahdi_get_index(chan, p, 0);
06612 if (idx < 0) {
06613 ast_log(LOG_WARNING, "No index in TDD?\n");
06614 return -1;
06615 }
06616 fd = p->subs[idx].dfd;
06617 while (len) {
06618 if (ast_check_hangup(chan))
06619 return -1;
06620 size = len;
06621 if (size > READ_SIZE)
06622 size = READ_SIZE;
06623 fds[0].fd = fd;
06624 fds[0].events = POLLPRI | POLLOUT;
06625 fds[0].revents = 0;
06626 res = poll(fds, 1, -1);
06627 if (!res) {
06628 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06629 continue;
06630 }
06631
06632 if (fds[0].revents & POLLPRI)
06633 return -1;
06634 if (!(fds[0].revents & POLLOUT)) {
06635 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06636 continue;
06637 }
06638 res = write(fd, buf, size);
06639 if (res != size) {
06640 if (res == -1) return -1;
06641 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06642 break;
06643 }
06644 len -= size;
06645 buf += size;
06646 }
06647 p->didtdd = 1;
06648 }
06649 if (*cp == 2) {
06650 if (p->tdd)
06651 tdd_free(p->tdd);
06652 p->tdd = 0;
06653 p->mate = 1;
06654 break;
06655 }
06656 if (!p->tdd) {
06657 p->tdd = tdd_new();
06658 }
06659 break;
06660 case AST_OPTION_RELAXDTMF:
06661 if (!p->dsp)
06662 break;
06663 cp = (char *) data;
06664 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06665 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06666 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06667 break;
06668 case AST_OPTION_AUDIO_MODE:
06669 #if defined(HAVE_PRI)
06670 if (dahdi_sig_pri_lib_handles(p->sig)
06671 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06672
06673 break;
06674 }
06675 #endif
06676
06677 cp = (char *) data;
06678 if (!*cp) {
06679 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06680 x = 0;
06681 dahdi_disable_ec(p);
06682 } else {
06683 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06684 x = 1;
06685 }
06686 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06687 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06688 break;
06689 case AST_OPTION_OPRMODE:
06690 oprmode = (struct oprmode *) data;
06691
06692 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06693 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06694 chan->tech->type, oprmode->peer->tech->type);
06695 errno = EINVAL;
06696 return -1;
06697 }
06698 pp = oprmode->peer->tech_pvt;
06699 p->oprmode = pp->oprmode = 0;
06700
06701 p->oprpeer = pp;
06702 pp->oprpeer = p;
06703
06704 if (oprmode->mode)
06705 {
06706 pp->oprmode = oprmode->mode;
06707 p->oprmode = -oprmode->mode;
06708 }
06709 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06710 oprmode->mode, chan->name,oprmode->peer->name);
06711 break;
06712 case AST_OPTION_ECHOCAN:
06713 cp = (char *) data;
06714 if (*cp) {
06715 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06716 dahdi_enable_ec(p);
06717 } else {
06718 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06719 dahdi_disable_ec(p);
06720 }
06721 break;
06722 case AST_OPTION_DIGIT_DETECT:
06723 cp = (char *) data;
06724 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06725 if (*cp) {
06726 enable_dtmf_detect(p);
06727 } else {
06728 disable_dtmf_detect(p);
06729 }
06730 break;
06731 case AST_OPTION_FAX_DETECT:
06732 cp = (char *) data;
06733 if (p->dsp) {
06734 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06735 if (*cp) {
06736 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06737 } else {
06738 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06739 }
06740 ast_dsp_set_features(p->dsp, p->dsp_features);
06741 }
06742 break;
06743 default:
06744 return -1;
06745 }
06746 errno = 0;
06747
06748 return 0;
06749 }
06750
06751 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06752 {
06753 struct dahdi_pvt *p = chan->tech_pvt;
06754 int res = 0;
06755
06756 if (!strcasecmp(data, "rxgain")) {
06757 ast_mutex_lock(&p->lock);
06758 snprintf(buf, len, "%f", p->rxgain);
06759 ast_mutex_unlock(&p->lock);
06760 } else if (!strcasecmp(data, "txgain")) {
06761 ast_mutex_lock(&p->lock);
06762 snprintf(buf, len, "%f", p->txgain);
06763 ast_mutex_unlock(&p->lock);
06764 #if defined(HAVE_PRI)
06765 #if defined(HAVE_PRI_REVERSE_CHARGE)
06766 } else if (!strcasecmp(data, "reversecharge")) {
06767 ast_mutex_lock(&p->lock);
06768 switch (p->sig) {
06769 case SIG_PRI_LIB_HANDLE_CASES:
06770 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06771 break;
06772 default:
06773 *buf = '\0';
06774 res = -1;
06775 break;
06776 }
06777 ast_mutex_unlock(&p->lock);
06778 #endif
06779 #if defined(HAVE_PRI_SETUP_KEYPAD)
06780 } else if (!strcasecmp(data, "keypad_digits")) {
06781 ast_mutex_lock(&p->lock);
06782 switch (p->sig) {
06783 case SIG_PRI_LIB_HANDLE_CASES:
06784 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06785 len);
06786 break;
06787 default:
06788 *buf = '\0';
06789 res = -1;
06790 break;
06791 }
06792 ast_mutex_unlock(&p->lock);
06793 #endif
06794 } else if (!strcasecmp(data, "no_media_path")) {
06795 ast_mutex_lock(&p->lock);
06796 switch (p->sig) {
06797 case SIG_PRI_LIB_HANDLE_CASES:
06798
06799
06800
06801
06802 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06803 break;
06804 default:
06805 *buf = '\0';
06806 res = -1;
06807 break;
06808 }
06809 ast_mutex_unlock(&p->lock);
06810 #endif
06811 } else {
06812 *buf = '\0';
06813 res = -1;
06814 }
06815
06816 return res;
06817 }
06818
06819
06820 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06821 {
06822 int res;
06823 char policy_str[21] = "";
06824
06825 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06826 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06827 return 1;
06828 }
06829 if (*num_buffers < 0) {
06830 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06831 return -1;
06832 }
06833 if (!strcasecmp(policy_str, "full")) {
06834 *policy = DAHDI_POLICY_WHEN_FULL;
06835 } else if (!strcasecmp(policy_str, "immediate")) {
06836 *policy = DAHDI_POLICY_IMMEDIATE;
06837 #if defined(HAVE_DAHDI_HALF_FULL)
06838 } else if (!strcasecmp(policy_str, "half")) {
06839 *policy = DAHDI_POLICY_HALF_FULL;
06840 #endif
06841 } else {
06842 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06843 return -1;
06844 }
06845
06846 return 0;
06847 }
06848
06849 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06850 {
06851 struct dahdi_pvt *p = chan->tech_pvt;
06852 int res = 0;
06853
06854 if (!strcasecmp(data, "buffers")) {
06855 int num_bufs, policy;
06856
06857 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06858 struct dahdi_bufferinfo bi = {
06859 .txbufpolicy = policy,
06860 .rxbufpolicy = policy,
06861 .bufsize = p->bufsize,
06862 .numbufs = num_bufs,
06863 };
06864 int bpres;
06865
06866 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06867 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06868 } else {
06869 p->bufferoverrideinuse = 1;
06870 }
06871 } else {
06872 res = -1;
06873 }
06874 } else if (!strcasecmp(data, "echocan_mode")) {
06875 if (!strcasecmp(value, "on")) {
06876 ast_mutex_lock(&p->lock);
06877 dahdi_enable_ec(p);
06878 ast_mutex_unlock(&p->lock);
06879 } else if (!strcasecmp(value, "off")) {
06880 ast_mutex_lock(&p->lock);
06881 dahdi_disable_ec(p);
06882 ast_mutex_unlock(&p->lock);
06883 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06884 } else if (!strcasecmp(value, "fax")) {
06885 int blah = 1;
06886
06887 ast_mutex_lock(&p->lock);
06888 if (!p->echocanon) {
06889 dahdi_enable_ec(p);
06890 }
06891 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06892 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06893 }
06894 ast_mutex_unlock(&p->lock);
06895 } else if (!strcasecmp(value, "voice")) {
06896 int blah = 0;
06897
06898 ast_mutex_lock(&p->lock);
06899 if (!p->echocanon) {
06900 dahdi_enable_ec(p);
06901 }
06902 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06903 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06904 }
06905 ast_mutex_unlock(&p->lock);
06906 #endif
06907 } else {
06908 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06909 res = -1;
06910 }
06911 } else {
06912 res = -1;
06913 }
06914
06915 return res;
06916 }
06917
06918 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
06919 {
06920
06921 int x;
06922 int hasslaves;
06923 if (!master)
06924 return;
06925 if (needlock) {
06926 ast_mutex_lock(&master->lock);
06927 if (slave) {
06928 while (ast_mutex_trylock(&slave->lock)) {
06929 DEADLOCK_AVOIDANCE(&master->lock);
06930 }
06931 }
06932 }
06933 hasslaves = 0;
06934 for (x = 0; x < MAX_SLAVES; x++) {
06935 if (master->slaves[x]) {
06936 if (!slave || (master->slaves[x] == slave)) {
06937
06938 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
06939 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
06940 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
06941 master->slaves[x]->master = NULL;
06942 master->slaves[x] = NULL;
06943 } else
06944 hasslaves = 1;
06945 }
06946 if (!hasslaves)
06947 master->inconference = 0;
06948 }
06949 if (!slave) {
06950 if (master->master) {
06951
06952 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
06953 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
06954 hasslaves = 0;
06955 for (x = 0; x < MAX_SLAVES; x++) {
06956 if (master->master->slaves[x] == master)
06957 master->master->slaves[x] = NULL;
06958 else if (master->master->slaves[x])
06959 hasslaves = 1;
06960 }
06961 if (!hasslaves)
06962 master->master->inconference = 0;
06963 }
06964 master->master = NULL;
06965 }
06966 update_conf(master);
06967 if (needlock) {
06968 if (slave)
06969 ast_mutex_unlock(&slave->lock);
06970 ast_mutex_unlock(&master->lock);
06971 }
06972 }
06973
06974 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
06975 int x;
06976 if (!slave || !master) {
06977 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
06978 return;
06979 }
06980 for (x = 0; x < MAX_SLAVES; x++) {
06981 if (!master->slaves[x]) {
06982 master->slaves[x] = slave;
06983 break;
06984 }
06985 }
06986 if (x >= MAX_SLAVES) {
06987 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
06988 master->slaves[MAX_SLAVES - 1] = slave;
06989 }
06990 if (slave->master)
06991 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
06992 slave->master = master;
06993
06994 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
06995 }
06996
06997 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)
06998 {
06999 struct ast_channel *who;
07000 struct dahdi_pvt *p0, *p1, *op0, *op1;
07001 struct dahdi_pvt *master = NULL, *slave = NULL;
07002 struct ast_frame *f;
07003 int inconf = 0;
07004 int nothingok = 1;
07005 int ofd0, ofd1;
07006 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
07007 int os0 = -1, os1 = -1;
07008 int priority = 0;
07009 struct ast_channel *oc0, *oc1;
07010 enum ast_bridge_result res;
07011 #ifdef PRI_2BCT
07012 int triedtopribridge = 0;
07013 q931_call *q931c0;
07014 q931_call *q931c1;
07015 #endif
07016
07017
07018
07019
07020
07021
07022 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07023 return AST_BRIDGE_FAILED_NOWARN;
07024
07025 ast_channel_lock(c0);
07026 while (ast_channel_trylock(c1)) {
07027 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07028 }
07029
07030 p0 = c0->tech_pvt;
07031 p1 = c1->tech_pvt;
07032
07033 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07034 ast_channel_unlock(c0);
07035 ast_channel_unlock(c1);
07036 return AST_BRIDGE_FAILED_NOWARN;
07037 }
07038
07039 oi0 = dahdi_get_index(c0, p0, 0);
07040 oi1 = dahdi_get_index(c1, p1, 0);
07041 if ((oi0 < 0) || (oi1 < 0)) {
07042 ast_channel_unlock(c0);
07043 ast_channel_unlock(c1);
07044 return AST_BRIDGE_FAILED;
07045 }
07046
07047 op0 = p0 = c0->tech_pvt;
07048 op1 = p1 = c1->tech_pvt;
07049 ofd0 = c0->fds[0];
07050 ofd1 = c1->fds[0];
07051 oc0 = p0->owner;
07052 oc1 = p1->owner;
07053
07054 if (ast_mutex_trylock(&p0->lock)) {
07055
07056 ast_channel_unlock(c0);
07057 ast_channel_unlock(c1);
07058 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07059 return AST_BRIDGE_RETRY;
07060 }
07061 if (ast_mutex_trylock(&p1->lock)) {
07062
07063 ast_mutex_unlock(&p0->lock);
07064 ast_channel_unlock(c0);
07065 ast_channel_unlock(c1);
07066 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07067 return AST_BRIDGE_RETRY;
07068 }
07069
07070 if ((p0->callwaiting && p0->callwaitingcallerid)
07071 || (p1->callwaiting && p1->callwaitingcallerid)) {
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081 ast_mutex_unlock(&p0->lock);
07082 ast_mutex_unlock(&p1->lock);
07083 ast_channel_unlock(c0);
07084 ast_channel_unlock(c1);
07085 return AST_BRIDGE_FAILED_NOWARN;
07086 }
07087
07088 #if defined(HAVE_PRI)
07089 if ((dahdi_sig_pri_lib_handles(p0->sig)
07090 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07091 || (dahdi_sig_pri_lib_handles(p1->sig)
07092 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07093
07094
07095
07096
07097 ast_mutex_unlock(&p0->lock);
07098 ast_mutex_unlock(&p1->lock);
07099 ast_channel_unlock(c0);
07100 ast_channel_unlock(c1);
07101 return AST_BRIDGE_FAILED_NOWARN;
07102 }
07103 #endif
07104
07105 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07106 if (p0->owner && p1->owner) {
07107
07108 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07109 master = p0;
07110 slave = p1;
07111 inconf = 1;
07112 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07113 master = p1;
07114 slave = p0;
07115 inconf = 1;
07116 } else {
07117 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07118 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07119 p0->channel,
07120 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07121 p0->subs[SUB_REAL].inthreeway, p0->channel,
07122 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07123 p1->subs[SUB_REAL].inthreeway);
07124 }
07125 nothingok = 0;
07126 }
07127 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07128 if (p1->subs[SUB_THREEWAY].inthreeway) {
07129 master = p1;
07130 slave = p0;
07131 nothingok = 0;
07132 }
07133 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07134 if (p0->subs[SUB_THREEWAY].inthreeway) {
07135 master = p0;
07136 slave = p1;
07137 nothingok = 0;
07138 }
07139 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07140
07141
07142 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07143 master = p1;
07144 slave = p0;
07145 nothingok = 0;
07146 }
07147 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07148
07149 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07150 master = p0;
07151 slave = p1;
07152 nothingok = 0;
07153 }
07154 }
07155 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07156 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07157 if (master && slave) {
07158
07159
07160
07161 if ((oi1 == SUB_THREEWAY) &&
07162 p1->subs[SUB_THREEWAY].inthreeway &&
07163 p1->subs[SUB_REAL].owner &&
07164 p1->subs[SUB_REAL].inthreeway &&
07165 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07166 ast_debug(1,
07167 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07168 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07169 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07170 os1 = p1->subs[SUB_REAL].owner->_state;
07171 } else {
07172 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07173 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07174 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07175 }
07176 if ((oi0 == SUB_THREEWAY) &&
07177 p0->subs[SUB_THREEWAY].inthreeway &&
07178 p0->subs[SUB_REAL].owner &&
07179 p0->subs[SUB_REAL].inthreeway &&
07180 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07181 ast_debug(1,
07182 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07183 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07184 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07185 os0 = p0->subs[SUB_REAL].owner->_state;
07186 } else {
07187 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07188 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07189 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07190 }
07191 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07192 if (!p0->echocanbridged || !p1->echocanbridged) {
07193
07194 dahdi_disable_ec(p0);
07195 dahdi_disable_ec(p1);
07196 }
07197 }
07198 dahdi_link(slave, master);
07199 master->inconference = inconf;
07200 } else if (!nothingok)
07201 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07202
07203 update_conf(p0);
07204 update_conf(p1);
07205 t0 = p0->subs[SUB_REAL].inthreeway;
07206 t1 = p1->subs[SUB_REAL].inthreeway;
07207
07208 ast_mutex_unlock(&p0->lock);
07209 ast_mutex_unlock(&p1->lock);
07210
07211 ast_channel_unlock(c0);
07212 ast_channel_unlock(c1);
07213
07214
07215 if ((!master || !slave) && !nothingok) {
07216 dahdi_enable_ec(p0);
07217 dahdi_enable_ec(p1);
07218 return AST_BRIDGE_FAILED;
07219 }
07220
07221 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07222
07223 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07224 disable_dtmf_detect(op0);
07225
07226 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07227 disable_dtmf_detect(op1);
07228
07229 for (;;) {
07230 struct ast_channel *c0_priority[2] = {c0, c1};
07231 struct ast_channel *c1_priority[2] = {c1, c0};
07232
07233
07234
07235
07236 ast_channel_lock(c0);
07237 while (ast_channel_trylock(c1)) {
07238 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07239 }
07240
07241 p0 = c0->tech_pvt;
07242 p1 = c1->tech_pvt;
07243
07244 if (op0 == p0)
07245 i0 = dahdi_get_index(c0, p0, 1);
07246 if (op1 == p1)
07247 i1 = dahdi_get_index(c1, p1, 1);
07248
07249 ast_channel_unlock(c0);
07250 ast_channel_unlock(c1);
07251
07252 if (!timeoutms ||
07253 (op0 != p0) ||
07254 (op1 != p1) ||
07255 (ofd0 != c0->fds[0]) ||
07256 (ofd1 != c1->fds[0]) ||
07257 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07258 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07259 (oc0 != p0->owner) ||
07260 (oc1 != p1->owner) ||
07261 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07262 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07263 (oi0 != i0) ||
07264 (oi1 != i1)) {
07265 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07266 op0->channel, oi0, op1->channel, oi1);
07267 res = AST_BRIDGE_RETRY;
07268 goto return_from_bridge;
07269 }
07270
07271 #ifdef PRI_2BCT
07272 if (!triedtopribridge) {
07273 triedtopribridge = 1;
07274 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07275 ast_mutex_lock(&p0->pri->lock);
07276 switch (p0->sig) {
07277 case SIG_PRI_LIB_HANDLE_CASES:
07278 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07279 break;
07280 default:
07281 q931c0 = NULL;
07282 break;
07283 }
07284 switch (p1->sig) {
07285 case SIG_PRI_LIB_HANDLE_CASES:
07286 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07287 break;
07288 default:
07289 q931c1 = NULL;
07290 break;
07291 }
07292 if (q931c0 && q931c1) {
07293 pri_channel_bridge(q931c0, q931c1);
07294 }
07295 ast_mutex_unlock(&p0->pri->lock);
07296 }
07297 }
07298 #endif
07299
07300 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07301 if (!who) {
07302 ast_debug(1, "Ooh, empty read...\n");
07303 continue;
07304 }
07305 f = ast_read(who);
07306 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07307 *fo = f;
07308 *rc = who;
07309 res = AST_BRIDGE_COMPLETE;
07310 goto return_from_bridge;
07311 }
07312 if (f->frametype == AST_FRAME_DTMF) {
07313 if ((who == c0) && p0->pulsedial) {
07314 ast_write(c1, f);
07315 } else if ((who == c1) && p1->pulsedial) {
07316 ast_write(c0, f);
07317 } else {
07318 *fo = f;
07319 *rc = who;
07320 res = AST_BRIDGE_COMPLETE;
07321 goto return_from_bridge;
07322 }
07323 }
07324 ast_frfree(f);
07325
07326
07327 priority = !priority;
07328 }
07329
07330 return_from_bridge:
07331 if (op0 == p0)
07332 dahdi_enable_ec(p0);
07333
07334 if (op1 == p1)
07335 dahdi_enable_ec(p1);
07336
07337 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07338 enable_dtmf_detect(op0);
07339
07340 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07341 enable_dtmf_detect(op1);
07342
07343 dahdi_unlink(slave, master, 1);
07344
07345 return res;
07346 }
07347
07348 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07349 {
07350 struct dahdi_pvt *p = newchan->tech_pvt;
07351 int x;
07352
07353 ast_mutex_lock(&p->lock);
07354
07355 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07356 if (p->owner == oldchan) {
07357 p->owner = newchan;
07358 }
07359 for (x = 0; x < 3; x++) {
07360 if (p->subs[x].owner == oldchan) {
07361 if (!x) {
07362 dahdi_unlink(NULL, p, 0);
07363 }
07364 p->subs[x].owner = newchan;
07365 }
07366 }
07367 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07368 analog_fixup(oldchan, newchan, p->sig_pvt);
07369 #if defined(HAVE_PRI)
07370 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07371 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07372 #endif
07373 #if defined(HAVE_SS7)
07374 } else if (p->sig == SIG_SS7) {
07375 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07376 #endif
07377 }
07378 update_conf(p);
07379
07380 ast_mutex_unlock(&p->lock);
07381
07382 if (newchan->_state == AST_STATE_RINGING) {
07383 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07384 }
07385 return 0;
07386 }
07387
07388 static int dahdi_ring_phone(struct dahdi_pvt *p)
07389 {
07390 int x;
07391 int res;
07392
07393 x = 0;
07394 x = DAHDI_ONHOOK;
07395 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07396 do {
07397 x = DAHDI_RING;
07398 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07399 if (res) {
07400 switch (errno) {
07401 case EBUSY:
07402 case EINTR:
07403
07404 usleep(10000);
07405 continue;
07406 case EINPROGRESS:
07407 res = 0;
07408 break;
07409 default:
07410 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07411 res = 0;
07412 }
07413 }
07414 } while (res);
07415 return res;
07416 }
07417
07418 static void *analog_ss_thread(void *data);
07419
07420 static int attempt_transfer(struct dahdi_pvt *p)
07421 {
07422
07423
07424
07425 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07426
07427
07428 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07429 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07430 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07431 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07432 }
07433 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07434 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07435 }
07436 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07437 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07438 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07439 return -1;
07440 }
07441
07442 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07443 unalloc_sub(p, SUB_THREEWAY);
07444 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07445 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07446 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07447 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07448 }
07449 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07450 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07451 }
07452 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07453 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07454 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07455 return -1;
07456 }
07457
07458 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07459 ast_channel_unlock(p->subs[SUB_REAL].owner);
07460 unalloc_sub(p, SUB_THREEWAY);
07461
07462 return 1;
07463 } else {
07464 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07465 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07466 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07467 return -1;
07468 }
07469 return 0;
07470 }
07471
07472 static int check_for_conference(struct dahdi_pvt *p)
07473 {
07474 struct dahdi_confinfo ci;
07475
07476 if (p->master || (p->confno > -1))
07477 return 0;
07478 memset(&ci, 0, sizeof(ci));
07479 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07480 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07481 return 0;
07482 }
07483
07484
07485
07486 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07487 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07488 return 1;
07489 }
07490 return 0;
07491 }
07492
07493
07494
07495
07496
07497
07498 static int get_alarms(struct dahdi_pvt *p)
07499 {
07500 int res;
07501 struct dahdi_spaninfo zi;
07502 struct dahdi_params params;
07503
07504 memset(&zi, 0, sizeof(zi));
07505 zi.spanno = p->span;
07506
07507 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07508 if (zi.alarms != DAHDI_ALARM_NONE)
07509 return zi.alarms;
07510 } else {
07511 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07512 return 0;
07513 }
07514
07515
07516 memset(¶ms, 0, sizeof(params));
07517 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07518 return params.chan_alarms;
07519
07520 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07521
07522 return DAHDI_ALARM_NONE;
07523 }
07524
07525 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07526 {
07527 struct dahdi_pvt *p = ast->tech_pvt;
07528 struct ast_frame *f = *dest;
07529
07530 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07531 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07532 f->subclass.integer, f->subclass.integer, ast->name);
07533
07534 if (p->confirmanswer) {
07535 if (f->frametype == AST_FRAME_DTMF_END) {
07536 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07537
07538
07539 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07540 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07541
07542 p->confirmanswer = 0;
07543 } else {
07544 p->subs[idx].f.frametype = AST_FRAME_NULL;
07545 p->subs[idx].f.subclass.integer = 0;
07546 }
07547 *dest = &p->subs[idx].f;
07548 } else if (p->callwaitcas) {
07549 if (f->frametype == AST_FRAME_DTMF_END) {
07550 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07551 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07552 ast_free(p->cidspill);
07553 p->cidspill = NULL;
07554 send_cwcidspill(p);
07555 }
07556 p->callwaitcas = 0;
07557 }
07558 p->subs[idx].f.frametype = AST_FRAME_NULL;
07559 p->subs[idx].f.subclass.integer = 0;
07560 *dest = &p->subs[idx].f;
07561 } else if (f->subclass.integer == 'f') {
07562 if (f->frametype == AST_FRAME_DTMF_END) {
07563
07564 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07565
07566 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07567 struct dahdi_bufferinfo bi = {
07568 .txbufpolicy = p->faxbuf_policy,
07569 .bufsize = p->bufsize,
07570 .numbufs = p->faxbuf_no
07571 };
07572 int res;
07573
07574 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07575 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07576 } else {
07577 p->bufferoverrideinuse = 1;
07578 }
07579 }
07580 p->faxhandled = 1;
07581 if (p->dsp) {
07582 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07583 ast_dsp_set_features(p->dsp, p->dsp_features);
07584 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07585 }
07586 if (strcmp(ast->exten, "fax")) {
07587 const char *target_context = S_OR(ast->macrocontext, ast->context);
07588
07589
07590
07591
07592
07593 ast_mutex_unlock(&p->lock);
07594 ast_channel_unlock(ast);
07595 if (ast_exists_extension(ast, target_context, "fax", 1,
07596 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07597 ast_channel_lock(ast);
07598 ast_mutex_lock(&p->lock);
07599 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07600
07601 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07602 if (ast_async_goto(ast, target_context, "fax", 1))
07603 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07604 } else {
07605 ast_channel_lock(ast);
07606 ast_mutex_lock(&p->lock);
07607 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07608 }
07609 } else {
07610 ast_debug(1, "Already in a fax extension, not redirecting\n");
07611 }
07612 } else {
07613 ast_debug(1, "Fax already handled\n");
07614 }
07615 dahdi_confmute(p, 0);
07616 }
07617 p->subs[idx].f.frametype = AST_FRAME_NULL;
07618 p->subs[idx].f.subclass.integer = 0;
07619 *dest = &p->subs[idx].f;
07620 }
07621 }
07622
07623 static void handle_alarms(struct dahdi_pvt *p, int alms)
07624 {
07625 const char *alarm_str = alarm2str(alms);
07626
07627 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07628 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07629 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07630 "Alarm: %s\r\n"
07631 "Channel: %d\r\n",
07632 alarm_str, p->channel);
07633 }
07634
07635 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07636 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07637 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07638 "Alarm: %s\r\n"
07639 "Span: %d\r\n",
07640 alarm_str, p->span);
07641 }
07642 }
07643
07644 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07645 {
07646 int res, x;
07647 int idx, mysig;
07648 char *c;
07649 struct dahdi_pvt *p = ast->tech_pvt;
07650 pthread_t threadid;
07651 struct ast_channel *chan;
07652 struct ast_frame *f;
07653
07654 idx = dahdi_get_index(ast, p, 0);
07655 mysig = p->sig;
07656 if (p->outsigmod > -1)
07657 mysig = p->outsigmod;
07658 p->subs[idx].f.frametype = AST_FRAME_NULL;
07659 p->subs[idx].f.subclass.integer = 0;
07660 p->subs[idx].f.datalen = 0;
07661 p->subs[idx].f.samples = 0;
07662 p->subs[idx].f.mallocd = 0;
07663 p->subs[idx].f.offset = 0;
07664 p->subs[idx].f.src = "dahdi_handle_event";
07665 p->subs[idx].f.data.ptr = NULL;
07666 f = &p->subs[idx].f;
07667
07668 if (idx < 0)
07669 return &p->subs[idx].f;
07670 if (p->fake_event) {
07671 res = p->fake_event;
07672 p->fake_event = 0;
07673 } else
07674 res = dahdi_get_event(p->subs[idx].dfd);
07675
07676 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07677
07678 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07679 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07680 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07681 #if defined(HAVE_PRI)
07682 if (dahdi_sig_pri_lib_handles(p->sig)
07683 && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07684 && p->pri
07685 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07686
07687 } else
07688 #endif
07689 {
07690
07691 dahdi_confmute(p, 0);
07692 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07693 p->subs[idx].f.subclass.integer = res & 0xff;
07694 dahdi_handle_dtmf(ast, idx, &f);
07695 }
07696 return f;
07697 }
07698
07699 if (res & DAHDI_EVENT_DTMFDOWN) {
07700 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
07701 #if defined(HAVE_PRI)
07702 if (dahdi_sig_pri_lib_handles(p->sig)
07703 && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07704 && p->pri
07705 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07706
07707 } else
07708 #endif
07709 {
07710
07711 dahdi_confmute(p, 1);
07712 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07713 p->subs[idx].f.subclass.integer = res & 0xff;
07714 dahdi_handle_dtmf(ast, idx, &f);
07715 }
07716 return &p->subs[idx].f;
07717 }
07718
07719 switch (res) {
07720 case DAHDI_EVENT_EC_DISABLED:
07721 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07722 p->echocanon = 0;
07723 break;
07724 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07725 case DAHDI_EVENT_TX_CED_DETECTED:
07726 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07727 break;
07728 case DAHDI_EVENT_RX_CED_DETECTED:
07729 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07730 break;
07731 case DAHDI_EVENT_EC_NLP_DISABLED:
07732 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07733 break;
07734 case DAHDI_EVENT_EC_NLP_ENABLED:
07735 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07736 break;
07737 #endif
07738 case DAHDI_EVENT_BITSCHANGED:
07739 #ifdef HAVE_OPENR2
07740 if (p->sig != SIG_MFCR2) {
07741 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07742 } else {
07743 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07744 openr2_chan_handle_cas(p->r2chan);
07745 }
07746 #else
07747 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07748 #endif
07749 case DAHDI_EVENT_PULSE_START:
07750
07751 if (!ast->pbx)
07752 tone_zone_play_tone(p->subs[idx].dfd, -1);
07753 break;
07754 case DAHDI_EVENT_DIALCOMPLETE:
07755 #ifdef HAVE_OPENR2
07756 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07757
07758
07759 break;
07760 }
07761 #endif
07762 if (p->inalarm) break;
07763 if ((p->radio || (p->oprmode < 0))) break;
07764 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07765 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07766 return NULL;
07767 }
07768 if (!x) {
07769 dahdi_enable_ec(p);
07770 if (p->echobreak) {
07771 dahdi_train_ec(p);
07772 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07773 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07774 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07775 p->echobreak = 0;
07776 } else {
07777 p->dialing = 0;
07778 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07779
07780 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07781 ast_setstate(ast, AST_STATE_UP);
07782 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07783 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07784 break;
07785 } else {
07786
07787 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07788 }
07789 }
07790 if (ast->_state == AST_STATE_DIALING) {
07791 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07792 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07793 } else if (p->confirmanswer || (!p->dialednone
07794 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07795 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07796 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07797 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07798 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07799 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07800 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07801 || (mysig == SIG_SF_FEATB)))) {
07802 ast_setstate(ast, AST_STATE_RINGING);
07803 } else if (!p->answeronpolarityswitch) {
07804 ast_setstate(ast, AST_STATE_UP);
07805 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07806 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07807
07808 p->polarity = POLARITY_REV;
07809 } else {
07810
07811 p->polarity = POLARITY_IDLE;
07812 }
07813 }
07814 }
07815 }
07816 break;
07817 case DAHDI_EVENT_ALARM:
07818 switch (p->sig) {
07819 #if defined(HAVE_PRI)
07820 case SIG_PRI_LIB_HANDLE_CASES:
07821 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07822 break;
07823 #endif
07824 #if defined(HAVE_SS7)
07825 case SIG_SS7:
07826 sig_ss7_set_alarm(p->sig_pvt, 1);
07827 break;
07828 #endif
07829 default:
07830 p->inalarm = 1;
07831 break;
07832 }
07833 res = get_alarms(p);
07834 handle_alarms(p, res);
07835 #ifdef HAVE_PRI
07836 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07837
07838 } else {
07839 break;
07840 }
07841 #endif
07842 #if defined(HAVE_SS7)
07843 if (p->sig == SIG_SS7)
07844 break;
07845 #endif
07846 #ifdef HAVE_OPENR2
07847 if (p->sig == SIG_MFCR2)
07848 break;
07849 #endif
07850 case DAHDI_EVENT_ONHOOK:
07851 if (p->radio) {
07852 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07853 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07854 break;
07855 }
07856 if (p->oprmode < 0)
07857 {
07858 if (p->oprmode != -1) break;
07859 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07860 {
07861
07862 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07863 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07864 save_conference(p->oprpeer);
07865 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07866 }
07867 break;
07868 }
07869 switch (p->sig) {
07870 case SIG_FXOLS:
07871 case SIG_FXOGS:
07872 case SIG_FXOKS:
07873
07874 if (idx == SUB_REAL) {
07875
07876 if (p->subs[SUB_CALLWAIT].owner) {
07877
07878 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07879 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07880 unalloc_sub(p, SUB_CALLWAIT);
07881 #if 0
07882 p->subs[idx].needanswer = 0;
07883 p->subs[idx].needringing = 0;
07884 #endif
07885 p->callwaitingrepeat = 0;
07886 p->cidcwexpire = 0;
07887 p->cid_suppress_expire = 0;
07888 p->owner = NULL;
07889
07890 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
07891 p->dialing = 1;
07892 dahdi_ring_phone(p);
07893 } else if (p->subs[SUB_THREEWAY].owner) {
07894 unsigned int mssinceflash;
07895
07896
07897 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07898
07899 DLA_UNLOCK(&p->lock);
07900 CHANNEL_DEADLOCK_AVOIDANCE(ast);
07901
07902
07903
07904 DLA_LOCK(&p->lock);
07905 if (p->owner != ast) {
07906 ast_log(LOG_WARNING, "This isn't good...\n");
07907 return NULL;
07908 }
07909 }
07910 if (!p->subs[SUB_THREEWAY].owner) {
07911 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07912 return NULL;
07913 }
07914 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07915 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
07916 if (mssinceflash < MIN_MS_SINCE_FLASH) {
07917
07918
07919 if (p->subs[SUB_THREEWAY].owner)
07920 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07921 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07922 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07923 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07924 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
07925 if (p->transfer) {
07926
07927 p->subs[SUB_REAL].inthreeway = 0;
07928 p->subs[SUB_THREEWAY].inthreeway = 0;
07929
07930 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
07931 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07932
07933 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07934 p->owner = NULL;
07935
07936 dahdi_ring_phone(p);
07937 } else {
07938 if ((res = attempt_transfer(p)) < 0) {
07939 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07940 if (p->subs[SUB_THREEWAY].owner)
07941 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07942 } else if (res) {
07943
07944 if (p->subs[SUB_THREEWAY].owner)
07945 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07946 break;
07947 }
07948 }
07949 } else {
07950 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07951 if (p->subs[SUB_THREEWAY].owner)
07952 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07953 }
07954 } else {
07955 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07956
07957 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07958 p->owner = NULL;
07959
07960 dahdi_ring_phone(p);
07961 }
07962 }
07963 } else {
07964 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07965 }
07966
07967 default:
07968 dahdi_disable_ec(p);
07969 return NULL;
07970 }
07971 break;
07972 case DAHDI_EVENT_RINGOFFHOOK:
07973 if (p->inalarm) break;
07974 if (p->oprmode < 0)
07975 {
07976 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07977 {
07978
07979 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07980 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07981 restore_conference(p->oprpeer);
07982 }
07983 break;
07984 }
07985 if (p->radio)
07986 {
07987 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07988 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
07989 break;
07990 }
07991
07992
07993 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
07994 c = strchr(p->dialdest, '/');
07995 if (c)
07996 c++;
07997 else
07998 c = p->dialdest;
07999 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
08000 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
08001 if (strlen(p->dop.dialstr) > 4) {
08002 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
08003 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
08004 p->echorest[sizeof(p->echorest) - 1] = '\0';
08005 p->echobreak = 1;
08006 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
08007 } else
08008 p->echobreak = 0;
08009 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
08010 int saveerr = errno;
08011
08012 x = DAHDI_ONHOOK;
08013 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
08014 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
08015 return NULL;
08016 }
08017 p->dialing = 1;
08018 return &p->subs[idx].f;
08019 }
08020 switch (p->sig) {
08021 case SIG_FXOLS:
08022 case SIG_FXOGS:
08023 case SIG_FXOKS:
08024 switch (ast->_state) {
08025 case AST_STATE_RINGING:
08026 dahdi_enable_ec(p);
08027 dahdi_train_ec(p);
08028 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08029 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08030
08031 p->subs[SUB_REAL].needringing = 0;
08032 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08033 ast_debug(1, "channel %d answered\n", p->channel);
08034
08035
08036 ast_free(p->cidspill);
08037 p->cidspill = NULL;
08038 restore_conference(p);
08039
08040 p->dialing = 0;
08041 p->callwaitcas = 0;
08042 if (p->confirmanswer) {
08043
08044 p->subs[idx].f.frametype = AST_FRAME_NULL;
08045 p->subs[idx].f.subclass.integer = 0;
08046 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08047
08048 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08049 if (res < 0) {
08050 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08051 p->dop.dialstr[0] = '\0';
08052 return NULL;
08053 } else {
08054 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08055 p->subs[idx].f.frametype = AST_FRAME_NULL;
08056 p->subs[idx].f.subclass.integer = 0;
08057 p->dialing = 1;
08058 }
08059 p->dop.dialstr[0] = '\0';
08060 ast_setstate(ast, AST_STATE_DIALING);
08061 } else
08062 ast_setstate(ast, AST_STATE_UP);
08063 return &p->subs[idx].f;
08064 case AST_STATE_DOWN:
08065 ast_setstate(ast, AST_STATE_RING);
08066 ast->rings = 1;
08067 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08068 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08069 ast_debug(1, "channel %d picked up\n", p->channel);
08070 return &p->subs[idx].f;
08071 case AST_STATE_UP:
08072
08073 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08074
08075 if (ast_bridged_channel(p->owner))
08076 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08077 p->subs[idx].needunhold = 1;
08078 break;
08079 case AST_STATE_RESERVED:
08080
08081 if (has_voicemail(p))
08082 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08083 else
08084 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08085 break;
08086 default:
08087 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08088 }
08089 break;
08090 case SIG_FXSLS:
08091 case SIG_FXSGS:
08092 case SIG_FXSKS:
08093 if (ast->_state == AST_STATE_RING) {
08094 p->ringt = p->ringt_base;
08095 }
08096
08097
08098
08099 ast_debug(1, "Setting IDLE polarity due "
08100 "to ring. Old polarity was %d\n",
08101 p->polarity);
08102 p->polarity = POLARITY_IDLE;
08103
08104
08105 case SIG_EM:
08106 case SIG_EM_E1:
08107 case SIG_EMWINK:
08108 case SIG_FEATD:
08109 case SIG_FEATDMF:
08110 case SIG_FEATDMF_TA:
08111 case SIG_E911:
08112 case SIG_FGC_CAMA:
08113 case SIG_FGC_CAMAMF:
08114 case SIG_FEATB:
08115 case SIG_SF:
08116 case SIG_SFWINK:
08117 case SIG_SF_FEATD:
08118 case SIG_SF_FEATDMF:
08119 case SIG_SF_FEATB:
08120 if (ast->_state == AST_STATE_PRERING)
08121 ast_setstate(ast, AST_STATE_RING);
08122 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08123 ast_debug(1, "Ring detected\n");
08124 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08125 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08126 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08127 ast_debug(1, "Line answered\n");
08128 if (p->confirmanswer) {
08129 p->subs[idx].f.frametype = AST_FRAME_NULL;
08130 p->subs[idx].f.subclass.integer = 0;
08131 } else {
08132 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08133 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08134 ast_setstate(ast, AST_STATE_UP);
08135 }
08136 } else if (ast->_state != AST_STATE_RING)
08137 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08138 break;
08139 default:
08140 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08141 }
08142 break;
08143 case DAHDI_EVENT_RINGBEGIN:
08144 switch (p->sig) {
08145 case SIG_FXSLS:
08146 case SIG_FXSGS:
08147 case SIG_FXSKS:
08148 if (ast->_state == AST_STATE_RING) {
08149 p->ringt = p->ringt_base;
08150 }
08151 break;
08152 }
08153 break;
08154 case DAHDI_EVENT_RINGERON:
08155 break;
08156 case DAHDI_EVENT_NOALARM:
08157 switch (p->sig) {
08158 #if defined(HAVE_PRI)
08159 case SIG_PRI_LIB_HANDLE_CASES:
08160 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08161 break;
08162 #endif
08163 #if defined(HAVE_SS7)
08164 case SIG_SS7:
08165 sig_ss7_set_alarm(p->sig_pvt, 0);
08166 break;
08167 #endif
08168 default:
08169 p->inalarm = 0;
08170 break;
08171 }
08172 handle_clear_alarms(p);
08173 break;
08174 case DAHDI_EVENT_WINKFLASH:
08175 if (p->inalarm) break;
08176 if (p->radio) break;
08177 if (p->oprmode < 0) break;
08178 if (p->oprmode > 1)
08179 {
08180 struct dahdi_params par;
08181
08182 memset(&par, 0, sizeof(par));
08183 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08184 {
08185 if (!par.rxisoffhook)
08186 {
08187
08188 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08189 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08190 save_conference(p);
08191 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08192 }
08193 }
08194 break;
08195 }
08196
08197 p->flashtime = ast_tvnow();
08198 switch (mysig) {
08199 case SIG_FXOLS:
08200 case SIG_FXOGS:
08201 case SIG_FXOKS:
08202 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08203 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08204
08205
08206 ast_free(p->cidspill);
08207 p->cidspill = NULL;
08208 restore_conference(p);
08209 p->callwaitcas = 0;
08210
08211 if (idx != SUB_REAL) {
08212 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08213 goto winkflashdone;
08214 }
08215
08216 if (p->subs[SUB_CALLWAIT].owner) {
08217
08218 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08219 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08220 p->owner = p->subs[SUB_REAL].owner;
08221 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08222 if (p->owner->_state == AST_STATE_RINGING) {
08223 ast_setstate(p->owner, AST_STATE_UP);
08224 p->subs[SUB_REAL].needanswer = 1;
08225 }
08226 p->callwaitingrepeat = 0;
08227 p->cidcwexpire = 0;
08228 p->cid_suppress_expire = 0;
08229
08230 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08231 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08232 S_OR(p->mohsuggest, NULL),
08233 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08234 }
08235 p->subs[SUB_CALLWAIT].needhold = 1;
08236 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08237 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08238 S_OR(p->mohsuggest, NULL),
08239 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08240 }
08241 p->subs[SUB_REAL].needunhold = 1;
08242 } else if (!p->subs[SUB_THREEWAY].owner) {
08243 if (!p->threewaycalling) {
08244
08245 p->subs[SUB_REAL].needflash = 1;
08246 goto winkflashdone;
08247 } else if (!check_for_conference(p)) {
08248 char cid_num[256];
08249 char cid_name[256];
08250
08251 cid_num[0] = 0;
08252 cid_name[0] = 0;
08253 if (p->dahditrcallerid && p->owner) {
08254 if (p->owner->caller.id.number.valid
08255 && p->owner->caller.id.number.str) {
08256 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08257 sizeof(cid_num));
08258 }
08259 if (p->owner->caller.id.name.valid
08260 && p->owner->caller.id.name.str) {
08261 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08262 sizeof(cid_name));
08263 }
08264 }
08265
08266
08267 if (!((ast->pbx) ||
08268 (ast->_state == AST_STATE_UP) ||
08269 (ast->_state == AST_STATE_RING))) {
08270 ast_debug(1, "Flash when call not up or ringing\n");
08271 goto winkflashdone;
08272 }
08273 if (alloc_sub(p, SUB_THREEWAY)) {
08274 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08275 goto winkflashdone;
08276 }
08277
08278 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08279 if (p->dahditrcallerid) {
08280 if (!p->origcid_num)
08281 p->origcid_num = ast_strdup(p->cid_num);
08282 if (!p->origcid_name)
08283 p->origcid_name = ast_strdup(p->cid_name);
08284 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08285 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08286 }
08287
08288 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08289
08290 dahdi_disable_ec(p);
08291 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08292 if (res)
08293 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08294 p->owner = chan;
08295 if (!chan) {
08296 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08297 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08298 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08299 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08300 dahdi_enable_ec(p);
08301 ast_hangup(chan);
08302 } else {
08303 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08304
08305
08306 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08307 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08308 S_OR(p->mohsuggest, NULL),
08309 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08310 }
08311 p->subs[SUB_THREEWAY].needhold = 1;
08312 }
08313 }
08314 } else {
08315
08316 if (p->subs[SUB_THREEWAY].inthreeway) {
08317
08318 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08319
08320 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08321
08322 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08323 p->owner = p->subs[SUB_REAL].owner;
08324 }
08325
08326 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08327 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08328 p->subs[SUB_REAL].inthreeway = 0;
08329 p->subs[SUB_THREEWAY].inthreeway = 0;
08330 } else {
08331
08332 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08333 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08334 int otherindex = SUB_THREEWAY;
08335
08336 ast_verb(3, "Building conference call with %s and %s\n",
08337 p->subs[SUB_THREEWAY].owner->name,
08338 p->subs[SUB_REAL].owner->name);
08339
08340 p->subs[SUB_THREEWAY].inthreeway = 1;
08341 p->subs[SUB_REAL].inthreeway = 1;
08342 if (ast->_state == AST_STATE_UP) {
08343 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08344 otherindex = SUB_REAL;
08345 }
08346 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08347 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08348 p->subs[otherindex].needunhold = 1;
08349 p->owner = p->subs[SUB_REAL].owner;
08350 } else {
08351 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08352 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08353 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08354 p->owner = p->subs[SUB_REAL].owner;
08355 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08356 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08357 p->subs[SUB_REAL].needunhold = 1;
08358 dahdi_enable_ec(p);
08359 }
08360 }
08361 }
08362 winkflashdone:
08363 update_conf(p);
08364 break;
08365 case SIG_EM:
08366 case SIG_EM_E1:
08367 case SIG_FEATD:
08368 case SIG_SF:
08369 case SIG_SFWINK:
08370 case SIG_SF_FEATD:
08371 case SIG_FXSLS:
08372 case SIG_FXSGS:
08373 if (p->dialing)
08374 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08375 else
08376 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08377 break;
08378 case SIG_FEATDMF_TA:
08379 switch (p->whichwink) {
08380 case 0:
08381 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08382 S_COR(p->owner->caller.ani.number.valid,
08383 p->owner->caller.ani.number.str, ""));
08384 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08385 p->owner->caller.ani2,
08386 S_COR(p->owner->caller.ani.number.valid,
08387 p->owner->caller.ani.number.str, ""));
08388 break;
08389 case 1:
08390 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08391 break;
08392 case 2:
08393 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08394 return NULL;
08395 }
08396 p->whichwink++;
08397
08398 case SIG_FEATDMF:
08399 case SIG_E911:
08400 case SIG_FGC_CAMAMF:
08401 case SIG_FGC_CAMA:
08402 case SIG_FEATB:
08403 case SIG_SF_FEATDMF:
08404 case SIG_SF_FEATB:
08405 case SIG_EMWINK:
08406
08407 if (!ast_strlen_zero(p->dop.dialstr)) {
08408 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08409 if (res < 0) {
08410 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08411 p->dop.dialstr[0] = '\0';
08412 return NULL;
08413 } else
08414 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08415 }
08416 p->dop.dialstr[0] = '\0';
08417 break;
08418 default:
08419 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08420 }
08421 break;
08422 case DAHDI_EVENT_HOOKCOMPLETE:
08423 if (p->inalarm) break;
08424 if ((p->radio || (p->oprmode < 0))) break;
08425 if (p->waitingfordt.tv_sec) break;
08426 switch (mysig) {
08427 case SIG_FXSLS:
08428 case SIG_FXSGS:
08429 case SIG_FXSKS:
08430 case SIG_EM:
08431 case SIG_EM_E1:
08432 case SIG_EMWINK:
08433 case SIG_FEATD:
08434 case SIG_SF:
08435 case SIG_SFWINK:
08436 case SIG_SF_FEATD:
08437 if (!ast_strlen_zero(p->dop.dialstr)) {
08438 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08439 if (res < 0) {
08440 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08441 p->dop.dialstr[0] = '\0';
08442 return NULL;
08443 } else
08444 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08445 }
08446 p->dop.dialstr[0] = '\0';
08447 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08448 break;
08449 case SIG_FEATDMF:
08450 case SIG_FEATDMF_TA:
08451 case SIG_E911:
08452 case SIG_FGC_CAMA:
08453 case SIG_FGC_CAMAMF:
08454 case SIG_FEATB:
08455 case SIG_SF_FEATDMF:
08456 case SIG_SF_FEATB:
08457 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08458 break;
08459 default:
08460 break;
08461 }
08462 break;
08463 case DAHDI_EVENT_POLARITY:
08464
08465
08466
08467
08468
08469
08470 if (p->polarity == POLARITY_IDLE) {
08471 p->polarity = POLARITY_REV;
08472 if (p->answeronpolarityswitch &&
08473 ((ast->_state == AST_STATE_DIALING) ||
08474 (ast->_state == AST_STATE_RINGING))) {
08475 ast_debug(1, "Answering on polarity switch!\n");
08476 ast_setstate(p->owner, AST_STATE_UP);
08477 if (p->hanguponpolarityswitch) {
08478 p->polaritydelaytv = ast_tvnow();
08479 }
08480 } else
08481 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08482 }
08483
08484
08485 if (p->hanguponpolarityswitch &&
08486 (p->polarityonanswerdelay > 0) &&
08487 (p->polarity == POLARITY_REV) &&
08488 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08489
08490 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) );
08491
08492 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08493 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08494 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08495 p->polarity = POLARITY_IDLE;
08496 } else
08497 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);
08498
08499 } else {
08500 p->polarity = POLARITY_IDLE;
08501 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08502 }
08503
08504 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) );
08505 break;
08506 default:
08507 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08508 }
08509 return &p->subs[idx].f;
08510 }
08511
08512 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08513 {
08514 int res;
08515 int idx;
08516 struct ast_frame *f;
08517 int usedindex = -1;
08518 struct dahdi_pvt *p = ast->tech_pvt;
08519
08520 idx = dahdi_get_index(ast, p, 1);
08521
08522 p->subs[idx].f.frametype = AST_FRAME_NULL;
08523 p->subs[idx].f.datalen = 0;
08524 p->subs[idx].f.samples = 0;
08525 p->subs[idx].f.mallocd = 0;
08526 p->subs[idx].f.offset = 0;
08527 p->subs[idx].f.subclass.integer = 0;
08528 p->subs[idx].f.delivery = ast_tv(0,0);
08529 p->subs[idx].f.src = "dahdi_exception";
08530 p->subs[idx].f.data.ptr = NULL;
08531
08532
08533 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08534
08535
08536
08537
08538
08539 if (p->fake_event) {
08540 res = p->fake_event;
08541 p->fake_event = 0;
08542 } else
08543 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08544
08545 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08546 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08547 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08548 p->owner = p->subs[SUB_REAL].owner;
08549 if (p->owner && ast_bridged_channel(p->owner))
08550 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08551 p->subs[SUB_REAL].needunhold = 1;
08552 }
08553 switch (res) {
08554 case DAHDI_EVENT_ONHOOK:
08555 dahdi_disable_ec(p);
08556 if (p->owner) {
08557 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08558 dahdi_ring_phone(p);
08559 p->callwaitingrepeat = 0;
08560 p->cidcwexpire = 0;
08561 p->cid_suppress_expire = 0;
08562 } else
08563 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08564 update_conf(p);
08565 break;
08566 case DAHDI_EVENT_RINGOFFHOOK:
08567 dahdi_enable_ec(p);
08568 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08569 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08570 p->subs[SUB_REAL].needanswer = 1;
08571 p->dialing = 0;
08572 }
08573 break;
08574 case DAHDI_EVENT_HOOKCOMPLETE:
08575 case DAHDI_EVENT_RINGERON:
08576 case DAHDI_EVENT_RINGEROFF:
08577
08578 break;
08579 case DAHDI_EVENT_WINKFLASH:
08580 p->flashtime = ast_tvnow();
08581 if (p->owner) {
08582 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08583 if (p->owner->_state != AST_STATE_UP) {
08584
08585 usedindex = dahdi_get_index(p->owner, p, 0);
08586 if (usedindex > -1) {
08587 p->subs[usedindex].needanswer = 1;
08588 }
08589 ast_setstate(p->owner, AST_STATE_UP);
08590 }
08591 p->callwaitingrepeat = 0;
08592 p->cidcwexpire = 0;
08593 p->cid_suppress_expire = 0;
08594 if (ast_bridged_channel(p->owner))
08595 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08596 p->subs[SUB_REAL].needunhold = 1;
08597 } else
08598 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08599 update_conf(p);
08600 break;
08601 default:
08602 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08603 }
08604 f = &p->subs[idx].f;
08605 return f;
08606 }
08607 if (!(p->radio || (p->oprmode < 0)))
08608 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08609
08610 if (ast != p->owner) {
08611 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08612 f = &p->subs[idx].f;
08613 return f;
08614 }
08615 f = dahdi_handle_event(ast);
08616
08617
08618 if (f == NULL) {
08619 ast_set_hangupsource(ast, ast->name, 0);
08620 }
08621
08622 return f;
08623 }
08624
08625 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08626 {
08627 struct dahdi_pvt *p = ast->tech_pvt;
08628 struct ast_frame *f;
08629 ast_mutex_lock(&p->lock);
08630 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08631 struct analog_pvt *analog_p = p->sig_pvt;
08632 f = analog_exception(analog_p, ast);
08633 } else {
08634 f = __dahdi_exception(ast);
08635 }
08636 ast_mutex_unlock(&p->lock);
08637 return f;
08638 }
08639
08640 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08641 {
08642 struct dahdi_pvt *p = ast->tech_pvt;
08643 int res;
08644 int idx;
08645 void *readbuf;
08646 struct ast_frame *f;
08647
08648 while (ast_mutex_trylock(&p->lock)) {
08649 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08650 }
08651
08652 idx = dahdi_get_index(ast, p, 0);
08653
08654
08655 if (idx < 0) {
08656 ast_log(LOG_WARNING, "We don't exist?\n");
08657 ast_mutex_unlock(&p->lock);
08658 return NULL;
08659 }
08660
08661 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08662 ast_mutex_unlock(&p->lock);
08663 return NULL;
08664 }
08665
08666 p->subs[idx].f.frametype = AST_FRAME_NULL;
08667 p->subs[idx].f.datalen = 0;
08668 p->subs[idx].f.samples = 0;
08669 p->subs[idx].f.mallocd = 0;
08670 p->subs[idx].f.offset = 0;
08671 p->subs[idx].f.subclass.integer = 0;
08672 p->subs[idx].f.delivery = ast_tv(0,0);
08673 p->subs[idx].f.src = "dahdi_read";
08674 p->subs[idx].f.data.ptr = NULL;
08675
08676
08677 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08678 {
08679 struct dahdi_params ps;
08680
08681 memset(&ps, 0, sizeof(ps));
08682 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08683 ast_mutex_unlock(&p->lock);
08684 return NULL;
08685 }
08686 p->firstradio = 1;
08687 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08688 if (ps.rxisoffhook)
08689 {
08690 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08691 }
08692 else
08693 {
08694 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08695 }
08696 ast_mutex_unlock(&p->lock);
08697 return &p->subs[idx].f;
08698 }
08699 if (p->ringt > 0) {
08700 if (!(--p->ringt)) {
08701 ast_mutex_unlock(&p->lock);
08702 return NULL;
08703 }
08704 }
08705
08706 #ifdef HAVE_OPENR2
08707 if (p->mfcr2) {
08708 openr2_chan_process_event(p->r2chan);
08709 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08710 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08711
08712
08713 if (p->mfcr2_call_accepted &&
08714 !p->mfcr2_progress &&
08715 ast->_state == AST_STATE_RINGING) {
08716 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08717 ast_queue_frame(p->owner, &f);
08718 p->mfcr2_progress = 1;
08719 }
08720 }
08721 }
08722 #endif
08723
08724 if (p->subs[idx].needringing) {
08725
08726 p->subs[idx].needringing = 0;
08727 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08728 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08729 ast_setstate(ast, AST_STATE_RINGING);
08730 ast_mutex_unlock(&p->lock);
08731 return &p->subs[idx].f;
08732 }
08733
08734 if (p->subs[idx].needbusy) {
08735
08736 p->subs[idx].needbusy = 0;
08737 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08738 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08739 ast_mutex_unlock(&p->lock);
08740 return &p->subs[idx].f;
08741 }
08742
08743 if (p->subs[idx].needcongestion) {
08744
08745 p->subs[idx].needcongestion = 0;
08746 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08747 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08748 ast_mutex_unlock(&p->lock);
08749 return &p->subs[idx].f;
08750 }
08751
08752 if (p->subs[idx].needanswer) {
08753
08754 p->subs[idx].needanswer = 0;
08755 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08756 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08757 ast_mutex_unlock(&p->lock);
08758 return &p->subs[idx].f;
08759 }
08760 #ifdef HAVE_OPENR2
08761 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08762
08763
08764
08765
08766 ast_mutex_unlock(&p->lock);
08767 return &ast_null_frame;
08768 }
08769 #endif
08770
08771 if (p->subs[idx].needflash) {
08772
08773 p->subs[idx].needflash = 0;
08774 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08775 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08776 ast_mutex_unlock(&p->lock);
08777 return &p->subs[idx].f;
08778 }
08779
08780 if (p->subs[idx].needhold) {
08781
08782 p->subs[idx].needhold = 0;
08783 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08784 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08785 ast_mutex_unlock(&p->lock);
08786 ast_debug(1, "Sending hold on '%s'\n", ast->name);
08787 return &p->subs[idx].f;
08788 }
08789
08790 if (p->subs[idx].needunhold) {
08791
08792 p->subs[idx].needunhold = 0;
08793 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08794 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08795 ast_mutex_unlock(&p->lock);
08796 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08797 return &p->subs[idx].f;
08798 }
08799
08800 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08801 if (!p->subs[idx].linear) {
08802 p->subs[idx].linear = 1;
08803 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08804 if (res)
08805 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08806 }
08807 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08808 (ast->rawreadformat == AST_FORMAT_ALAW)) {
08809 if (p->subs[idx].linear) {
08810 p->subs[idx].linear = 0;
08811 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08812 if (res)
08813 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08814 }
08815 } else {
08816 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08817 ast_mutex_unlock(&p->lock);
08818 return NULL;
08819 }
08820 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08821 CHECK_BLOCKING(ast);
08822 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08823 ast_clear_flag(ast, AST_FLAG_BLOCKING);
08824
08825 if (res < 0) {
08826 f = NULL;
08827 if (res == -1) {
08828 if (errno == EAGAIN) {
08829
08830 ast_mutex_unlock(&p->lock);
08831 return &p->subs[idx].f;
08832 } else if (errno == ELAST) {
08833 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08834 struct analog_pvt *analog_p = p->sig_pvt;
08835 f = analog_exception(analog_p, ast);
08836 } else {
08837 f = __dahdi_exception(ast);
08838 }
08839 } else
08840 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08841 }
08842 ast_mutex_unlock(&p->lock);
08843 return f;
08844 }
08845 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08846 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08847 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08848 struct analog_pvt *analog_p = p->sig_pvt;
08849 f = analog_exception(analog_p, ast);
08850 } else {
08851 f = __dahdi_exception(ast);
08852 }
08853 ast_mutex_unlock(&p->lock);
08854 return f;
08855 }
08856 if (p->tdd) {
08857 int c;
08858
08859 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
08860 if (c < 0) {
08861 ast_debug(1,"tdd_feed failed\n");
08862 ast_mutex_unlock(&p->lock);
08863 return NULL;
08864 }
08865 if (c) {
08866 p->subs[idx].f.subclass.integer = 0;
08867 p->subs[idx].f.frametype = AST_FRAME_TEXT;
08868 p->subs[idx].f.mallocd = 0;
08869 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08870 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
08871 p->subs[idx].f.datalen = 1;
08872 *((char *) p->subs[idx].f.data.ptr) = c;
08873 ast_mutex_unlock(&p->lock);
08874 return &p->subs[idx].f;
08875 }
08876 }
08877 if (idx == SUB_REAL) {
08878
08879 if (p->cidcwexpire) {
08880 if (!--p->cidcwexpire) {
08881
08882 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
08883 restore_conference(p);
08884 }
08885 }
08886 if (p->cid_suppress_expire) {
08887 --p->cid_suppress_expire;
08888 }
08889 if (p->callwaitingrepeat) {
08890 if (!--p->callwaitingrepeat) {
08891
08892 ++p->callwaitrings;
08893 dahdi_callwait(ast);
08894 }
08895 }
08896 }
08897 if (p->subs[idx].linear) {
08898 p->subs[idx].f.datalen = READ_SIZE * 2;
08899 } else
08900 p->subs[idx].f.datalen = READ_SIZE;
08901
08902
08903 if ((p->owner == ast) && p->cidspill) {
08904 send_callerid(p);
08905 }
08906
08907 p->subs[idx].f.frametype = AST_FRAME_VOICE;
08908 p->subs[idx].f.subclass.codec = ast->rawreadformat;
08909 p->subs[idx].f.samples = READ_SIZE;
08910 p->subs[idx].f.mallocd = 0;
08911 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08912 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
08913 #if 0
08914 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
08915 #endif
08916 if (p->dialing || p->radio ||
08917 (idx && (ast->_state != AST_STATE_UP)) ||
08918 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
08919 ) {
08920
08921
08922 p->subs[idx].f.frametype = AST_FRAME_NULL;
08923 p->subs[idx].f.subclass.integer = 0;
08924 p->subs[idx].f.samples = 0;
08925 p->subs[idx].f.mallocd = 0;
08926 p->subs[idx].f.offset = 0;
08927 p->subs[idx].f.data.ptr = NULL;
08928 p->subs[idx].f.datalen= 0;
08929 }
08930 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
08931
08932 int mute;
08933
08934 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
08935
08936
08937 mute = ast_dsp_was_muted(p->dsp);
08938 if (p->muting != mute) {
08939 p->muting = mute;
08940 dahdi_confmute(p, mute);
08941 }
08942
08943 if (f) {
08944 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
08945 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
08946
08947
08948 f = NULL;
08949 }
08950 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
08951 || f->frametype == AST_FRAME_DTMF_END) {
08952 #ifdef HAVE_PRI
08953 if (dahdi_sig_pri_lib_handles(p->sig)
08954 && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
08955 && p->pri
08956 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
08957 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
08958
08959 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
08960 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
08961 f->subclass.integer, f->subclass.integer, ast->name);
08962
08963 f->frametype = AST_FRAME_NULL;
08964 f->subclass.integer = 0;
08965 }
08966 #endif
08967
08968 p->pulsedial = 0;
08969 } else if (p->waitingfordt.tv_sec) {
08970 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
08971 p->waitingfordt.tv_sec = 0;
08972 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
08973 f=NULL;
08974 } else if (f->frametype == AST_FRAME_VOICE) {
08975 f->frametype = AST_FRAME_NULL;
08976 f->subclass.integer = 0;
08977 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) {
08978 p->waitingfordt.tv_sec = 0;
08979 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
08980 ast_dsp_set_features(p->dsp, p->dsp_features);
08981 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
08982 if (!ast_strlen_zero(p->dop.dialstr)) {
08983 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08984 if (res < 0) {
08985 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
08986 p->dop.dialstr[0] = '\0';
08987 ast_mutex_unlock(&p->lock);
08988 return NULL;
08989 } else {
08990 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
08991 p->dialing = 1;
08992 p->dop.dialstr[0] = '\0';
08993 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08994 ast_setstate(ast, AST_STATE_DIALING);
08995 }
08996 }
08997 }
08998 }
08999 }
09000 }
09001 } else
09002 f = &p->subs[idx].f;
09003
09004 if (f) {
09005 switch (f->frametype) {
09006 case AST_FRAME_DTMF_BEGIN:
09007 case AST_FRAME_DTMF_END:
09008 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
09009 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
09010 } else {
09011 dahdi_handle_dtmf(ast, idx, &f);
09012 }
09013 break;
09014 case AST_FRAME_VOICE:
09015 if (p->cidspill || p->cid_suppress_expire) {
09016
09017 p->subs[idx].f.frametype = AST_FRAME_NULL;
09018 p->subs[idx].f.subclass.integer = 0;
09019 p->subs[idx].f.samples = 0;
09020 p->subs[idx].f.mallocd = 0;
09021 p->subs[idx].f.offset = 0;
09022 p->subs[idx].f.data.ptr = NULL;
09023 p->subs[idx].f.datalen= 0;
09024 }
09025 break;
09026 default:
09027 break;
09028 }
09029 }
09030
09031
09032 if (p->fake_event)
09033 ast_set_flag(ast, AST_FLAG_EXCEPTION);
09034
09035 ast_mutex_unlock(&p->lock);
09036 return f;
09037 }
09038
09039 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09040 {
09041 int sent=0;
09042 int size;
09043 int res;
09044 int fd;
09045 fd = p->subs[idx].dfd;
09046 while (len) {
09047 size = len;
09048 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09049 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09050 res = write(fd, buf, size);
09051 if (res != size) {
09052 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09053 return sent;
09054 }
09055 len -= size;
09056 buf += size;
09057 }
09058 return sent;
09059 }
09060
09061 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09062 {
09063 struct dahdi_pvt *p = ast->tech_pvt;
09064 int res;
09065 int idx;
09066 idx = dahdi_get_index(ast, p, 0);
09067 if (idx < 0) {
09068 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09069 return -1;
09070 }
09071
09072
09073 if (frame->frametype != AST_FRAME_VOICE) {
09074 if (frame->frametype != AST_FRAME_IMAGE)
09075 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09076 return 0;
09077 }
09078 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09079 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09080 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09081 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09082 return -1;
09083 }
09084 if (p->dialing) {
09085 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09086 return 0;
09087 }
09088 if (!p->owner) {
09089 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09090 return 0;
09091 }
09092 if (p->cidspill) {
09093 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09094 ast->name);
09095 return 0;
09096 }
09097
09098 if (!frame->data.ptr || !frame->datalen)
09099 return 0;
09100
09101 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09102 if (!p->subs[idx].linear) {
09103 p->subs[idx].linear = 1;
09104 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09105 if (res)
09106 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09107 }
09108 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09109 } else {
09110
09111 if (p->subs[idx].linear) {
09112 p->subs[idx].linear = 0;
09113 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09114 if (res)
09115 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09116 }
09117 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09118 }
09119 if (res < 0) {
09120 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09121 return -1;
09122 }
09123 return 0;
09124 }
09125
09126 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09127 {
09128 struct dahdi_pvt *p = chan->tech_pvt;
09129 int res=-1;
09130 int idx;
09131 int func = DAHDI_FLASH;
09132
09133 ast_mutex_lock(&p->lock);
09134 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09135 switch (p->sig) {
09136 #if defined(HAVE_PRI)
09137 case SIG_PRI_LIB_HANDLE_CASES:
09138 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09139 ast_mutex_unlock(&p->lock);
09140 return res;
09141 #endif
09142 #if defined(HAVE_SS7)
09143 case SIG_SS7:
09144 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09145 ast_mutex_unlock(&p->lock);
09146 return res;
09147 #endif
09148 default:
09149 break;
09150 }
09151 #ifdef HAVE_OPENR2
09152 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09153 ast_mutex_unlock(&p->lock);
09154
09155
09156 return 0;
09157 }
09158 #endif
09159 idx = dahdi_get_index(chan, p, 0);
09160 if (idx == SUB_REAL) {
09161 switch (condition) {
09162 case AST_CONTROL_BUSY:
09163 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09164 break;
09165 case AST_CONTROL_RINGING:
09166 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09167
09168 if (chan->_state != AST_STATE_UP) {
09169 if ((chan->_state != AST_STATE_RING) ||
09170 ((p->sig != SIG_FXSKS) &&
09171 (p->sig != SIG_FXSLS) &&
09172 (p->sig != SIG_FXSGS)))
09173 ast_setstate(chan, AST_STATE_RINGING);
09174 }
09175 break;
09176 case AST_CONTROL_PROCEEDING:
09177 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09178
09179 res = 0;
09180 break;
09181 case AST_CONTROL_PROGRESS:
09182 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09183
09184 res = 0;
09185 break;
09186 case AST_CONTROL_CONGESTION:
09187 chan->hangupcause = AST_CAUSE_CONGESTION;
09188 break;
09189 case AST_CONTROL_HOLD:
09190 ast_moh_start(chan, data, p->mohinterpret);
09191 break;
09192 case AST_CONTROL_UNHOLD:
09193 ast_moh_stop(chan);
09194 break;
09195 case AST_CONTROL_RADIO_KEY:
09196 if (p->radio)
09197 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09198 res = 0;
09199 break;
09200 case AST_CONTROL_RADIO_UNKEY:
09201 if (p->radio)
09202 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09203 res = 0;
09204 break;
09205 case AST_CONTROL_FLASH:
09206
09207 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09208
09209 p->dop.dialstr[0] = '\0';
09210 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09211 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09212 chan->name, strerror(errno));
09213 } else
09214 res = 0;
09215 } else
09216 res = 0;
09217 break;
09218 case AST_CONTROL_SRCUPDATE:
09219 res = 0;
09220 break;
09221 case -1:
09222 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09223 break;
09224 }
09225 } else {
09226 res = 0;
09227 }
09228 ast_mutex_unlock(&p->lock);
09229 return res;
09230 }
09231
09232 #if defined(HAVE_PRI)
09233 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09234 #else
09235 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09236 #endif
09237 {
09238 struct ast_str *chan_name;
09239 int x, y;
09240
09241
09242 if (!(chan_name = ast_str_create(32))) {
09243 return NULL;
09244 }
09245 if (i->channel == CHAN_PSEUDO) {
09246 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09247 #if defined(HAVE_PRI)
09248 } else if (i->pri) {
09249 ast_mutex_lock(&i->pri->lock);
09250 y = ++i->pri->new_chan_seq;
09251 if (is_outgoing) {
09252 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09253 address[0] = '\0';
09254 } else if (ast_strlen_zero(i->cid_subaddr)) {
09255
09256 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09257 } else {
09258
09259 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09260 i->cid_subaddr, y);
09261 }
09262 ast_mutex_unlock(&i->pri->lock);
09263 #endif
09264 } else {
09265 y = 1;
09266 do {
09267 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09268 for (x = 0; x < 3; ++x) {
09269 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09270 i->subs[x].owner->name + 6)) {
09271 break;
09272 }
09273 }
09274 ++y;
09275 } while (x < 3);
09276 }
09277 return chan_name;
09278 }
09279
09280 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09281 {
09282 struct ast_channel *tmp;
09283 format_t deflaw;
09284 int x;
09285 int features;
09286 struct ast_str *chan_name;
09287 struct ast_variable *v;
09288
09289 if (i->subs[idx].owner) {
09290 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09291 return NULL;
09292 }
09293
09294 #if defined(HAVE_PRI)
09295
09296
09297
09298
09299 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09300 #else
09301 chan_name = create_channel_name(i);
09302 #endif
09303 if (!chan_name) {
09304 return NULL;
09305 }
09306
09307 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));
09308 ast_free(chan_name);
09309 if (!tmp)
09310 return NULL;
09311 tmp->tech = &dahdi_tech;
09312 #if defined(HAVE_PRI)
09313 if (i->pri) {
09314 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09315 }
09316 #endif
09317 ast_channel_cc_params_init(tmp, i->cc_params);
09318 if (law) {
09319 i->law = law;
09320 if (law == DAHDI_LAW_ALAW) {
09321 deflaw = AST_FORMAT_ALAW;
09322 } else {
09323 deflaw = AST_FORMAT_ULAW;
09324 }
09325 } else {
09326 switch (i->sig) {
09327 case SIG_PRI_LIB_HANDLE_CASES:
09328
09329 i->law = (i->law_default == DAHDI_LAW_ALAW)
09330 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09331 break;
09332 default:
09333 i->law = i->law_default;
09334 break;
09335 }
09336 if (i->law_default == DAHDI_LAW_ALAW) {
09337 deflaw = AST_FORMAT_ALAW;
09338 } else {
09339 deflaw = AST_FORMAT_ULAW;
09340 }
09341 }
09342 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09343 tmp->nativeformats = deflaw;
09344
09345 tmp->rawreadformat = deflaw;
09346 tmp->readformat = deflaw;
09347 tmp->rawwriteformat = deflaw;
09348 tmp->writeformat = deflaw;
09349 i->subs[idx].linear = 0;
09350 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09351 features = 0;
09352 if (idx == SUB_REAL) {
09353 if (i->busydetect && CANBUSYDETECT(i))
09354 features |= DSP_FEATURE_BUSY_DETECT;
09355 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09356 features |= DSP_FEATURE_CALL_PROGRESS;
09357 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09358 features |= DSP_FEATURE_WAITDIALTONE;
09359 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09360 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09361 features |= DSP_FEATURE_FAX_DETECT;
09362 }
09363 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09364 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09365 i->hardwaredtmf = 0;
09366 features |= DSP_FEATURE_DIGIT_DETECT;
09367 } else if (NEED_MFDETECT(i)) {
09368 i->hardwaredtmf = 1;
09369 features |= DSP_FEATURE_DIGIT_DETECT;
09370 }
09371 }
09372 if (features) {
09373 if (i->dsp) {
09374 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09375 } else {
09376 if (i->channel != CHAN_PSEUDO)
09377 i->dsp = ast_dsp_new();
09378 else
09379 i->dsp = NULL;
09380 if (i->dsp) {
09381 i->dsp_features = features;
09382 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09383
09384 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09385
09386
09387 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09388 features = 0;
09389 }
09390 #endif
09391 ast_dsp_set_features(i->dsp, features);
09392 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09393 if (!ast_strlen_zero(progzone))
09394 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09395 if (i->busydetect && CANBUSYDETECT(i)) {
09396 if(i->silencethreshold > 0)
09397 ast_dsp_set_threshold(i->dsp, i->silencethreshold);
09398 ast_dsp_set_busy_count(i->dsp, i->busycount);
09399 if(i->busytonelength > 0)
09400 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
09401 if((i->busytonelength == i->busyquietlength) && i->busycompare)
09402 ast_dsp_set_busy_compare(i->dsp, i->busycompare);
09403 }
09404 }
09405 }
09406 }
09407
09408 if (state == AST_STATE_RING)
09409 tmp->rings = 1;
09410 tmp->tech_pvt = i;
09411 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09412
09413 tmp->callgroup = i->callgroup;
09414 tmp->pickupgroup = i->pickupgroup;
09415 }
09416 if (!ast_strlen_zero(i->parkinglot))
09417 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09418 if (!ast_strlen_zero(i->language))
09419 ast_string_field_set(tmp, language, i->language);
09420 if (!i->owner)
09421 i->owner = tmp;
09422 if (!ast_strlen_zero(i->accountcode))
09423 ast_string_field_set(tmp, accountcode, i->accountcode);
09424 if (i->amaflags)
09425 tmp->amaflags = i->amaflags;
09426 i->subs[idx].owner = tmp;
09427 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09428 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09429 ast_string_field_set(tmp, call_forward, i->call_forward);
09430 }
09431
09432 if (!i->adsi)
09433 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09434 if (!ast_strlen_zero(i->exten))
09435 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09436 if (!ast_strlen_zero(i->rdnis)) {
09437 tmp->redirecting.from.number.valid = 1;
09438 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09439 }
09440 if (!ast_strlen_zero(i->dnid)) {
09441 tmp->dialed.number.str = ast_strdup(i->dnid);
09442 }
09443
09444
09445
09446 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09447 if (!ast_strlen_zero(i->cid_ani)) {
09448 tmp->caller.ani.number.valid = 1;
09449 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09450 } else if (!ast_strlen_zero(i->cid_num)) {
09451 tmp->caller.ani.number.valid = 1;
09452 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09453 }
09454 #else
09455 if (!ast_strlen_zero(i->cid_num)) {
09456 tmp->caller.ani.number.valid = 1;
09457 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09458 }
09459 #endif
09460 tmp->caller.id.name.presentation = i->callingpres;
09461 tmp->caller.id.number.presentation = i->callingpres;
09462 tmp->caller.id.number.plan = i->cid_ton;
09463 tmp->caller.ani2 = i->cid_ani2;
09464 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09465
09466 i->fake_event = 0;
09467
09468 dahdi_confmute(i, 0);
09469 i->muting = 0;
09470
09471 ast_jb_configure(tmp, &global_jbconf);
09472
09473 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
09474
09475 for (v = i->vars ; v ; v = v->next)
09476 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09477
09478 ast_module_ref(ast_module_info->self);
09479
09480 if (startpbx) {
09481 #ifdef HAVE_OPENR2
09482 if (i->mfcr2call) {
09483 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09484 }
09485 #endif
09486 if (ast_pbx_start(tmp)) {
09487 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09488 ast_hangup(tmp);
09489 return NULL;
09490 }
09491 }
09492 return tmp;
09493 }
09494
09495
09496 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09497 {
09498 char c;
09499
09500 *str = 0;
09501 for (;;)
09502 {
09503
09504 c = ast_waitfordigit(chan, ms);
09505
09506 if (c < 1)
09507 return c;
09508 *str++ = c;
09509 *str = 0;
09510 if (strchr(term, c))
09511 return 1;
09512 }
09513 }
09514
09515 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09516 {
09517 int j;
09518 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09519 for (;;)
09520 {
09521
09522 j = DAHDI_IOMUX_SIGEVENT;
09523
09524 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09525
09526 if (j & DAHDI_IOMUX_SIGEVENT) break;
09527 }
09528
09529 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09530 return 0;
09531 }
09532
09533
09534
09535
09536
09537
09538
09539
09540
09541
09542 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09543 {
09544 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09545 return analog_dnd(dahdichan->sig_pvt, flag);
09546 }
09547
09548 if (flag == -1) {
09549 return dahdichan->dnd;
09550 }
09551
09552
09553 dahdichan->dnd = flag;
09554 ast_verb(3, "%s DND on channel %d\n",
09555 flag? "Enabled" : "Disabled",
09556 dahdichan->channel);
09557 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09558 "Channel: DAHDI/%d\r\n"
09559 "Status: %s\r\n", dahdichan->channel,
09560 flag? "enabled" : "disabled");
09561
09562 return 0;
09563 }
09564
09565 static void *analog_ss_thread(void *data)
09566 {
09567 struct ast_channel *chan = data;
09568 struct dahdi_pvt *p = chan->tech_pvt;
09569 char exten[AST_MAX_EXTENSION] = "";
09570 char exten2[AST_MAX_EXTENSION] = "";
09571 unsigned char buf[256];
09572 char dtmfcid[300];
09573 char dtmfbuf[300];
09574 struct callerid_state *cs = NULL;
09575 char *name = NULL, *number = NULL;
09576 int distMatches;
09577 int curRingData[3];
09578 int receivedRingT;
09579 int counter1;
09580 int counter;
09581 int samples = 0;
09582 struct ast_smdi_md_message *smdi_msg = NULL;
09583 int flags = 0;
09584 int i;
09585 int timeout;
09586 int getforward = 0;
09587 char *s1, *s2;
09588 int len = 0;
09589 int res;
09590 int idx;
09591
09592 ast_mutex_lock(&ss_thread_lock);
09593 ss_thread_count++;
09594 ast_mutex_unlock(&ss_thread_lock);
09595
09596
09597
09598 if (!p) {
09599 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09600 ast_hangup(chan);
09601 goto quit;
09602 }
09603 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09604 idx = dahdi_get_index(chan, p, 1);
09605 if (idx < 0) {
09606 ast_log(LOG_WARNING, "Huh?\n");
09607 ast_hangup(chan);
09608 goto quit;
09609 }
09610 if (p->dsp)
09611 ast_dsp_digitreset(p->dsp);
09612 switch (p->sig) {
09613 case SIG_FEATD:
09614 case SIG_FEATDMF:
09615 case SIG_FEATDMF_TA:
09616 case SIG_E911:
09617 case SIG_FGC_CAMAMF:
09618 case SIG_FEATB:
09619 case SIG_EMWINK:
09620 case SIG_SF_FEATD:
09621 case SIG_SF_FEATDMF:
09622 case SIG_SF_FEATB:
09623 case SIG_SFWINK:
09624 if (dahdi_wink(p, idx))
09625 goto quit;
09626
09627 case SIG_EM:
09628 case SIG_EM_E1:
09629 case SIG_SF:
09630 case SIG_FGC_CAMA:
09631 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09632 if (p->dsp)
09633 ast_dsp_digitreset(p->dsp);
09634
09635 if (p->dsp) {
09636 if (NEED_MFDETECT(p))
09637 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09638 else
09639 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09640 }
09641 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09642
09643 if (!p->immediate)
09644
09645 res = ast_waitfordigit(chan, 5000);
09646 else
09647 res = 0;
09648 if (res > 0) {
09649
09650 dtmfbuf[0] = res;
09651 switch (p->sig) {
09652 case SIG_FEATD:
09653 case SIG_SF_FEATD:
09654 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09655 if (res > 0)
09656 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09657 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09658 break;
09659 case SIG_FEATDMF_TA:
09660 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09661 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09662 if (dahdi_wink(p, idx)) goto quit;
09663 dtmfbuf[0] = 0;
09664
09665 res = ast_waitfordigit(chan, 5000);
09666 if (res <= 0) break;
09667 dtmfbuf[0] = res;
09668
09669 case SIG_FEATDMF:
09670 case SIG_E911:
09671 case SIG_FGC_CAMAMF:
09672 case SIG_SF_FEATDMF:
09673 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09674
09675 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09676 {
09677 if (dahdi_wink(p, idx)) goto quit;
09678 dtmfbuf[0] = 0;
09679
09680 res = ast_waitfordigit(chan, 5000);
09681 if (res <= 0) break;
09682 dtmfbuf[0] = res;
09683 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09684 }
09685 if (res > 0) {
09686
09687 if (p->sig == SIG_E911)
09688 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09689 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09690 }
09691 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09692 break;
09693 case SIG_FEATB:
09694 case SIG_SF_FEATB:
09695 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09696 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09697 break;
09698 case SIG_EMWINK:
09699
09700
09701
09702
09703 if (res == '*') {
09704 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09705 if (res > 0)
09706 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09707 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09708 break;
09709 }
09710 default:
09711
09712 len = 1;
09713 dtmfbuf[len] = '\0';
09714 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09715 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09716 timeout = matchdigittimeout;
09717 } else {
09718 timeout = gendigittimeout;
09719 }
09720 res = ast_waitfordigit(chan, timeout);
09721 if (res < 0) {
09722 ast_debug(1, "waitfordigit returned < 0...\n");
09723 ast_hangup(chan);
09724 goto quit;
09725 } else if (res) {
09726 dtmfbuf[len++] = res;
09727 dtmfbuf[len] = '\0';
09728 } else {
09729 break;
09730 }
09731 }
09732 break;
09733 }
09734 }
09735 if (res == -1) {
09736 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09737 ast_hangup(chan);
09738 goto quit;
09739 } else if (res < 0) {
09740 ast_debug(1, "Got hung up before digits finished\n");
09741 ast_hangup(chan);
09742 goto quit;
09743 }
09744
09745 if (p->sig == SIG_FGC_CAMA) {
09746 char anibuf[100];
09747
09748 if (ast_safe_sleep(chan,1000) == -1) {
09749 ast_hangup(chan);
09750 goto quit;
09751 }
09752 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09753 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09754 res = my_getsigstr(chan, anibuf, "#", 10000);
09755 if ((res > 0) && (strlen(anibuf) > 2)) {
09756 if (anibuf[strlen(anibuf) - 1] == '#')
09757 anibuf[strlen(anibuf) - 1] = 0;
09758 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09759 }
09760 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09761 }
09762
09763 ast_copy_string(exten, dtmfbuf, sizeof(exten));
09764 if (ast_strlen_zero(exten))
09765 ast_copy_string(exten, "s", sizeof(exten));
09766 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09767
09768 if (exten[0] == '*') {
09769 char *stringp=NULL;
09770 ast_copy_string(exten2, exten, sizeof(exten2));
09771
09772 stringp=exten2 +1;
09773 s1 = strsep(&stringp, "*");
09774 s2 = strsep(&stringp, "*");
09775 if (s2) {
09776 if (!ast_strlen_zero(p->cid_num))
09777 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09778 else
09779 ast_set_callerid(chan, s1, NULL, s1);
09780 ast_copy_string(exten, s2, sizeof(exten));
09781 } else
09782 ast_copy_string(exten, s1, sizeof(exten));
09783 } else if (p->sig == SIG_FEATD)
09784 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09785 }
09786 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09787 if (exten[0] == '*') {
09788 char *stringp=NULL;
09789 ast_copy_string(exten2, exten, sizeof(exten2));
09790
09791 stringp=exten2 +1;
09792 s1 = strsep(&stringp, "#");
09793 s2 = strsep(&stringp, "#");
09794 if (s2) {
09795 if (!ast_strlen_zero(p->cid_num))
09796 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09797 else
09798 if (*(s1 + 2))
09799 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09800 ast_copy_string(exten, s2 + 1, sizeof(exten));
09801 } else
09802 ast_copy_string(exten, s1 + 2, sizeof(exten));
09803 } else
09804 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09805 }
09806 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09807 if (exten[0] == '*') {
09808 char *stringp=NULL;
09809 ast_copy_string(exten2, exten, sizeof(exten2));
09810
09811 stringp=exten2 +1;
09812 s1 = strsep(&stringp, "#");
09813 s2 = strsep(&stringp, "#");
09814 if (s2 && (*(s2 + 1) == '0')) {
09815 if (*(s2 + 2))
09816 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
09817 }
09818 if (s1) ast_copy_string(exten, s1, sizeof(exten));
09819 else ast_copy_string(exten, "911", sizeof(exten));
09820 } else
09821 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
09822 }
09823 if (p->sig == SIG_FEATB) {
09824 if (exten[0] == '*') {
09825 char *stringp=NULL;
09826 ast_copy_string(exten2, exten, sizeof(exten2));
09827
09828 stringp=exten2 +1;
09829 s1 = strsep(&stringp, "#");
09830 ast_copy_string(exten, exten2 + 1, sizeof(exten));
09831 } else
09832 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
09833 }
09834 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09835 dahdi_wink(p, idx);
09836
09837
09838
09839 if (ast_safe_sleep(chan,100)) goto quit;
09840 }
09841 dahdi_enable_ec(p);
09842 if (NEED_MFDETECT(p)) {
09843 if (p->dsp) {
09844 if (!p->hardwaredtmf)
09845 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09846 else {
09847 ast_dsp_free(p->dsp);
09848 p->dsp = NULL;
09849 }
09850 }
09851 }
09852
09853 if (ast_exists_extension(chan, chan->context, exten, 1,
09854 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09855 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09856 if (p->dsp) ast_dsp_digitreset(p->dsp);
09857 res = ast_pbx_run(chan);
09858 if (res) {
09859 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09860 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09861 }
09862 goto quit;
09863 } else {
09864 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
09865 sleep(2);
09866 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
09867 if (res < 0)
09868 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
09869 else
09870 sleep(1);
09871 res = ast_streamfile(chan, "ss-noservice", chan->language);
09872 if (res >= 0)
09873 ast_waitstream(chan, "");
09874 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09875 ast_hangup(chan);
09876 goto quit;
09877 }
09878 break;
09879 case SIG_FXOLS:
09880 case SIG_FXOGS:
09881 case SIG_FXOKS:
09882
09883 timeout = firstdigittimeout;
09884
09885
09886 if (p->subs[SUB_THREEWAY].owner)
09887 timeout = 999999;
09888 while (len < AST_MAX_EXTENSION-1) {
09889
09890
09891 if (p->immediate)
09892 res = 's';
09893 else
09894 res = ast_waitfordigit(chan, timeout);
09895 timeout = 0;
09896 if (res < 0) {
09897 ast_debug(1, "waitfordigit returned < 0...\n");
09898 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09899 ast_hangup(chan);
09900 goto quit;
09901 } else if (res) {
09902 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
09903 exten[len++]=res;
09904 exten[len] = '\0';
09905 }
09906 if (!ast_ignore_pattern(chan->context, exten))
09907 tone_zone_play_tone(p->subs[idx].dfd, -1);
09908 else
09909 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09910 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
09911 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
09912 if (getforward) {
09913
09914 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
09915 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
09916 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09917 if (res)
09918 break;
09919 usleep(500000);
09920 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09921 sleep(1);
09922 memset(exten, 0, sizeof(exten));
09923 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09924 len = 0;
09925 getforward = 0;
09926 } else {
09927 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09928 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09929 if (!ast_strlen_zero(p->cid_num)) {
09930 if (!p->hidecallerid)
09931 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09932 else
09933 ast_set_callerid(chan, NULL, NULL, p->cid_num);
09934 }
09935 if (!ast_strlen_zero(p->cid_name)) {
09936 if (!p->hidecallerid)
09937 ast_set_callerid(chan, NULL, p->cid_name, NULL);
09938 }
09939 ast_setstate(chan, AST_STATE_RING);
09940 dahdi_enable_ec(p);
09941 res = ast_pbx_run(chan);
09942 if (res) {
09943 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09944 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09945 }
09946 goto quit;
09947 }
09948 } else {
09949
09950
09951 timeout = matchdigittimeout;
09952 }
09953 } else if (res == 0) {
09954 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
09955 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09956 dahdi_wait_event(p->subs[idx].dfd);
09957 ast_hangup(chan);
09958 goto quit;
09959 } else if (p->callwaiting && !strcmp(exten, "*70")) {
09960 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
09961
09962 p->callwaiting = 0;
09963 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09964 if (res) {
09965 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09966 chan->name, strerror(errno));
09967 }
09968 len = 0;
09969 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
09970 memset(exten, 0, sizeof(exten));
09971 timeout = firstdigittimeout;
09972
09973 } else if (!strcmp(exten,ast_pickup_ext())) {
09974
09975
09976
09977
09978 if (idx == SUB_REAL) {
09979
09980 if (p->subs[SUB_THREEWAY].owner) {
09981
09982
09983 alloc_sub(p, SUB_CALLWAIT);
09984 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
09985 unalloc_sub(p, SUB_THREEWAY);
09986 }
09987 dahdi_enable_ec(p);
09988 if (ast_pickup_call(chan)) {
09989 ast_debug(1, "No call pickup possible...\n");
09990 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09991 dahdi_wait_event(p->subs[idx].dfd);
09992 }
09993 ast_hangup(chan);
09994 goto quit;
09995 } else {
09996 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
09997 ast_hangup(chan);
09998 goto quit;
09999 }
10000
10001 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
10002 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
10003
10004 p->hidecallerid = 1;
10005 ast_party_number_free(&chan->caller.id.number);
10006 ast_party_number_init(&chan->caller.id.number);
10007 ast_party_name_free(&chan->caller.id.name);
10008 ast_party_name_init(&chan->caller.id.name);
10009 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10010 if (res) {
10011 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10012 chan->name, strerror(errno));
10013 }
10014 len = 0;
10015 memset(exten, 0, sizeof(exten));
10016 timeout = firstdigittimeout;
10017 } else if (p->callreturn && !strcmp(exten, "*69")) {
10018 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10019 break;
10020 } else if (!strcmp(exten, "*78")) {
10021 dahdi_dnd(p, 1);
10022
10023 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10024 getforward = 0;
10025 memset(exten, 0, sizeof(exten));
10026 len = 0;
10027 } else if (!strcmp(exten, "*79")) {
10028 dahdi_dnd(p, 0);
10029
10030 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10031 getforward = 0;
10032 memset(exten, 0, sizeof(exten));
10033 len = 0;
10034 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10035 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10036 getforward = 1;
10037 memset(exten, 0, sizeof(exten));
10038 len = 0;
10039 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10040 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10041 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10042 memset(p->call_forward, 0, sizeof(p->call_forward));
10043 getforward = 0;
10044 memset(exten, 0, sizeof(exten));
10045 len = 0;
10046 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10047 p->subs[SUB_THREEWAY].owner &&
10048 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10049
10050
10051 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10052 ast_verb(3, "Parking call to '%s'\n", chan->name);
10053 break;
10054 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10055 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10056
10057 p->hidecallerid = 0;
10058 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10059 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10060 if (res) {
10061 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10062 chan->name, strerror(errno));
10063 }
10064 len = 0;
10065 memset(exten, 0, sizeof(exten));
10066 timeout = firstdigittimeout;
10067 } else if (!strcmp(exten, "*0")) {
10068 struct ast_channel *nbridge =
10069 p->subs[SUB_THREEWAY].owner;
10070 struct dahdi_pvt *pbridge = NULL;
10071
10072 if (nbridge && ast_bridged_channel(nbridge))
10073 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10074 if (nbridge && pbridge &&
10075 (nbridge->tech == &dahdi_tech) &&
10076 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10077 ISTRUNK(pbridge)) {
10078 int func = DAHDI_FLASH;
10079
10080 p->dop.dialstr[0] = '\0';
10081
10082 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10083 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10084 nbridge->name, strerror(errno));
10085 }
10086 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10087 unalloc_sub(p, SUB_THREEWAY);
10088 p->owner = p->subs[SUB_REAL].owner;
10089 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10090 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10091 ast_hangup(chan);
10092 goto quit;
10093 } else {
10094 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10095 dahdi_wait_event(p->subs[idx].dfd);
10096 tone_zone_play_tone(p->subs[idx].dfd, -1);
10097 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10098 unalloc_sub(p, SUB_THREEWAY);
10099 p->owner = p->subs[SUB_REAL].owner;
10100 ast_hangup(chan);
10101 goto quit;
10102 }
10103 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10104 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10105 && ((exten[0] != '*') || (strlen(exten) > 2))) {
10106 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10107 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10108 chan->context);
10109 break;
10110 }
10111 if (!timeout)
10112 timeout = gendigittimeout;
10113 if (len && !ast_ignore_pattern(chan->context, exten))
10114 tone_zone_play_tone(p->subs[idx].dfd, -1);
10115 }
10116 break;
10117 case SIG_FXSLS:
10118 case SIG_FXSGS:
10119 case SIG_FXSKS:
10120
10121 if (p->use_smdi && p->smdi_iface) {
10122 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10123
10124 if (smdi_msg != NULL) {
10125 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10126
10127 if (smdi_msg->type == 'B')
10128 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10129 else if (smdi_msg->type == 'N')
10130 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10131
10132 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10133 } else {
10134 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10135 }
10136 }
10137
10138 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10139 number = smdi_msg->calling_st;
10140
10141
10142
10143
10144 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10145 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10146
10147 if (p->cid_signalling == CID_SIG_DTMF) {
10148 int k = 0;
10149 cs = NULL;
10150 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10151 dahdi_setlinear(p->subs[idx].dfd, 0);
10152
10153
10154
10155
10156
10157
10158 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10159 res = 4000;
10160 for (;;) {
10161 struct ast_frame *f;
10162 res = ast_waitfor(chan, res);
10163 if (res <= 0) {
10164
10165
10166
10167
10168
10169 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10170 "Exiting simple switch\n");
10171 ast_hangup(chan);
10172 goto quit;
10173 }
10174 f = ast_read(chan);
10175 if (!f)
10176 break;
10177 if (f->frametype == AST_FRAME_DTMF) {
10178 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10179 dtmfbuf[k++] = f->subclass.integer;
10180 }
10181 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10182 res = 4000;
10183 }
10184 ast_frfree(f);
10185 if (chan->_state == AST_STATE_RING ||
10186 chan->_state == AST_STATE_RINGING)
10187 break;
10188 }
10189 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10190 dtmfbuf[k] = '\0';
10191 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10192
10193 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10194 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10195 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10196
10197 if (!ast_strlen_zero(dtmfcid))
10198 number = dtmfcid;
10199 else
10200 number = NULL;
10201
10202 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10203 cs = callerid_new(p->cid_signalling);
10204 if (cs) {
10205 samples = 0;
10206 #if 1
10207 bump_gains(p);
10208 #endif
10209
10210 dahdi_setlinear(p->subs[idx].dfd, 0);
10211
10212
10213 for (;;) {
10214 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10215 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10216 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10217 callerid_free(cs);
10218 ast_hangup(chan);
10219 goto quit;
10220 }
10221 if (i & DAHDI_IOMUX_SIGEVENT) {
10222 res = dahdi_get_event(p->subs[idx].dfd);
10223 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10224 if (res == DAHDI_EVENT_NOALARM) {
10225 p->inalarm = 0;
10226 }
10227
10228 if (p->cid_signalling == CID_SIG_V23_JP) {
10229 if (res == DAHDI_EVENT_RINGBEGIN) {
10230 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10231 usleep(1);
10232 }
10233 } else {
10234 res = 0;
10235 break;
10236 }
10237 } else if (i & DAHDI_IOMUX_READ) {
10238 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10239 if (res < 0) {
10240 if (errno != ELAST) {
10241 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10242 callerid_free(cs);
10243 ast_hangup(chan);
10244 goto quit;
10245 }
10246 break;
10247 }
10248 samples += res;
10249
10250 if (p->cid_signalling == CID_SIG_V23_JP) {
10251 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10252 } else {
10253 res = callerid_feed(cs, buf, res, AST_LAW(p));
10254 }
10255 if (res < 0) {
10256
10257
10258
10259
10260 ast_log(LOG_WARNING,
10261 "Failed to decode CallerID on channel '%s'\n",
10262 chan->name);
10263 break;
10264 } else if (res)
10265 break;
10266 else if (samples > (8000 * 10))
10267 break;
10268 }
10269 }
10270 if (res == 1) {
10271 callerid_get(cs, &name, &number, &flags);
10272 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10273 }
10274
10275 if (p->cid_signalling == CID_SIG_V23_JP) {
10276 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10277 usleep(1);
10278 }
10279
10280
10281 res = 4000;
10282 for (;;) {
10283 struct ast_frame *f;
10284 res = ast_waitfor(chan, res);
10285 if (res <= 0) {
10286 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10287 "Exiting simple switch\n");
10288 ast_hangup(chan);
10289 goto quit;
10290 }
10291 if (!(f = ast_read(chan))) {
10292 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10293 ast_hangup(chan);
10294 goto quit;
10295 }
10296 ast_frfree(f);
10297 if (chan->_state == AST_STATE_RING ||
10298 chan->_state == AST_STATE_RINGING)
10299 break;
10300 }
10301
10302
10303
10304 if (p->usedistinctiveringdetection) {
10305 len = 0;
10306 distMatches = 0;
10307
10308 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10309 curRingData[receivedRingT] = 0;
10310 receivedRingT = 0;
10311 counter = 0;
10312 counter1 = 0;
10313
10314 if (strcmp(p->context,p->defcontext) != 0) {
10315 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10316 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10317 }
10318
10319 for (;;) {
10320 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10321 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10322 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10323 callerid_free(cs);
10324 ast_hangup(chan);
10325 goto quit;
10326 }
10327 if (i & DAHDI_IOMUX_SIGEVENT) {
10328 res = dahdi_get_event(p->subs[idx].dfd);
10329 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10330 if (res == DAHDI_EVENT_NOALARM) {
10331 p->inalarm = 0;
10332 }
10333 res = 0;
10334
10335
10336 curRingData[receivedRingT] = p->ringt;
10337
10338 if (p->ringt < p->ringt_base/2)
10339 break;
10340
10341
10342 if (++receivedRingT == ARRAY_LEN(curRingData))
10343 break;
10344 } else if (i & DAHDI_IOMUX_READ) {
10345 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10346 if (res < 0) {
10347 if (errno != ELAST) {
10348 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10349 callerid_free(cs);
10350 ast_hangup(chan);
10351 goto quit;
10352 }
10353 break;
10354 }
10355 if (p->ringt > 0) {
10356 if (!(--p->ringt)) {
10357 res = -1;
10358 break;
10359 }
10360 }
10361 }
10362 }
10363
10364 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10365 for (counter = 0; counter < 3; counter++) {
10366
10367
10368 distMatches = 0;
10369 for (counter1 = 0; counter1 < 3; counter1++) {
10370 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10371 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10372 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10373 curRingData[counter1]);
10374 distMatches++;
10375 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10376 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10377 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10378 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10379 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10380 distMatches++;
10381 }
10382 }
10383
10384 if (distMatches == 3) {
10385
10386 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10387 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10388 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10389 break;
10390 }
10391 }
10392 }
10393
10394 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10395 #if 1
10396 restore_gains(p);
10397 #endif
10398 } else
10399 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10400 } else {
10401 ast_log(LOG_WARNING, "Channel %s in prering "
10402 "state, but I have nothing to do. "
10403 "Terminating simple switch, should be "
10404 "restarted by the actual ring.\n",
10405 chan->name);
10406 ast_hangup(chan);
10407 goto quit;
10408 }
10409 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10410 if (p->cid_signalling == CID_SIG_DTMF) {
10411 int k = 0;
10412 cs = NULL;
10413 dahdi_setlinear(p->subs[idx].dfd, 0);
10414 res = 2000;
10415 for (;;) {
10416 struct ast_frame *f;
10417 res = ast_waitfor(chan, res);
10418 if (res <= 0) {
10419 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10420 "Exiting simple switch\n");
10421 ast_hangup(chan);
10422 return NULL;
10423 }
10424 f = ast_read(chan);
10425 if (f->frametype == AST_FRAME_DTMF) {
10426 dtmfbuf[k++] = f->subclass.integer;
10427 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10428 res = 2000;
10429 }
10430 ast_frfree(f);
10431
10432 if (p->ringt_base == p->ringt)
10433 break;
10434 }
10435 dtmfbuf[k] = '\0';
10436 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10437
10438 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10439 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10440 dtmfcid, flags);
10441
10442 if (!ast_strlen_zero(dtmfcid))
10443 number = dtmfcid;
10444 else
10445 number = NULL;
10446
10447 } else {
10448
10449 cs = callerid_new(p->cid_signalling);
10450 if (cs) {
10451 #if 1
10452 bump_gains(p);
10453 #endif
10454 samples = 0;
10455 len = 0;
10456 distMatches = 0;
10457
10458 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10459 curRingData[receivedRingT] = 0;
10460 receivedRingT = 0;
10461 counter = 0;
10462 counter1 = 0;
10463
10464 if (strcmp(p->context,p->defcontext) != 0) {
10465 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10466 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10467 }
10468
10469
10470 dahdi_setlinear(p->subs[idx].dfd, 0);
10471 for (;;) {
10472 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10473 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10474 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10475 callerid_free(cs);
10476 ast_hangup(chan);
10477 goto quit;
10478 }
10479 if (i & DAHDI_IOMUX_SIGEVENT) {
10480 res = dahdi_get_event(p->subs[idx].dfd);
10481 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10482 if (res == DAHDI_EVENT_NOALARM) {
10483 p->inalarm = 0;
10484 }
10485
10486 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10487 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10488 p->polarity = POLARITY_IDLE;
10489 callerid_free(cs);
10490 ast_hangup(chan);
10491 goto quit;
10492 }
10493 res = 0;
10494
10495
10496 curRingData[receivedRingT] = p->ringt;
10497
10498 if (p->ringt < p->ringt_base/2)
10499 break;
10500
10501
10502 if (++receivedRingT == ARRAY_LEN(curRingData))
10503 break;
10504 } else if (i & DAHDI_IOMUX_READ) {
10505 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10506 if (res < 0) {
10507 if (errno != ELAST) {
10508 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10509 callerid_free(cs);
10510 ast_hangup(chan);
10511 goto quit;
10512 }
10513 break;
10514 }
10515 if (p->ringt > 0) {
10516 if (!(--p->ringt)) {
10517 res = -1;
10518 break;
10519 }
10520 }
10521 samples += res;
10522 res = callerid_feed(cs, buf, res, AST_LAW(p));
10523 if (res < 0) {
10524
10525
10526
10527
10528 ast_log(LOG_WARNING,
10529 "Failed to decode CallerID on channel '%s'\n",
10530 chan->name);
10531 break;
10532 } else if (res)
10533 break;
10534 else if (samples > (8000 * 10))
10535 break;
10536 }
10537 }
10538 if (res == 1) {
10539 callerid_get(cs, &name, &number, &flags);
10540 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10541 }
10542 if (distinctiveringaftercid == 1) {
10543
10544 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10545 curRingData[receivedRingT] = 0;
10546 }
10547 receivedRingT = 0;
10548 ast_verb(3, "Detecting post-CID distinctive ring\n");
10549 for (;;) {
10550 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10551 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10552 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10553 callerid_free(cs);
10554 ast_hangup(chan);
10555 goto quit;
10556 }
10557 if (i & DAHDI_IOMUX_SIGEVENT) {
10558 res = dahdi_get_event(p->subs[idx].dfd);
10559 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10560 if (res == DAHDI_EVENT_NOALARM) {
10561 p->inalarm = 0;
10562 }
10563 res = 0;
10564
10565
10566 curRingData[receivedRingT] = p->ringt;
10567
10568 if (p->ringt < p->ringt_base/2)
10569 break;
10570
10571
10572 if (++receivedRingT == ARRAY_LEN(curRingData))
10573 break;
10574 } else if (i & DAHDI_IOMUX_READ) {
10575 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10576 if (res < 0) {
10577 if (errno != ELAST) {
10578 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10579 callerid_free(cs);
10580 ast_hangup(chan);
10581 goto quit;
10582 }
10583 break;
10584 }
10585 if (p->ringt > 0) {
10586 if (!(--p->ringt)) {
10587 res = -1;
10588 break;
10589 }
10590 }
10591 }
10592 }
10593 }
10594 if (p->usedistinctiveringdetection) {
10595
10596 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10597
10598 for (counter = 0; counter < 3; counter++) {
10599
10600
10601
10602 ast_verb(3, "Checking %d,%d,%d\n",
10603 p->drings.ringnum[counter].ring[0],
10604 p->drings.ringnum[counter].ring[1],
10605 p->drings.ringnum[counter].ring[2]);
10606 distMatches = 0;
10607 for (counter1 = 0; counter1 < 3; counter1++) {
10608 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10609 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10610 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10611 curRingData[counter1]);
10612 distMatches++;
10613 }
10614 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10615 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10616 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10617 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10618 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10619 distMatches++;
10620 }
10621 }
10622 if (distMatches == 3) {
10623
10624 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10625 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10626 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10627 break;
10628 }
10629 }
10630 }
10631
10632 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10633 #if 1
10634 restore_gains(p);
10635 #endif
10636 if (res < 0) {
10637 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10638 }
10639 } else
10640 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10641 }
10642 } else
10643 cs = NULL;
10644
10645 if (number)
10646 ast_shrink_phone_number(number);
10647 ast_set_callerid(chan, number, name, number);
10648
10649 if (smdi_msg)
10650 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10651
10652 if (cs)
10653 callerid_free(cs);
10654
10655 my_handle_notify_message(chan, p, flags, -1);
10656
10657 ast_setstate(chan, AST_STATE_RING);
10658 chan->rings = 1;
10659 p->ringt = p->ringt_base;
10660 res = ast_pbx_run(chan);
10661 if (res) {
10662 ast_hangup(chan);
10663 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10664 }
10665 goto quit;
10666 default:
10667 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10668 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10669 if (res < 0)
10670 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10671 }
10672 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10673 if (res < 0)
10674 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10675 ast_hangup(chan);
10676 quit:
10677 ast_mutex_lock(&ss_thread_lock);
10678 ss_thread_count--;
10679 ast_cond_signal(&ss_thread_complete);
10680 ast_mutex_unlock(&ss_thread_lock);
10681 return NULL;
10682 }
10683
10684 struct mwi_thread_data {
10685 struct dahdi_pvt *pvt;
10686 unsigned char buf[READ_SIZE];
10687 size_t len;
10688 };
10689
10690 static int calc_energy(const unsigned char *buf, int len, format_t law)
10691 {
10692 int x;
10693 int sum = 0;
10694
10695 if (!len)
10696 return 0;
10697
10698 for (x = 0; x < len; x++)
10699 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10700
10701 return sum / len;
10702 }
10703
10704 static void *mwi_thread(void *data)
10705 {
10706 struct mwi_thread_data *mtd = data;
10707 struct callerid_state *cs;
10708 pthread_t threadid;
10709 int samples = 0;
10710 char *name, *number;
10711 int flags;
10712 int i, res;
10713 unsigned int spill_done = 0;
10714 int spill_result = -1;
10715
10716 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10717 mtd->pvt->mwimonitoractive = 0;
10718
10719 return NULL;
10720 }
10721
10722 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10723
10724 bump_gains(mtd->pvt);
10725
10726 for (;;) {
10727 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10728 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10729 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10730 goto quit;
10731 }
10732
10733 if (i & DAHDI_IOMUX_SIGEVENT) {
10734 struct ast_channel *chan;
10735
10736
10737
10738
10739 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10740
10741 switch (res) {
10742 case DAHDI_EVENT_NEONMWI_ACTIVE:
10743 case DAHDI_EVENT_NEONMWI_INACTIVE:
10744 case DAHDI_EVENT_NONE:
10745 case DAHDI_EVENT_BITSCHANGED:
10746 break;
10747 case DAHDI_EVENT_NOALARM:
10748 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10749 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10750
10751 analog_p->inalarm = 0;
10752 }
10753 mtd->pvt->inalarm = 0;
10754 handle_clear_alarms(mtd->pvt);
10755 break;
10756 case DAHDI_EVENT_ALARM:
10757 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10758 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10759
10760 analog_p->inalarm = 1;
10761 }
10762 mtd->pvt->inalarm = 1;
10763 res = get_alarms(mtd->pvt);
10764 handle_alarms(mtd->pvt, res);
10765 break;
10766 default:
10767 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
10768 callerid_free(cs);
10769
10770 restore_gains(mtd->pvt);
10771 mtd->pvt->ringt = mtd->pvt->ringt_base;
10772
10773 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10774 int result;
10775 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10776 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10777 } else {
10778 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10779 }
10780 if (result) {
10781 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10782 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10783 if (res < 0)
10784 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10785 ast_hangup(chan);
10786 goto quit;
10787 }
10788 goto quit_no_clean;
10789
10790 } else {
10791 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10792 }
10793 }
10794 } else if (i & DAHDI_IOMUX_READ) {
10795 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10796 if (errno != ELAST) {
10797 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10798 goto quit;
10799 }
10800 break;
10801 }
10802 samples += res;
10803 if (!spill_done) {
10804 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10805
10806
10807
10808
10809 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10810 break;
10811 } else if (spill_result) {
10812 spill_done = 1;
10813 }
10814 } else {
10815
10816
10817
10818 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
10819 break;
10820 }
10821 if (samples > (8000 * 4))
10822 break;
10823 }
10824 }
10825
10826 if (spill_result == 1) {
10827 callerid_get(cs, &name, &number, &flags);
10828 if (flags & CID_MSGWAITING) {
10829 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
10830 notify_message(mtd->pvt->mailbox, 1);
10831 } else if (flags & CID_NOMSGWAITING) {
10832 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
10833 notify_message(mtd->pvt->mailbox, 0);
10834 } else {
10835 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
10836 }
10837 }
10838
10839
10840 quit:
10841 callerid_free(cs);
10842
10843 restore_gains(mtd->pvt);
10844
10845 quit_no_clean:
10846 mtd->pvt->mwimonitoractive = 0;
10847
10848 ast_free(mtd);
10849
10850 return NULL;
10851 }
10852
10853
10854
10855
10856
10857
10858
10859
10860 static int mwi_send_init(struct dahdi_pvt * pvt)
10861 {
10862 int x, res;
10863
10864 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10865
10866 if (pvt->mwisend_rpas) {
10867 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10868 pvt->mwisendactive = 1;
10869 } else if (pvt->mwisend_fsk) {
10870 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10871 pvt->mwisendactive = 1;
10872 } else {
10873 pvt->mwisendactive = 0;
10874 return 0;
10875 }
10876 #else
10877 if (mwisend_rpas) {
10878 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10879 } else {
10880 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10881 }
10882 pvt->mwisendactive = 1;
10883 #endif
10884
10885 if (pvt->cidspill) {
10886 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
10887 ast_free(pvt->cidspill);
10888 pvt->cidspill = NULL;
10889 pvt->cidpos = 0;
10890 pvt->cidlen = 0;
10891 }
10892 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
10893 if (!pvt->cidspill) {
10894 pvt->mwisendactive = 0;
10895 return -1;
10896 }
10897 x = DAHDI_FLUSH_BOTH;
10898 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
10899 x = 3000;
10900 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
10901 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10902 if (pvt->mwisend_fsk) {
10903 #endif
10904 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
10905 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
10906 pvt->cidpos = 0;
10907 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10908 }
10909 #endif
10910 return 0;
10911 }
10912
10913 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
10914 {
10915 struct timeval now;
10916 int res;
10917
10918
10919
10920
10921 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
10922 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10923 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10924
10925 switch ( pvt->mwisend_data.mwisend_current) {
10926 case MWI_SEND_SA:
10927
10928 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
10929 if (res) {
10930 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
10931 goto quit;
10932 }
10933 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
10934 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
10935 break;
10936 case MWI_SEND_SA_WAIT:
10937 break;
10938 case MWI_SEND_PAUSE:
10939 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10940 if (pvt->mwisend_fsk) {
10941 #endif
10942 gettimeofday(&now, NULL);
10943 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
10944 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10945 }
10946 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10947 } else {
10948 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10949 }
10950 #endif
10951 break;
10952 case MWI_SEND_SPILL:
10953
10954 if(0 < num_read) {
10955 if (num_read > pvt->cidlen - pvt->cidpos)
10956 num_read = pvt->cidlen - pvt->cidpos;
10957 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
10958 if (res > 0) {
10959 pvt->cidpos += res;
10960 if (pvt->cidpos >= pvt->cidlen) {
10961 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10962 }
10963 } else {
10964 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
10965 goto quit;
10966 }
10967 }
10968 break;
10969 case MWI_SEND_CLEANUP:
10970
10971 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10972 break;
10973 default:
10974
10975 goto quit;
10976 }
10977 }
10978
10979 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
10980 if (pvt->cidspill) {
10981 ast_free(pvt->cidspill);
10982 pvt->cidspill = NULL;
10983 pvt->cidpos = 0;
10984 pvt->cidlen = 0;
10985 }
10986 pvt->mwisendactive = 0;
10987 }
10988 return 0;
10989 quit:
10990 if (pvt->cidspill) {
10991 ast_free(pvt->cidspill);
10992 pvt->cidspill = NULL;
10993 pvt->cidpos = 0;
10994 pvt->cidlen = 0;
10995 }
10996 pvt->mwisendactive = 0;
10997 return -1;
10998 }
10999
11000 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
11001 {
11002 int handled = 0;
11003
11004 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
11005 switch (event) {
11006 case DAHDI_EVENT_RINGEROFF:
11007 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
11008 handled = 1;
11009
11010 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
11011 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
11012 ast_free(pvt->cidspill);
11013 pvt->cidspill = NULL;
11014 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11015 pvt->mwisendactive = 0;
11016 } else {
11017 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
11018 gettimeofday(&pvt->mwisend_data.pause, NULL);
11019 }
11020 }
11021 break;
11022
11023 case DAHDI_EVENT_RINGOFFHOOK:
11024 if (pvt->cidspill) {
11025 ast_free(pvt->cidspill);
11026 pvt->cidspill = NULL;
11027 pvt->cidpos = 0;
11028 pvt->cidlen = 0;
11029 }
11030 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11031 pvt->mwisendactive = 0;
11032 break;
11033 case DAHDI_EVENT_RINGERON:
11034 case DAHDI_EVENT_HOOKCOMPLETE:
11035 break;
11036 default:
11037 break;
11038 }
11039 }
11040 return handled;
11041 }
11042
11043
11044 static int dahdi_destroy_channel_bynum(int channel)
11045 {
11046 struct dahdi_pvt *cur;
11047
11048 ast_mutex_lock(&iflock);
11049 for (cur = iflist; cur; cur = cur->next) {
11050 if (cur->channel == channel) {
11051 int x = DAHDI_FLASH;
11052
11053
11054 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11055
11056 destroy_channel(cur, 1);
11057 ast_mutex_unlock(&iflock);
11058 ast_module_unref(ast_module_info->self);
11059 return RESULT_SUCCESS;
11060 }
11061 }
11062 ast_mutex_unlock(&iflock);
11063 return RESULT_FAILURE;
11064 }
11065
11066 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11067 {
11068 int res;
11069 pthread_t threadid;
11070 struct ast_channel *chan;
11071
11072
11073
11074 switch (event) {
11075 case DAHDI_EVENT_NONE:
11076 case DAHDI_EVENT_BITSCHANGED:
11077 break;
11078 case DAHDI_EVENT_WINKFLASH:
11079 case DAHDI_EVENT_RINGOFFHOOK:
11080 if (i->inalarm) break;
11081 if (i->radio) break;
11082
11083 switch (i->sig) {
11084 case SIG_FXOLS:
11085 case SIG_FXOGS:
11086 case SIG_FXOKS:
11087 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11088 if (res && (errno == EBUSY))
11089 break;
11090
11091
11092 ast_free(i->cidspill);
11093 i->cidspill = NULL;
11094 restore_conference(i);
11095
11096 if (i->immediate) {
11097 dahdi_enable_ec(i);
11098
11099 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11100 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11101 if (!chan) {
11102 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11103 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11104 if (res < 0)
11105 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11106 }
11107 } else {
11108
11109 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11110 if (chan) {
11111 if (has_voicemail(i))
11112 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11113 else
11114 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11115 if (res < 0)
11116 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11117 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11118 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11119 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11120 if (res < 0)
11121 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11122 ast_hangup(chan);
11123 }
11124 } else
11125 ast_log(LOG_WARNING, "Unable to create channel\n");
11126 }
11127 break;
11128 case SIG_FXSLS:
11129 case SIG_FXSGS:
11130 case SIG_FXSKS:
11131 i->ringt = i->ringt_base;
11132
11133 case SIG_EMWINK:
11134 case SIG_FEATD:
11135 case SIG_FEATDMF:
11136 case SIG_FEATDMF_TA:
11137 case SIG_E911:
11138 case SIG_FGC_CAMA:
11139 case SIG_FGC_CAMAMF:
11140 case SIG_FEATB:
11141 case SIG_EM:
11142 case SIG_EM_E1:
11143 case SIG_SFWINK:
11144 case SIG_SF_FEATD:
11145 case SIG_SF_FEATDMF:
11146 case SIG_SF_FEATB:
11147 case SIG_SF:
11148
11149 if (i->cid_start == CID_START_POLARITY_IN) {
11150 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11151 } else {
11152 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11153 }
11154
11155 if (!chan) {
11156 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11157 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11158 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11159 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11160 if (res < 0) {
11161 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11162 }
11163 ast_hangup(chan);
11164 }
11165 break;
11166 default:
11167 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11168 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11169 if (res < 0)
11170 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11171 return NULL;
11172 }
11173 break;
11174 case DAHDI_EVENT_NOALARM:
11175 switch (i->sig) {
11176 #if defined(HAVE_PRI)
11177 case SIG_PRI_LIB_HANDLE_CASES:
11178 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11179 break;
11180 #endif
11181 #if defined(HAVE_SS7)
11182 case SIG_SS7:
11183 sig_ss7_set_alarm(i->sig_pvt, 0);
11184 break;
11185 #endif
11186 default:
11187 i->inalarm = 0;
11188 break;
11189 }
11190 handle_clear_alarms(i);
11191 break;
11192 case DAHDI_EVENT_ALARM:
11193 switch (i->sig) {
11194 #if defined(HAVE_PRI)
11195 case SIG_PRI_LIB_HANDLE_CASES:
11196 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11197 break;
11198 #endif
11199 #if defined(HAVE_SS7)
11200 case SIG_SS7:
11201 sig_ss7_set_alarm(i->sig_pvt, 1);
11202 break;
11203 #endif
11204 default:
11205 i->inalarm = 1;
11206 break;
11207 }
11208 res = get_alarms(i);
11209 handle_alarms(i, res);
11210
11211 case DAHDI_EVENT_ONHOOK:
11212 if (i->radio)
11213 break;
11214
11215 switch (i->sig) {
11216 case SIG_FXOLS:
11217 case SIG_FXOGS:
11218 case SIG_FEATD:
11219 case SIG_FEATDMF:
11220 case SIG_FEATDMF_TA:
11221 case SIG_E911:
11222 case SIG_FGC_CAMA:
11223 case SIG_FGC_CAMAMF:
11224 case SIG_FEATB:
11225 case SIG_EM:
11226 case SIG_EM_E1:
11227 case SIG_EMWINK:
11228 case SIG_SF_FEATD:
11229 case SIG_SF_FEATDMF:
11230 case SIG_SF_FEATB:
11231 case SIG_SF:
11232 case SIG_SFWINK:
11233 case SIG_FXSLS:
11234 case SIG_FXSGS:
11235 case SIG_FXSKS:
11236 case SIG_FXOKS:
11237 dahdi_disable_ec(i);
11238
11239 #ifdef ZHONE_HACK
11240 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11241 usleep(1);
11242 #endif
11243 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11244 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11245 break;
11246 case SIG_SS7:
11247 case SIG_PRI_LIB_HANDLE_CASES:
11248 dahdi_disable_ec(i);
11249 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11250 break;
11251 default:
11252 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11253 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11254 return NULL;
11255 }
11256 break;
11257 case DAHDI_EVENT_POLARITY:
11258 switch (i->sig) {
11259 case SIG_FXSLS:
11260 case SIG_FXSKS:
11261 case SIG_FXSGS:
11262
11263
11264
11265
11266 if (i->hanguponpolarityswitch)
11267 i->polarity = POLARITY_REV;
11268 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11269 i->polarity = POLARITY_REV;
11270 ast_verb(2, "Starting post polarity "
11271 "CID detection on channel %d\n",
11272 i->channel);
11273 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11274 if (!chan) {
11275 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11276 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11277 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11278 }
11279 }
11280 break;
11281 default:
11282 ast_log(LOG_WARNING, "handle_init_event detected "
11283 "polarity reversal on non-FXO (SIG_FXS) "
11284 "interface %d\n", i->channel);
11285 }
11286 break;
11287 case DAHDI_EVENT_REMOVED:
11288 ast_log(LOG_NOTICE,
11289 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11290 i->channel);
11291 return i;
11292 case DAHDI_EVENT_NEONMWI_ACTIVE:
11293 if (i->mwimonitor_neon) {
11294 notify_message(i->mailbox, 1);
11295 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11296 }
11297 break;
11298 case DAHDI_EVENT_NEONMWI_INACTIVE:
11299 if (i->mwimonitor_neon) {
11300 notify_message(i->mailbox, 0);
11301 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11302 }
11303 break;
11304 }
11305 return NULL;
11306 }
11307
11308 static void *do_monitor(void *data)
11309 {
11310 int count, res, res2, spoint, pollres=0;
11311 struct dahdi_pvt *i;
11312 struct dahdi_pvt *last = NULL;
11313 struct dahdi_pvt *doomed;
11314 time_t thispass = 0, lastpass = 0;
11315 int found;
11316 char buf[1024];
11317 struct pollfd *pfds=NULL;
11318 int lastalloc = -1;
11319
11320
11321
11322 #if 0
11323 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11324 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11325 return NULL;
11326 }
11327 ast_debug(1, "Monitor starting...\n");
11328 #endif
11329 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11330
11331 for (;;) {
11332
11333 ast_mutex_lock(&iflock);
11334 if (!pfds || (lastalloc != ifcount)) {
11335 if (pfds) {
11336 ast_free(pfds);
11337 pfds = NULL;
11338 }
11339 if (ifcount) {
11340 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11341 ast_mutex_unlock(&iflock);
11342 return NULL;
11343 }
11344 }
11345 lastalloc = ifcount;
11346 }
11347
11348
11349 count = 0;
11350 for (i = iflist; i; i = i->next) {
11351 ast_mutex_lock(&i->lock);
11352 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11353 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11354 struct analog_pvt *p = i->sig_pvt;
11355
11356 if (!p)
11357 ast_log(LOG_ERROR, "No sig_pvt?\n");
11358
11359 if (!p->owner && !p->subs[SUB_REAL].owner) {
11360
11361 pfds[count].fd = i->subs[SUB_REAL].dfd;
11362 pfds[count].events = POLLPRI;
11363 pfds[count].revents = 0;
11364
11365 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11366 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11367 pfds[count].events |= POLLIN;
11368 }
11369 count++;
11370 }
11371 } else {
11372 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11373
11374 pfds[count].fd = i->subs[SUB_REAL].dfd;
11375 pfds[count].events = POLLPRI;
11376 pfds[count].revents = 0;
11377
11378
11379 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11380 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11381 pfds[count].events |= POLLIN;
11382 }
11383 count++;
11384 }
11385 }
11386 }
11387 ast_mutex_unlock(&i->lock);
11388 }
11389
11390 ast_mutex_unlock(&iflock);
11391
11392 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11393 pthread_testcancel();
11394
11395 res = poll(pfds, count, 1000);
11396 pthread_testcancel();
11397 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11398
11399
11400 if (res < 0) {
11401 if ((errno != EAGAIN) && (errno != EINTR))
11402 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11403 continue;
11404 }
11405
11406
11407 ast_mutex_lock(&iflock);
11408 found = 0;
11409 spoint = 0;
11410 lastpass = thispass;
11411 thispass = time(NULL);
11412 doomed = NULL;
11413 for (i = iflist;; i = i->next) {
11414 if (doomed) {
11415 int res;
11416 res = dahdi_destroy_channel_bynum(doomed->channel);
11417 if (res != RESULT_SUCCESS) {
11418 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11419 }
11420 doomed = NULL;
11421 }
11422 if (!i) {
11423 break;
11424 }
11425
11426 if (thispass != lastpass) {
11427 if (!found && ((i == last) || ((i == iflist) && !last))) {
11428 last = i;
11429 if (last) {
11430 struct analog_pvt *analog_p = last->sig_pvt;
11431
11432 if (analog_p
11433 && !last->mwisendactive
11434 && (last->sig & __DAHDI_SIG_FXO)
11435 && !analog_p->fxsoffhookstate
11436 && !last->owner
11437 && !ast_strlen_zero(last->mailbox)
11438 && (thispass - analog_p->onhooktime > 3)) {
11439 res = has_voicemail(last);
11440 if (analog_p->msgstate != res) {
11441
11442 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11443 if (res2) {
11444
11445 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11446 }
11447
11448 if (mwi_send_init(last)) {
11449 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11450 }
11451 analog_p->msgstate = res;
11452 found ++;
11453 }
11454 }
11455 last = last->next;
11456 }
11457 }
11458 }
11459 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11460 if (i->radio && !i->owner)
11461 {
11462 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11463 if (res)
11464 {
11465 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11466
11467 ast_mutex_unlock(&iflock);
11468 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11469 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11470 else
11471 doomed = handle_init_event(i, res);
11472 ast_mutex_lock(&iflock);
11473 }
11474 continue;
11475 }
11476 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11477 if (pollres & POLLIN) {
11478 if (i->owner || i->subs[SUB_REAL].owner) {
11479 #ifdef HAVE_PRI
11480 if (!i->pri)
11481 #endif
11482 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11483 continue;
11484 }
11485 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11486 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11487 continue;
11488 }
11489 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11490 if (res > 0) {
11491 if (i->mwimonitor_fsk) {
11492 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11493 pthread_attr_t attr;
11494 pthread_t threadid;
11495 struct mwi_thread_data *mtd;
11496
11497 pthread_attr_init(&attr);
11498 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11499
11500 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11501 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11502 mtd->pvt = i;
11503 memcpy(mtd->buf, buf, res);
11504 mtd->len = res;
11505 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11506 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11507 ast_free(mtd);
11508 }
11509 i->mwimonitoractive = 1;
11510 }
11511 }
11512
11513 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11514 int energy;
11515 struct timeval now;
11516
11517
11518
11519 if (1 == i->dtmfcid_holdoff_state) {
11520 gettimeofday(&i->dtmfcid_delay, NULL);
11521 i->dtmfcid_holdoff_state = 2;
11522 } else if (2 == i->dtmfcid_holdoff_state) {
11523 gettimeofday(&now, NULL);
11524 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11525 i->dtmfcid_holdoff_state = 0;
11526 }
11527 } else {
11528 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11529 if (!i->mwisendactive && energy > dtmfcid_level) {
11530 pthread_t threadid;
11531 struct ast_channel *chan;
11532 ast_mutex_unlock(&iflock);
11533 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11534
11535 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11536 i->dtmfcid_holdoff_state = 1;
11537 } else {
11538 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11539 if (!chan) {
11540 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11541 } else {
11542 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11543 if (res) {
11544 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11545 } else {
11546 i->dtmfcid_holdoff_state = 1;
11547 }
11548 }
11549 }
11550 ast_mutex_lock(&iflock);
11551 }
11552 }
11553 }
11554 if (i->mwisendactive) {
11555 mwi_send_process_buffer(i, res);
11556 }
11557 } else {
11558 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11559 }
11560 }
11561 if (pollres & POLLPRI) {
11562 if (i->owner || i->subs[SUB_REAL].owner) {
11563 #ifdef HAVE_PRI
11564 if (!i->pri)
11565 #endif
11566 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11567 continue;
11568 }
11569 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11570 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11571
11572 ast_mutex_unlock(&iflock);
11573 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11574 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11575 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11576 else
11577 doomed = handle_init_event(i, res);
11578 }
11579 ast_mutex_lock(&iflock);
11580 }
11581 }
11582 }
11583 ast_mutex_unlock(&iflock);
11584 }
11585
11586 return NULL;
11587
11588 }
11589
11590 static int restart_monitor(void)
11591 {
11592
11593 if (monitor_thread == AST_PTHREADT_STOP)
11594 return 0;
11595 ast_mutex_lock(&monlock);
11596 if (monitor_thread == pthread_self()) {
11597 ast_mutex_unlock(&monlock);
11598 ast_log(LOG_WARNING, "Cannot kill myself\n");
11599 return -1;
11600 }
11601 if (monitor_thread != AST_PTHREADT_NULL) {
11602
11603 pthread_kill(monitor_thread, SIGURG);
11604 } else {
11605
11606 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11607 ast_mutex_unlock(&monlock);
11608 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11609 return -1;
11610 }
11611 }
11612 ast_mutex_unlock(&monlock);
11613 return 0;
11614 }
11615
11616 #if defined(HAVE_PRI)
11617 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11618 {
11619 int x;
11620 int trunkgroup;
11621
11622 trunkgroup = pris[*span].mastertrunkgroup;
11623 if (trunkgroup) {
11624
11625 for (x = 0; x < NUM_SPANS; x++) {
11626 if (pris[x].pri.trunkgroup == trunkgroup) {
11627 *span = x;
11628 return 0;
11629 }
11630 }
11631 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11632 *span = -1;
11633 } else {
11634 if (pris[*span].pri.trunkgroup) {
11635 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);
11636 *span = -1;
11637 } else if (pris[*span].mastertrunkgroup) {
11638 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11639 *span = -1;
11640 } else {
11641 if (si->totalchans == 31) {
11642
11643 pris[*span].dchannels[0] = 16 + offset;
11644 } else if (si->totalchans == 24) {
11645
11646 pris[*span].dchannels[0] = 24 + offset;
11647 } else if (si->totalchans == 3) {
11648
11649 pris[*span].dchannels[0] = 3 + offset;
11650 } else {
11651 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);
11652 *span = -1;
11653 return 0;
11654 }
11655 pris[*span].pri.span = *span + 1;
11656 }
11657 }
11658 return 0;
11659 }
11660 #endif
11661
11662 #if defined(HAVE_PRI)
11663 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11664 {
11665 struct dahdi_spaninfo si;
11666 struct dahdi_params p;
11667 int fd;
11668 int span;
11669 int ospan=0;
11670 int x,y;
11671 for (x = 0; x < NUM_SPANS; x++) {
11672 if (pris[x].pri.trunkgroup == trunkgroup) {
11673 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11674 return -1;
11675 }
11676 }
11677 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11678 if (!channels[y])
11679 break;
11680 memset(&si, 0, sizeof(si));
11681 memset(&p, 0, sizeof(p));
11682 fd = open("/dev/dahdi/channel", O_RDWR);
11683 if (fd < 0) {
11684 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11685 return -1;
11686 }
11687 x = channels[y];
11688 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11689 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11690 close(fd);
11691 return -1;
11692 }
11693 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11694 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11695 return -1;
11696 }
11697 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11698 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11699 close(fd);
11700 return -1;
11701 }
11702 span = p.spanno - 1;
11703 if (pris[span].pri.trunkgroup) {
11704 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11705 close(fd);
11706 return -1;
11707 }
11708 if (pris[span].pri.pvts[0]) {
11709 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11710 close(fd);
11711 return -1;
11712 }
11713 if (!y) {
11714 pris[span].pri.trunkgroup = trunkgroup;
11715 ospan = span;
11716 }
11717 pris[ospan].dchannels[y] = channels[y];
11718 pris[span].pri.span = span + 1;
11719 close(fd);
11720 }
11721 return 0;
11722 }
11723 #endif
11724
11725 #if defined(HAVE_PRI)
11726 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11727 {
11728 if (pris[span].mastertrunkgroup) {
11729 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);
11730 return -1;
11731 }
11732 pris[span].mastertrunkgroup = trunkgroup;
11733 pris[span].prilogicalspan = logicalspan;
11734 return 0;
11735 }
11736 #endif
11737
11738 #if defined(HAVE_SS7)
11739 static unsigned int parse_pointcode(const char *pcstring)
11740 {
11741 unsigned int code1, code2, code3;
11742 int numvals;
11743
11744 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11745 if (numvals == 1)
11746 return code1;
11747 if (numvals == 3)
11748 return (code1 << 16) | (code2 << 8) | code3;
11749
11750 return 0;
11751 }
11752 #endif
11753
11754 #if defined(HAVE_SS7)
11755 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11756 {
11757 if ((linkset < 0) || (linkset >= NUM_SPANS))
11758 return NULL;
11759 else
11760 return &linksets[linkset - 1];
11761 }
11762 #endif
11763
11764 #ifdef HAVE_OPENR2
11765 static void dahdi_r2_destroy_links(void)
11766 {
11767 int i = 0;
11768 if (!r2links) {
11769 return;
11770 }
11771 for (; i < r2links_count; i++) {
11772 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11773 pthread_cancel(r2links[i]->r2master);
11774 pthread_join(r2links[i]->r2master, NULL);
11775 openr2_context_delete(r2links[i]->protocol_context);
11776 }
11777 ast_free(r2links[i]);
11778 }
11779 ast_free(r2links);
11780 r2links = NULL;
11781 r2links_count = 0;
11782 }
11783
11784 #define R2_LINK_CAPACITY 10
11785 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11786 {
11787 struct dahdi_mfcr2 *new_r2link = NULL;
11788 struct dahdi_mfcr2 **new_r2links = NULL;
11789
11790
11791 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11792 new_r2link = ast_calloc(1, sizeof(**r2links));
11793 if (!new_r2link) {
11794 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11795 return NULL;
11796 }
11797 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11798 if (!new_r2links) {
11799 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11800 ast_free(new_r2link);
11801 return NULL;
11802 }
11803 r2links = new_r2links;
11804 new_r2link->r2master = AST_PTHREADT_NULL;
11805 r2links[r2links_count] = new_r2link;
11806 r2links_count++;
11807 ast_log(LOG_DEBUG, "Created new R2 link!\n");
11808 }
11809 return r2links[r2links_count - 1];
11810 }
11811
11812 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
11813 {
11814 char tmplogdir[] = "/tmp";
11815 char logdir[OR2_MAX_PATH];
11816 int threshold = 0;
11817 int snres = 0;
11818 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
11819 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
11820 conf->mfcr2.max_dnis);
11821 if (!r2_link->protocol_context) {
11822 return -1;
11823 }
11824 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
11825 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
11826 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
11827 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
11828 #endif
11829 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
11830 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
11831 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
11832 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
11833 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
11834 if (ast_strlen_zero(conf->mfcr2.logdir)) {
11835 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11836 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11837 }
11838 } else {
11839 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
11840 if (snres >= sizeof(logdir)) {
11841 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
11842 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11843 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11844 }
11845 } else {
11846 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
11847 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
11848 }
11849 }
11850 }
11851 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
11852 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
11853 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
11854 }
11855 }
11856 r2_link->monitored_count = 0;
11857 return 0;
11858 }
11859 #endif
11860
11861
11862
11863
11864
11865
11866 static int sigtype_to_signalling(int sigtype)
11867 {
11868 return sigtype;
11869 }
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
11884 {
11885 struct stat stbuf;
11886 int num;
11887
11888 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
11889 if (stat(path, &stbuf) < 0) {
11890 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
11891 return -errno;
11892 }
11893 if (!S_ISCHR(stbuf.st_mode)) {
11894 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
11895 return -EINVAL;
11896 }
11897 num = minor(stbuf.st_rdev);
11898 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
11899 return num;
11900
11901 }
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
11918 {
11919
11920 struct dahdi_pvt *tmp;
11921 char fn[80];
11922 struct dahdi_bufferinfo bi;
11923
11924 int res;
11925 int span = 0;
11926 int here = 0;
11927 int x;
11928 struct analog_pvt *analog_p = NULL;
11929 struct dahdi_params p;
11930 #if defined(HAVE_PRI)
11931 struct dahdi_spaninfo si;
11932 struct sig_pri_chan *pri_chan = NULL;
11933 #endif
11934 #if defined(HAVE_SS7)
11935 struct sig_ss7_chan *ss7_chan = NULL;
11936 #endif
11937
11938
11939 for (tmp = iflist; tmp; tmp = tmp->next) {
11940 if (!tmp->destroy) {
11941 if (tmp->channel == channel) {
11942
11943 here = 1;
11944 break;
11945 }
11946 if (tmp->channel > channel) {
11947
11948 tmp = NULL;
11949 break;
11950 }
11951 }
11952 }
11953
11954 if (!here && reloading != 1) {
11955 tmp = ast_calloc(1, sizeof(*tmp));
11956 if (!tmp) {
11957 return NULL;
11958 }
11959 tmp->cc_params = ast_cc_config_params_init();
11960 if (!tmp->cc_params) {
11961 ast_free(tmp);
11962 return NULL;
11963 }
11964 ast_mutex_init(&tmp->lock);
11965 ifcount++;
11966 for (x = 0; x < 3; x++)
11967 tmp->subs[x].dfd = -1;
11968 tmp->channel = channel;
11969 tmp->priindication_oob = conf->chan.priindication_oob;
11970 }
11971
11972 if (tmp) {
11973 int chan_sig = conf->chan.sig;
11974
11975 if (!here) {
11976
11977 if ((channel != CHAN_PSEUDO)) {
11978 int count = 0;
11979
11980 snprintf(fn, sizeof(fn), "%d", channel);
11981
11982 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11983 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
11984 usleep(1);
11985 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11986 count++;
11987 }
11988
11989 if (tmp->subs[SUB_REAL].dfd < 0) {
11990 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);
11991 destroy_dahdi_pvt(tmp);
11992 return NULL;
11993 }
11994 memset(&p, 0, sizeof(p));
11995 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
11996 if (res < 0) {
11997 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
11998 destroy_dahdi_pvt(tmp);
11999 return NULL;
12000 }
12001 if (conf->is_sig_auto)
12002 chan_sig = sigtype_to_signalling(p.sigtype);
12003 if (p.sigtype != (chan_sig & 0x3ffff)) {
12004 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));
12005 destroy_dahdi_pvt(tmp);
12006 return NULL;
12007 }
12008 tmp->law_default = p.curlaw;
12009 tmp->law = p.curlaw;
12010 tmp->span = p.spanno;
12011 span = p.spanno - 1;
12012 } else {
12013 chan_sig = 0;
12014 }
12015 tmp->sig = chan_sig;
12016 tmp->outsigmod = conf->chan.outsigmod;
12017
12018 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
12019 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
12020 if (!analog_p) {
12021 destroy_dahdi_pvt(tmp);
12022 return NULL;
12023 }
12024 tmp->sig_pvt = analog_p;
12025 }
12026 #if defined(HAVE_SS7)
12027 if (chan_sig == SIG_SS7) {
12028 struct dahdi_ss7 *ss7;
12029 int clear = 0;
12030
12031 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12032 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12033 destroy_dahdi_pvt(tmp);
12034 return NULL;
12035 }
12036
12037 ss7 = ss7_resolve_linkset(cur_linkset);
12038 if (!ss7) {
12039 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12040 destroy_dahdi_pvt(tmp);
12041 return NULL;
12042 }
12043 ss7->ss7.span = cur_linkset;
12044 if (cur_cicbeginswith < 0) {
12045 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12046 destroy_dahdi_pvt(tmp);
12047 return NULL;
12048 }
12049 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12050 if (!ss7_chan) {
12051 destroy_dahdi_pvt(tmp);
12052 return NULL;
12053 }
12054 tmp->sig_pvt = ss7_chan;
12055 tmp->ss7 = &ss7->ss7;
12056
12057 ss7_chan->channel = tmp->channel;
12058 ss7_chan->cic = cur_cicbeginswith++;
12059
12060
12061 ss7_chan->dpc = cur_defaultdpc;
12062
12063 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12064
12065 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12066 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12067 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12068 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12069
12070 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12071 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12072 }
12073 #endif
12074 #ifdef HAVE_OPENR2
12075 if (chan_sig == SIG_MFCR2) {
12076 struct dahdi_mfcr2 *r2_link;
12077 r2_link = dahdi_r2_get_link();
12078 if (!r2_link) {
12079 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12080 destroy_dahdi_pvt(tmp);
12081 return NULL;
12082 }
12083 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12084 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12085 destroy_dahdi_pvt(tmp);
12086 return NULL;
12087 }
12088 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12089 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12090 destroy_dahdi_pvt(tmp);
12091 return NULL;
12092 }
12093 r2_link->pvts[r2_link->numchans++] = tmp;
12094 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12095 tmp->subs[SUB_REAL].dfd,
12096 NULL, NULL);
12097 if (!tmp->r2chan) {
12098 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12099 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12100 destroy_dahdi_pvt(tmp);
12101 return NULL;
12102 }
12103 tmp->mfcr2 = r2_link;
12104 if (conf->mfcr2.call_files) {
12105 openr2_chan_enable_call_files(tmp->r2chan);
12106 }
12107 openr2_chan_set_client_data(tmp->r2chan, tmp);
12108
12109 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12110 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12111 tmp->mfcr2_category = conf->mfcr2.category;
12112 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12113 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12114 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12115 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12116 tmp->mfcr2call = 0;
12117 tmp->mfcr2_dnis_index = 0;
12118 tmp->mfcr2_ani_index = 0;
12119 r2_link->monitored_count++;
12120 }
12121 #endif
12122 #ifdef HAVE_PRI
12123 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12124 int offset;
12125 int matchesdchan;
12126 int x,y;
12127 int myswitchtype = 0;
12128
12129 offset = 0;
12130 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12131 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12132 destroy_dahdi_pvt(tmp);
12133 return NULL;
12134 }
12135 if (span >= NUM_SPANS) {
12136 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12137 destroy_dahdi_pvt(tmp);
12138 return NULL;
12139 } else {
12140 si.spanno = 0;
12141 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12142 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12143 destroy_dahdi_pvt(tmp);
12144 return NULL;
12145 }
12146
12147 tmp->logicalspan = pris[span].prilogicalspan;
12148 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12149 if (span < 0) {
12150 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12151 destroy_dahdi_pvt(tmp);
12152 return NULL;
12153 }
12154 myswitchtype = conf->pri.pri.switchtype;
12155
12156 matchesdchan=0;
12157 for (x = 0; x < NUM_SPANS; x++) {
12158 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12159 if (pris[x].dchannels[y] == tmp->channel) {
12160 matchesdchan = 1;
12161 break;
12162 }
12163 }
12164 }
12165 if (!matchesdchan) {
12166 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12167 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12168 destroy_dahdi_pvt(tmp);
12169 return NULL;
12170 }
12171 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12172 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12173 destroy_dahdi_pvt(tmp);
12174 return NULL;
12175 }
12176 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12177 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));
12178 destroy_dahdi_pvt(tmp);
12179 return NULL;
12180 }
12181 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12182 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12183 destroy_dahdi_pvt(tmp);
12184 return NULL;
12185 }
12186 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12187 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12188 destroy_dahdi_pvt(tmp);
12189 return NULL;
12190 }
12191 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12192 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12193 destroy_dahdi_pvt(tmp);
12194 return NULL;
12195 }
12196 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12197 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12198 destroy_dahdi_pvt(tmp);
12199 return NULL;
12200 }
12201 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12202 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12203 pris[span].pri.trunkgroup);
12204 destroy_dahdi_pvt(tmp);
12205 return NULL;
12206 }
12207
12208 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12209 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12210 if (!pri_chan) {
12211 destroy_dahdi_pvt(tmp);
12212 return NULL;
12213 }
12214 tmp->sig_pvt = pri_chan;
12215 tmp->pri = &pris[span].pri;
12216
12217 tmp->priexclusive = conf->chan.priexclusive;
12218
12219 if (!tmp->pri->cc_params) {
12220 tmp->pri->cc_params = ast_cc_config_params_init();
12221 if (!tmp->pri->cc_params) {
12222 destroy_dahdi_pvt(tmp);
12223 return NULL;
12224 }
12225 }
12226 ast_cc_copy_config_params(tmp->pri->cc_params,
12227 conf->chan.cc_params);
12228
12229 pris[span].pri.sig = chan_sig;
12230 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12231 pris[span].pri.switchtype = myswitchtype;
12232 pris[span].pri.nsf = conf->pri.pri.nsf;
12233 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12234 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12235 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12236 pris[span].pri.minunused = conf->pri.pri.minunused;
12237 pris[span].pri.minidle = conf->pri.pri.minidle;
12238 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12239 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12240 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12241 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12242 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12243 #endif
12244 #ifdef HAVE_PRI_INBANDDISCONNECT
12245 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12246 #endif
12247 #if defined(HAVE_PRI_CALL_HOLD)
12248 pris[span].pri.hold_disconnect_transfer =
12249 conf->pri.pri.hold_disconnect_transfer;
12250 #endif
12251 #if defined(HAVE_PRI_CCSS)
12252 pris[span].pri.cc_ptmp_recall_mode =
12253 conf->pri.pri.cc_ptmp_recall_mode;
12254 pris[span].pri.cc_qsig_signaling_link_req =
12255 conf->pri.pri.cc_qsig_signaling_link_req;
12256 pris[span].pri.cc_qsig_signaling_link_rsp =
12257 conf->pri.pri.cc_qsig_signaling_link_rsp;
12258 #endif
12259 #if defined(HAVE_PRI_CALL_WAITING)
12260 pris[span].pri.max_call_waiting_calls =
12261 conf->pri.pri.max_call_waiting_calls;
12262 pris[span].pri.allow_call_waiting_calls =
12263 conf->pri.pri.allow_call_waiting_calls;
12264 #endif
12265 pris[span].pri.transfer = conf->chan.transfer;
12266 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12267 #if defined(HAVE_PRI_AOC_EVENTS)
12268 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12269 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12270 #endif
12271 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12272 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12273 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12274 #if defined(HAVE_PRI_MWI)
12275 ast_copy_string(pris[span].pri.mwi_mailboxes,
12276 conf->pri.pri.mwi_mailboxes,
12277 sizeof(pris[span].pri.mwi_mailboxes));
12278 #endif
12279 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12280 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12281 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12282 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12283 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12284 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12285 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12286 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12287
12288 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12289 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12290 }
12291
12292 #if defined(HAVE_PRI_CALL_WAITING)
12293
12294 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12295 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12296 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12297 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12298 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12299 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12300 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12301 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12302 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12303 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12304 #endif
12305 } else {
12306 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12307 destroy_dahdi_pvt(tmp);
12308 return NULL;
12309 }
12310 }
12311 }
12312 #endif
12313 } else {
12314
12315 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));
12316 chan_sig = tmp->sig;
12317 if (tmp->subs[SUB_REAL].dfd > -1) {
12318 memset(&p, 0, sizeof(p));
12319 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12320 }
12321 }
12322
12323 switch (chan_sig) {
12324 case SIG_FXSKS:
12325 case SIG_FXSLS:
12326 case SIG_EM:
12327 case SIG_EM_E1:
12328 case SIG_EMWINK:
12329 case SIG_FEATD:
12330 case SIG_FEATDMF:
12331 case SIG_FEATDMF_TA:
12332 case SIG_FEATB:
12333 case SIG_E911:
12334 case SIG_SF:
12335 case SIG_SFWINK:
12336 case SIG_FGC_CAMA:
12337 case SIG_FGC_CAMAMF:
12338 case SIG_SF_FEATD:
12339 case SIG_SF_FEATDMF:
12340 case SIG_SF_FEATB:
12341 p.starttime = 250;
12342 break;
12343 }
12344
12345 if (tmp->radio) {
12346
12347 p.channo = channel;
12348 p.rxwinktime = 1;
12349 p.rxflashtime = 1;
12350 p.starttime = 1;
12351 p.debouncetime = 5;
12352 } else {
12353 p.channo = channel;
12354
12355 if (conf->timing.prewinktime >= 0)
12356 p.prewinktime = conf->timing.prewinktime;
12357 if (conf->timing.preflashtime >= 0)
12358 p.preflashtime = conf->timing.preflashtime;
12359 if (conf->timing.winktime >= 0)
12360 p.winktime = conf->timing.winktime;
12361 if (conf->timing.flashtime >= 0)
12362 p.flashtime = conf->timing.flashtime;
12363 if (conf->timing.starttime >= 0)
12364 p.starttime = conf->timing.starttime;
12365 if (conf->timing.rxwinktime >= 0)
12366 p.rxwinktime = conf->timing.rxwinktime;
12367 if (conf->timing.rxflashtime >= 0)
12368 p.rxflashtime = conf->timing.rxflashtime;
12369 if (conf->timing.debouncetime >= 0)
12370 p.debouncetime = conf->timing.debouncetime;
12371 }
12372
12373
12374 if (tmp->subs[SUB_REAL].dfd >= 0)
12375 {
12376 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12377 if (res < 0) {
12378 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12379 destroy_dahdi_pvt(tmp);
12380 return NULL;
12381 }
12382 }
12383 #if 1
12384 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12385 memset(&bi, 0, sizeof(bi));
12386 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12387 if (!res) {
12388 bi.txbufpolicy = conf->chan.buf_policy;
12389 bi.rxbufpolicy = conf->chan.buf_policy;
12390 bi.numbufs = conf->chan.buf_no;
12391 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12392 if (res < 0) {
12393 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12394 }
12395 } else {
12396 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12397 }
12398 tmp->buf_policy = conf->chan.buf_policy;
12399 tmp->buf_no = conf->chan.buf_no;
12400 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12401 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12402 tmp->faxbuf_no = conf->chan.faxbuf_no;
12403
12404
12405
12406
12407 tmp->bufsize = bi.bufsize;
12408 }
12409 #endif
12410 tmp->immediate = conf->chan.immediate;
12411 tmp->transfertobusy = conf->chan.transfertobusy;
12412 if (chan_sig & __DAHDI_SIG_FXS) {
12413 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12414 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12415 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12416 }
12417 tmp->ringt_base = ringt_base;
12418 tmp->firstradio = 0;
12419 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12420 tmp->permcallwaiting = conf->chan.callwaiting;
12421 else
12422 tmp->permcallwaiting = 0;
12423
12424 tmp->destroy = 0;
12425 tmp->drings = conf->chan.drings;
12426
12427
12428 if (tmp->drings.ringnum[0].range == 0)
12429 tmp->drings.ringnum[0].range = 10;
12430 if (tmp->drings.ringnum[1].range == 0)
12431 tmp->drings.ringnum[1].range = 10;
12432 if (tmp->drings.ringnum[2].range == 0)
12433 tmp->drings.ringnum[2].range = 10;
12434
12435 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12436 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12437 tmp->threewaycalling = conf->chan.threewaycalling;
12438 tmp->adsi = conf->chan.adsi;
12439 tmp->use_smdi = conf->chan.use_smdi;
12440 tmp->permhidecallerid = conf->chan.hidecallerid;
12441 tmp->hidecalleridname = conf->chan.hidecalleridname;
12442 tmp->callreturn = conf->chan.callreturn;
12443 tmp->echocancel = conf->chan.echocancel;
12444 tmp->echotraining = conf->chan.echotraining;
12445 tmp->pulse = conf->chan.pulse;
12446 if (tmp->echocancel.head.tap_length) {
12447 tmp->echocanbridged = conf->chan.echocanbridged;
12448 } else {
12449 if (conf->chan.echocanbridged)
12450 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12451 tmp->echocanbridged = 0;
12452 }
12453 tmp->busydetect = conf->chan.busydetect;
12454 tmp->busycount = conf->chan.busycount;
12455 tmp->busycompare = conf->chan.busycompare;
12456 tmp->busytonelength = conf->chan.busytonelength;
12457 tmp->busyquietlength = conf->chan.busyquietlength;
12458 tmp->busyfuzziness = conf->chan.busyfuzziness;
12459 tmp->silencethreshold = conf->chan.silencethreshold;
12460 tmp->callprogress = conf->chan.callprogress;
12461 tmp->waitfordialtone = conf->chan.waitfordialtone;
12462 tmp->cancallforward = conf->chan.cancallforward;
12463 tmp->dtmfrelax = conf->chan.dtmfrelax;
12464 tmp->callwaiting = tmp->permcallwaiting;
12465 tmp->hidecallerid = tmp->permhidecallerid;
12466 tmp->channel = channel;
12467 tmp->stripmsd = conf->chan.stripmsd;
12468 tmp->use_callerid = conf->chan.use_callerid;
12469 tmp->cid_signalling = conf->chan.cid_signalling;
12470 tmp->cid_start = conf->chan.cid_start;
12471 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12472 tmp->restrictcid = conf->chan.restrictcid;
12473 tmp->use_callingpres = conf->chan.use_callingpres;
12474 if (tmp->usedistinctiveringdetection) {
12475 if (!tmp->use_callerid) {
12476 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12477 tmp->use_callerid = 1;
12478 }
12479 }
12480
12481 if (tmp->cid_signalling == CID_SIG_SMDI) {
12482 if (!tmp->use_smdi) {
12483 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12484 tmp->use_smdi = 1;
12485 }
12486 }
12487 if (tmp->use_smdi) {
12488 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12489 if (!(tmp->smdi_iface)) {
12490 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12491 tmp->use_smdi = 0;
12492 }
12493 }
12494
12495 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12496 tmp->amaflags = conf->chan.amaflags;
12497 if (!here) {
12498 tmp->confno = -1;
12499 tmp->propconfno = -1;
12500 }
12501 tmp->canpark = conf->chan.canpark;
12502 tmp->transfer = conf->chan.transfer;
12503 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12504 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12505 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12506 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12507 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12508 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12509 tmp->cid_ton = 0;
12510 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12511 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12512 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12513 } else {
12514 tmp->cid_num[0] = '\0';
12515 tmp->cid_name[0] = '\0';
12516 }
12517 #if defined(HAVE_PRI)
12518 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12519 tmp->cid_tag[0] = '\0';
12520 } else
12521 #endif
12522 {
12523 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12524 }
12525 tmp->cid_subaddr[0] = '\0';
12526 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12527 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12528 char *mailbox, *context;
12529 mailbox = context = ast_strdupa(tmp->mailbox);
12530 strsep(&context, "@");
12531 if (ast_strlen_zero(context))
12532 context = "default";
12533 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12534 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12535 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12536 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12537 AST_EVENT_IE_END);
12538 }
12539 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12540 tmp->mwisend_setting = conf->chan.mwisend_setting;
12541 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12542 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12543 #endif
12544
12545 tmp->group = conf->chan.group;
12546 tmp->callgroup = conf->chan.callgroup;
12547 tmp->pickupgroup= conf->chan.pickupgroup;
12548 if (conf->chan.vars) {
12549 struct ast_variable *v, *tmpvar;
12550 for (v = conf->chan.vars ; v ; v = v->next) {
12551 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12552 tmpvar->next = tmp->vars;
12553 tmp->vars = tmpvar;
12554 }
12555 }
12556 }
12557 tmp->cid_rxgain = conf->chan.cid_rxgain;
12558 tmp->rxgain = conf->chan.rxgain;
12559 tmp->txgain = conf->chan.txgain;
12560 tmp->txdrc = conf->chan.txdrc;
12561 tmp->rxdrc = conf->chan.rxdrc;
12562 tmp->tonezone = conf->chan.tonezone;
12563 if (tmp->subs[SUB_REAL].dfd > -1) {
12564 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12565 if (tmp->dsp)
12566 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12567 update_conf(tmp);
12568 if (!here) {
12569 switch (chan_sig) {
12570 case SIG_PRI_LIB_HANDLE_CASES:
12571 case SIG_SS7:
12572 case SIG_MFCR2:
12573 break;
12574 default:
12575
12576 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12577 break;
12578 }
12579 }
12580 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12581 #ifdef HAVE_PRI
12582 memset(&si, 0, sizeof(si));
12583 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12584 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12585 destroy_dahdi_pvt(tmp);
12586 return NULL;
12587 }
12588 #endif
12589 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12590
12591 switch (tmp->sig) {
12592 #ifdef HAVE_PRI
12593 case SIG_PRI_LIB_HANDLE_CASES:
12594 sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
12595 break;
12596 #endif
12597 #if defined(HAVE_SS7)
12598 case SIG_SS7:
12599 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12600 break;
12601 #endif
12602 default:
12603
12604 analog_p = tmp->sig_pvt;
12605 if (analog_p) {
12606 analog_p->inalarm = 1;
12607 }
12608 tmp->inalarm = 1;
12609 break;
12610 }
12611 handle_alarms(tmp, res);
12612 }
12613 }
12614
12615 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12616 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12617 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12618 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12619 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12620
12621 if (!here) {
12622 tmp->locallyblocked = 0;
12623 tmp->remotelyblocked = 0;
12624 switch (tmp->sig) {
12625 #if defined(HAVE_PRI)
12626 case SIG_PRI_LIB_HANDLE_CASES:
12627 tmp->inservice = 1;
12628 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12629 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12630 if (chan_sig == SIG_PRI) {
12631 char db_chan_name[20];
12632 char db_answer[5];
12633
12634
12635
12636
12637
12638 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12639 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12640 unsigned *why;
12641
12642 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12643 if (tmp->pri->enable_service_message_support) {
12644 char state;
12645
12646 sscanf(db_answer, "%1c:%30u", &state, why);
12647
12648
12649 *why &= (SRVST_NEAREND | SRVST_FAREND);
12650 }
12651 if (!*why) {
12652 ast_db_del(db_chan_name, SRVST_DBKEY);
12653 }
12654 }
12655 }
12656 #endif
12657 break;
12658 #endif
12659 #if defined(HAVE_SS7)
12660 case SIG_SS7:
12661 tmp->inservice = 0;
12662 break;
12663 #endif
12664 default:
12665
12666 tmp->inservice = 1;
12667 break;
12668 }
12669 }
12670
12671 switch (tmp->sig) {
12672 #if defined(HAVE_PRI)
12673 case SIG_PRI_LIB_HANDLE_CASES:
12674 if (pri_chan) {
12675 pri_chan->channel = tmp->channel;
12676 pri_chan->hidecallerid = tmp->hidecallerid;
12677 pri_chan->hidecalleridname = tmp->hidecalleridname;
12678 pri_chan->immediate = tmp->immediate;
12679 pri_chan->inalarm = tmp->inalarm;
12680 pri_chan->priexclusive = tmp->priexclusive;
12681 pri_chan->priindication_oob = tmp->priindication_oob;
12682 pri_chan->use_callerid = tmp->use_callerid;
12683 pri_chan->use_callingpres = tmp->use_callingpres;
12684 ast_copy_string(pri_chan->context, tmp->context,
12685 sizeof(pri_chan->context));
12686 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12687 sizeof(pri_chan->mohinterpret));
12688 pri_chan->stripmsd = tmp->stripmsd;
12689 }
12690 break;
12691 #endif
12692 #if defined(HAVE_SS7)
12693 case SIG_SS7:
12694 if (ss7_chan) {
12695 ss7_chan->inalarm = tmp->inalarm;
12696
12697 ss7_chan->stripmsd = tmp->stripmsd;
12698 ss7_chan->hidecallerid = tmp->hidecallerid;
12699 ss7_chan->use_callerid = tmp->use_callerid;
12700 ss7_chan->use_callingpres = tmp->use_callingpres;
12701 ss7_chan->immediate = tmp->immediate;
12702 ss7_chan->locallyblocked = tmp->locallyblocked;
12703 ss7_chan->remotelyblocked = tmp->remotelyblocked;
12704 ast_copy_string(ss7_chan->context, tmp->context,
12705 sizeof(ss7_chan->context));
12706 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12707 sizeof(ss7_chan->mohinterpret));
12708 }
12709 break;
12710 #endif
12711 default:
12712
12713 analog_p = tmp->sig_pvt;
12714 if (analog_p) {
12715 analog_p->channel = tmp->channel;
12716 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12717 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12718 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12719 analog_p->permcallwaiting = conf->chan.callwaiting;
12720 analog_p->callreturn = conf->chan.callreturn;
12721 analog_p->cancallforward = conf->chan.cancallforward;
12722 analog_p->canpark = conf->chan.canpark;
12723 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12724 analog_p->immediate = conf->chan.immediate;
12725 analog_p->permhidecallerid = conf->chan.permhidecallerid;
12726 analog_p->pulse = conf->chan.pulse;
12727 analog_p->threewaycalling = conf->chan.threewaycalling;
12728 analog_p->transfer = conf->chan.transfer;
12729 analog_p->transfertobusy = conf->chan.transfertobusy;
12730 analog_p->use_callerid = tmp->use_callerid;
12731 analog_p->use_smdi = tmp->use_smdi;
12732 analog_p->smdi_iface = tmp->smdi_iface;
12733 analog_p->outsigmod = ANALOG_SIG_NONE;
12734 analog_p->echotraining = conf->chan.echotraining;
12735 analog_p->cid_signalling = conf->chan.cid_signalling;
12736 analog_p->stripmsd = conf->chan.stripmsd;
12737 switch (conf->chan.cid_start) {
12738 case CID_START_POLARITY:
12739 analog_p->cid_start = ANALOG_CID_START_POLARITY;
12740 break;
12741 case CID_START_POLARITY_IN:
12742 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12743 break;
12744 case CID_START_DTMF_NOALERT:
12745 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12746 break;
12747 default:
12748 analog_p->cid_start = ANALOG_CID_START_RING;
12749 break;
12750 }
12751 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12752 analog_p->ringt = conf->chan.ringt;
12753 analog_p->ringt_base = ringt_base;
12754 analog_p->chan_tech = &dahdi_tech;
12755 analog_p->onhooktime = time(NULL);
12756 if (chan_sig & __DAHDI_SIG_FXO) {
12757 memset(&p, 0, sizeof(p));
12758 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12759 if (!res) {
12760 analog_p->fxsoffhookstate = p.rxisoffhook;
12761 }
12762 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12763 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12764 #endif
12765 }
12766 analog_p->msgstate = -1;
12767
12768 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12769 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12770 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12771
12772 analog_config_complete(analog_p);
12773 }
12774 break;
12775 }
12776 #if defined(HAVE_PRI)
12777 if (tmp->channel == CHAN_PSEUDO) {
12778
12779
12780
12781
12782 dahdi_pseudo_parms.buf_no = tmp->buf_no;
12783 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12784 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12785 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12786 }
12787 #endif
12788 }
12789 if (tmp && !here) {
12790
12791 dahdi_iflist_insert(tmp);
12792 }
12793 return tmp;
12794 }
12795
12796 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
12797 {
12798 #if defined(HAVE_PRI)
12799 if (0 < span) {
12800
12801 if (!p->pri || p->pri->span != span) {
12802 return 0;
12803 }
12804 if (!groupmatch && channelmatch == -1) {
12805
12806 *groupmatched = 1;
12807 return 1;
12808 }
12809 }
12810 #endif
12811
12812 if (groupmatch) {
12813 if ((p->group & groupmatch) != groupmatch)
12814
12815 return 0;
12816 *groupmatched = 1;
12817 }
12818
12819 if (channelmatch != -1) {
12820 if (p->channel != channelmatch)
12821
12822 return 0;
12823 *channelmatched = 1;
12824 }
12825
12826 return 1;
12827 }
12828
12829 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
12830 {
12831 struct dahdi_pvt *p = *pvt;
12832
12833 if (p->inalarm)
12834 return 0;
12835
12836 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
12837 return analog_available(p->sig_pvt);
12838
12839 switch (p->sig) {
12840 #if defined(HAVE_PRI)
12841 case SIG_PRI_LIB_HANDLE_CASES:
12842 {
12843 struct sig_pri_chan *pvt_chan;
12844 int res;
12845
12846 pvt_chan = p->sig_pvt;
12847 res = sig_pri_available(&pvt_chan, is_specific_channel);
12848 *pvt = pvt_chan->chan_pvt;
12849 return res;
12850 }
12851 #endif
12852 #if defined(HAVE_SS7)
12853 case SIG_SS7:
12854 return sig_ss7_available(p->sig_pvt);
12855 #endif
12856 default:
12857 break;
12858 }
12859
12860 if (p->locallyblocked || p->remotelyblocked) {
12861 return 0;
12862 }
12863
12864
12865 if (!p->owner) {
12866 #ifdef HAVE_OPENR2
12867
12868 if (p->mfcr2) {
12869 if (p->mfcr2call) {
12870 return 0;
12871 } else {
12872 return 1;
12873 }
12874 }
12875 #endif
12876 return 1;
12877 }
12878
12879 return 0;
12880 }
12881
12882 #if defined(HAVE_PRI)
12883 #if defined(HAVE_PRI_CALL_WAITING)
12884
12885
12886
12887
12888
12889
12890
12891
12892
12893
12894
12895
12896 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
12897 {
12898 struct dahdi_pvt *pvt = priv;
12899
12900 pvt->stripmsd = pri->ch_cfg.stripmsd;
12901 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
12902 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
12903 pvt->immediate = pri->ch_cfg.immediate;
12904 pvt->priexclusive = pri->ch_cfg.priexclusive;
12905 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
12906 pvt->use_callerid = pri->ch_cfg.use_callerid;
12907 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
12908 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
12909 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
12910 }
12911 #endif
12912 #endif
12913
12914 #if defined(HAVE_PRI)
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924
12925
12926
12927 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
12928 {
12929 int pvt_idx;
12930 int res;
12931 unsigned idx;
12932 struct dahdi_pvt *pvt;
12933 struct sig_pri_chan *chan;
12934 struct dahdi_bufferinfo bi;
12935
12936 static int nobch_channel = CHAN_PSEUDO;
12937
12938
12939 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
12940 if (!pri->pvts[pvt_idx]) {
12941 break;
12942 }
12943 }
12944 if (pri->numchans == pvt_idx) {
12945 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
12946 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
12947 return -1;
12948 }
12949
12950
12951 pri->pvts[pvt_idx] = NULL;
12952 ++pri->numchans;
12953 }
12954
12955 pvt = ast_calloc(1, sizeof(*pvt));
12956 if (!pvt) {
12957 return -1;
12958 }
12959 pvt->cc_params = ast_cc_config_params_init();
12960 if (!pvt->cc_params) {
12961 ast_free(pvt);
12962 return -1;
12963 }
12964 ast_mutex_init(&pvt->lock);
12965 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
12966 pvt->subs[idx].dfd = -1;
12967 }
12968 pvt->buf_no = dahdi_pseudo_parms.buf_no;
12969 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
12970 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
12971 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
12972
12973 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
12974 if (!chan) {
12975 destroy_dahdi_pvt(pvt);
12976 return -1;
12977 }
12978 chan->no_b_channel = 1;
12979
12980
12981
12982
12983
12984
12985 pvt->law_default = DAHDI_LAW_ALAW;
12986
12987 pvt->sig = pri->sig;
12988 pvt->outsigmod = -1;
12989 pvt->pri = pri;
12990 pvt->sig_pvt = chan;
12991 pri->pvts[pvt_idx] = chan;
12992
12993 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
12994 if (pvt->subs[SUB_REAL].dfd < 0) {
12995 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
12996 strerror(errno));
12997 destroy_dahdi_pvt(pvt);
12998 return -1;
12999 }
13000 memset(&bi, 0, sizeof(bi));
13001 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13002 if (!res) {
13003 pvt->bufsize = bi.bufsize;
13004 bi.txbufpolicy = pvt->buf_policy;
13005 bi.rxbufpolicy = pvt->buf_policy;
13006 bi.numbufs = pvt->buf_no;
13007 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13008 if (res < 0) {
13009 ast_log(LOG_WARNING,
13010 "Unable to set buffer policy on no B channel interface: %s\n",
13011 strerror(errno));
13012 }
13013 } else
13014 ast_log(LOG_WARNING,
13015 "Unable to check buffer policy on no B channel interface: %s\n",
13016 strerror(errno));
13017
13018 --nobch_channel;
13019 if (CHAN_PSEUDO < nobch_channel) {
13020 nobch_channel = CHAN_PSEUDO - 1;
13021 }
13022 pvt->channel = nobch_channel;
13023 chan->channel = pvt->channel;
13024
13025 dahdi_nobch_insert(pri, pvt);
13026
13027 return pvt_idx;
13028 }
13029 #endif
13030
13031
13032
13033
13034
13035
13036 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13037 {
13038 struct dahdi_pvt *p;
13039 struct dahdi_bufferinfo bi;
13040 int res;
13041
13042 p = ast_malloc(sizeof(*p));
13043 if (!p) {
13044 return NULL;
13045 }
13046 *p = *src;
13047
13048
13049 p->cc_params = ast_cc_config_params_init();
13050 if (!p->cc_params) {
13051 ast_free(p);
13052 return NULL;
13053 }
13054 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13055
13056 p->which_iflist = DAHDI_IFLIST_NONE;
13057 p->next = NULL;
13058 p->prev = NULL;
13059 ast_mutex_init(&p->lock);
13060 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13061 if (p->subs[SUB_REAL].dfd < 0) {
13062 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13063 destroy_dahdi_pvt(p);
13064 return NULL;
13065 }
13066 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13067 if (!res) {
13068 bi.txbufpolicy = src->buf_policy;
13069 bi.rxbufpolicy = src->buf_policy;
13070 bi.numbufs = src->buf_no;
13071 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13072 if (res < 0) {
13073 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13074 }
13075 } else
13076 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13077 p->destroy = 1;
13078 dahdi_iflist_insert(p);
13079 return p;
13080 }
13081
13082 struct dahdi_starting_point {
13083
13084 ast_group_t groupmatch;
13085
13086 int channelmatch;
13087
13088 int rr_starting_point;
13089
13090 int span;
13091
13092 int cadance;
13093
13094 char opt;
13095
13096 char backwards;
13097
13098 char roundrobin;
13099 };
13100 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13101 {
13102 char *dest;
13103 char *s;
13104 int x;
13105 int res = 0;
13106 struct dahdi_pvt *p;
13107 char *subdir = NULL;
13108 AST_DECLARE_APP_ARGS(args,
13109 AST_APP_ARG(group);
13110
13111
13112 AST_APP_ARG(other);
13113 );
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138 if (data) {
13139 dest = ast_strdupa(data);
13140 } else {
13141 ast_log(LOG_WARNING, "Channel requested with no data\n");
13142 return NULL;
13143 }
13144 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13145 if (!args.argc || ast_strlen_zero(args.group)) {
13146 ast_log(LOG_WARNING, "No channel/group specified\n");
13147 return NULL;
13148 }
13149
13150
13151 memset(param, 0, sizeof(*param));
13152 param->channelmatch = -1;
13153
13154 if (strchr(args.group, '!') != NULL) {
13155 char *prev = args.group;
13156 while ((s = strchr(prev, '!')) != NULL) {
13157 *s++ = '/';
13158 prev = s;
13159 }
13160 *(prev - 1) = '\0';
13161 subdir = args.group;
13162 args.group = prev;
13163 } else if (args.group[0] == 'i') {
13164
13165 res = sscanf(args.group + 1, "%30d", &x);
13166 if (res < 1) {
13167 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13168 return NULL;
13169 }
13170 param->span = x;
13171
13172
13173 s = strchr(args.group, '-');
13174 if (!s) {
13175
13176 return iflist;
13177 }
13178 args.group = s + 1;
13179 res = 0;
13180 }
13181 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13182
13183 s = args.group + 1;
13184 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13185 if (res < 1) {
13186 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13187 return NULL;
13188 }
13189 param->groupmatch = ((ast_group_t) 1 << x);
13190
13191 if (toupper(args.group[0]) == 'G') {
13192 if (args.group[0] == 'G') {
13193 param->backwards = 1;
13194 p = ifend;
13195 } else
13196 p = iflist;
13197 } else {
13198 if (ARRAY_LEN(round_robin) <= x) {
13199 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13200 x, data);
13201 return NULL;
13202 }
13203 if (args.group[0] == 'R') {
13204 param->backwards = 1;
13205 p = round_robin[x] ? round_robin[x]->prev : ifend;
13206 if (!p)
13207 p = ifend;
13208 } else {
13209 p = round_robin[x] ? round_robin[x]->next : iflist;
13210 if (!p)
13211 p = iflist;
13212 }
13213 param->roundrobin = 1;
13214 param->rr_starting_point = x;
13215 }
13216 } else {
13217 s = args.group;
13218 if (!strcasecmp(s, "pseudo")) {
13219
13220 x = CHAN_PSEUDO;
13221 param->channelmatch = x;
13222 } else {
13223 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13224 if (res < 1) {
13225 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13226 return NULL;
13227 } else {
13228 param->channelmatch = x;
13229 }
13230 }
13231 if (subdir) {
13232 char path[PATH_MAX];
13233 struct stat stbuf;
13234
13235 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13236 subdir, param->channelmatch);
13237 if (stat(path, &stbuf) < 0) {
13238 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13239 path, strerror(errno));
13240 return NULL;
13241 }
13242 if (!S_ISCHR(stbuf.st_mode)) {
13243 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13244 path);
13245 return NULL;
13246 }
13247 param->channelmatch = minor(stbuf.st_rdev);
13248 }
13249
13250 p = iflist;
13251 }
13252
13253 if (param->opt == 'r' && res < 3) {
13254 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13255 param->opt = '\0';
13256 }
13257
13258 return p;
13259 }
13260
13261 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13262 {
13263 int callwait = 0;
13264 struct dahdi_pvt *p;
13265 struct ast_channel *tmp = NULL;
13266 struct dahdi_pvt *exitpvt;
13267 int channelmatched = 0;
13268 int groupmatched = 0;
13269 int transcapdigital = 0;
13270 struct dahdi_starting_point start;
13271
13272 ast_mutex_lock(&iflock);
13273 p = determine_starting_point(data, &start);
13274 if (!p) {
13275
13276 ast_mutex_unlock(&iflock);
13277 return NULL;
13278 }
13279
13280
13281 exitpvt = p;
13282 while (p && !tmp) {
13283 if (start.roundrobin)
13284 round_robin[start.rr_starting_point] = p;
13285
13286 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13287 && available(&p, channelmatched)) {
13288 ast_debug(1, "Using channel %d\n", p->channel);
13289
13290 callwait = (p->owner != NULL);
13291 #ifdef HAVE_OPENR2
13292 if (p->mfcr2) {
13293 ast_mutex_lock(&p->lock);
13294 if (p->mfcr2call) {
13295 ast_mutex_unlock(&p->lock);
13296 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13297 goto next;
13298 }
13299 p->mfcr2call = 1;
13300 ast_mutex_unlock(&p->lock);
13301 }
13302 #endif
13303 if (p->channel == CHAN_PSEUDO) {
13304 p = duplicate_pseudo(p);
13305 if (!p) {
13306 break;
13307 }
13308 }
13309
13310
13311 switch (start.opt) {
13312 case '\0':
13313
13314 break;
13315 case 'c':
13316
13317 p->confirmanswer = 1;
13318 break;
13319 case 'r':
13320
13321 p->distinctivering = start.cadance;
13322 break;
13323 case 'd':
13324
13325 transcapdigital = AST_TRANS_CAP_DIGITAL;
13326 break;
13327 default:
13328 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13329 break;
13330 }
13331
13332 p->outgoing = 1;
13333 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13334 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13335 #ifdef HAVE_PRI
13336 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13337 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13338 sizeof(p->dnid));
13339 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13340 #endif
13341 #if defined(HAVE_SS7)
13342 } else if (p->sig == SIG_SS7) {
13343 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13344 #endif
13345 } else {
13346 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13347 }
13348 if (!tmp) {
13349 p->outgoing = 0;
13350 #if defined(HAVE_PRI)
13351 #if defined(HAVE_PRI_CALL_WAITING)
13352 switch (p->sig) {
13353 case SIG_PRI_LIB_HANDLE_CASES:
13354 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13355 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13356 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13357 }
13358 break;
13359 default:
13360 break;
13361 }
13362 #endif
13363 #endif
13364 } else {
13365 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13366 }
13367 break;
13368 }
13369 #ifdef HAVE_OPENR2
13370 next:
13371 #endif
13372 if (start.backwards) {
13373 p = p->prev;
13374 if (!p)
13375 p = ifend;
13376 } else {
13377 p = p->next;
13378 if (!p)
13379 p = iflist;
13380 }
13381
13382 if (p == exitpvt)
13383 break;
13384 }
13385 ast_mutex_unlock(&iflock);
13386 restart_monitor();
13387 if (cause && !tmp) {
13388 if (callwait || channelmatched) {
13389 *cause = AST_CAUSE_BUSY;
13390 } else if (groupmatched) {
13391 *cause = AST_CAUSE_CONGESTION;
13392 } else {
13393
13394
13395
13396
13397 }
13398 }
13399
13400 return tmp;
13401 }
13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413 static int dahdi_devicestate(void *data)
13414 {
13415 #if defined(HAVE_PRI)
13416 char *device;
13417 unsigned span;
13418 int res;
13419
13420 device = data;
13421
13422 if (*device != 'I') {
13423
13424 return AST_DEVICE_UNKNOWN;
13425 }
13426 res = sscanf(device, "I%30u", &span);
13427 if (res != 1 || !span || NUM_SPANS < span) {
13428
13429 return AST_DEVICE_UNKNOWN;
13430 }
13431 device = strchr(device, '/');
13432 if (!device) {
13433
13434 return AST_DEVICE_UNKNOWN;
13435 }
13436
13437
13438
13439
13440
13441 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13442 ++device;
13443 if (!strcmp(device, "congestion"))
13444 #endif
13445 {
13446 return pris[span - 1].pri.congestion_devstate;
13447 }
13448 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13449 else if (!strcmp(device, "threshold")) {
13450 return pris[span - 1].pri.threshold_devstate;
13451 }
13452 return AST_DEVICE_UNKNOWN;
13453 #endif
13454 #else
13455 return AST_DEVICE_UNKNOWN;
13456 #endif
13457 }
13458
13459
13460
13461
13462
13463
13464
13465
13466
13467
13468
13469
13470
13471
13472
13473
13474
13475 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13476 {
13477 struct dahdi_pvt *p;
13478 struct dahdi_pvt *exitpvt;
13479 struct dahdi_starting_point start;
13480 int groupmatched = 0;
13481 int channelmatched = 0;
13482
13483 ast_mutex_lock(&iflock);
13484 p = determine_starting_point(dest, &start);
13485 if (!p) {
13486 ast_mutex_unlock(&iflock);
13487 return -1;
13488 }
13489 exitpvt = p;
13490 for (;;) {
13491 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13492
13493 struct ast_str *device_name;
13494 char *dash;
13495 const char *monitor_type;
13496 char dialstring[AST_CHANNEL_NAME];
13497 char full_device_name[AST_CHANNEL_NAME];
13498
13499 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13500 case AST_CC_MONITOR_NEVER:
13501 break;
13502 case AST_CC_MONITOR_NATIVE:
13503 case AST_CC_MONITOR_ALWAYS:
13504 case AST_CC_MONITOR_GENERIC:
13505 #if defined(HAVE_PRI)
13506 if (dahdi_sig_pri_lib_handles(p->sig)) {
13507
13508
13509
13510
13511 snprintf(full_device_name, sizeof(full_device_name),
13512 "DAHDI/I%d/congestion", p->pri->span);
13513 } else
13514 #endif
13515 {
13516 #if defined(HAVE_PRI)
13517 device_name = create_channel_name(p, 1, "");
13518 #else
13519 device_name = create_channel_name(p);
13520 #endif
13521 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13522 device_name ? ast_str_buffer(device_name) : "");
13523 ast_free(device_name);
13524
13525
13526
13527
13528
13529 dash = strrchr(full_device_name, '-');
13530 if (dash) {
13531 *dash = '\0';
13532 }
13533 }
13534 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13535
13536
13537
13538
13539
13540
13541
13542 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13543 callback(inbound,
13544 #if defined(HAVE_PRI)
13545 p->pri ? p->pri->cc_params : p->cc_params,
13546 #else
13547 p->cc_params,
13548 #endif
13549 monitor_type, full_device_name, dialstring, NULL);
13550 break;
13551 }
13552 }
13553 p = start.backwards ? p->prev : p->next;
13554 if (!p) {
13555 p = start.backwards ? ifend : iflist;
13556 }
13557 if (p == exitpvt) {
13558 break;
13559 }
13560 }
13561 ast_mutex_unlock(&iflock);
13562 return 0;
13563 }
13564
13565 #if defined(HAVE_SS7)
13566 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13567 {
13568 int i;
13569
13570 if (ss7) {
13571 for (i = 0; i < NUM_SPANS; i++) {
13572 if (linksets[i].ss7.ss7 == ss7) {
13573 ast_verbose("[%d] %s", i + 1, s);
13574 return;
13575 }
13576 }
13577 }
13578 ast_verbose("%s", s);
13579 }
13580 #endif
13581
13582 #if defined(HAVE_SS7)
13583 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13584 {
13585 int i;
13586
13587 if (ss7) {
13588 for (i = 0; i < NUM_SPANS; i++) {
13589 if (linksets[i].ss7.ss7 == ss7) {
13590 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13591 return;
13592 }
13593 }
13594 }
13595 ast_log(LOG_ERROR, "%s", s);
13596 }
13597 #endif
13598
13599 #if defined(HAVE_OPENR2)
13600 static void *mfcr2_monitor(void *data)
13601 {
13602 struct dahdi_mfcr2 *mfcr2 = data;
13603
13604
13605
13606
13607
13608 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13609 int res = 0;
13610 int i = 0;
13611 int oldstate = 0;
13612 int quit_loop = 0;
13613 int maxsleep = 20;
13614 int was_idle = 0;
13615 int pollsize = 0;
13616
13617
13618 for (i = 0; i < mfcr2->numchans; i++) {
13619 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13620 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13621 }
13622 while (1) {
13623
13624
13625 pollsize = 0;
13626 for (i = 0; i < mfcr2->numchans; i++) {
13627 pollers[i].revents = 0;
13628 pollers[i].events = 0;
13629 if (mfcr2->pvts[i]->owner) {
13630 continue;
13631 }
13632 if (!mfcr2->pvts[i]->r2chan) {
13633 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13634 quit_loop = 1;
13635 break;
13636 }
13637 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13638 pollers[i].events = POLLIN | POLLPRI;
13639 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13640 pollsize++;
13641 }
13642 if (quit_loop) {
13643 break;
13644 }
13645 if (pollsize == 0) {
13646 if (!was_idle) {
13647 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13648 was_idle = 1;
13649 }
13650 poll(NULL, 0, maxsleep);
13651 continue;
13652 }
13653 was_idle = 0;
13654
13655
13656 pthread_testcancel();
13657 res = poll(pollers, mfcr2->numchans, maxsleep);
13658 pthread_testcancel();
13659 if ((res < 0) && (errno != EINTR)) {
13660 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13661 break;
13662 }
13663
13664 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13665 for (i = 0; i < mfcr2->numchans; i++) {
13666 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13667 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13668 }
13669 }
13670 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13671 }
13672 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13673 return 0;
13674 }
13675 #endif
13676
13677 #if defined(HAVE_PRI)
13678 #ifndef PRI_RESTART
13679 #error "Upgrade your libpri"
13680 #endif
13681 static void dahdi_pri_message(struct pri *pri, char *s)
13682 {
13683 int x, y;
13684 int dchan = -1, span = -1, dchancount = 0;
13685
13686 if (pri) {
13687 for (x = 0; x < NUM_SPANS; x++) {
13688 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13689 if (pris[x].pri.dchans[y])
13690 dchancount++;
13691
13692 if (pris[x].pri.dchans[y] == pri)
13693 dchan = y;
13694 }
13695 if (dchan >= 0) {
13696 span = x;
13697 break;
13698 }
13699 dchancount = 0;
13700 }
13701 if (dchancount > 1 && (span > -1))
13702 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13703 else if (span > -1)
13704 ast_verbose("%d %s", span+1, s);
13705 else
13706 ast_verbose("%s", s);
13707 } else
13708 ast_verbose("%s", s);
13709
13710 ast_mutex_lock(&pridebugfdlock);
13711
13712 if (pridebugfd >= 0) {
13713 if (write(pridebugfd, s, strlen(s)) < 0) {
13714 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13715 }
13716 }
13717
13718 ast_mutex_unlock(&pridebugfdlock);
13719 }
13720 #endif
13721
13722 #if defined(HAVE_PRI)
13723 static void dahdi_pri_error(struct pri *pri, char *s)
13724 {
13725 int x, y;
13726 int dchan = -1, span = -1;
13727 int dchancount = 0;
13728
13729 if (pri) {
13730 for (x = 0; x < NUM_SPANS; x++) {
13731 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13732 if (pris[x].pri.dchans[y])
13733 dchancount++;
13734
13735 if (pris[x].pri.dchans[y] == pri)
13736 dchan = y;
13737 }
13738 if (dchan >= 0) {
13739 span = x;
13740 break;
13741 }
13742 dchancount = 0;
13743 }
13744 if ((dchancount > 1) && (span > -1))
13745 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13746 else if (span > -1)
13747 ast_log(LOG_ERROR, "%d %s", span+1, s);
13748 else
13749 ast_log(LOG_ERROR, "%s", s);
13750 } else
13751 ast_log(LOG_ERROR, "%s", s);
13752
13753 ast_mutex_lock(&pridebugfdlock);
13754
13755 if (pridebugfd >= 0) {
13756 if (write(pridebugfd, s, strlen(s)) < 0) {
13757 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13758 }
13759 }
13760
13761 ast_mutex_unlock(&pridebugfdlock);
13762 }
13763 #endif
13764
13765 #if defined(HAVE_PRI)
13766 static int prepare_pri(struct dahdi_pri *pri)
13767 {
13768 int i, res, x;
13769 struct dahdi_params p;
13770 struct dahdi_bufferinfo bi;
13771 struct dahdi_spaninfo si;
13772
13773 pri->pri.calls = &dahdi_pri_callbacks;
13774
13775 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
13776 if (!pri->dchannels[i])
13777 break;
13778 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
13779 x = pri->dchannels[i];
13780 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
13781 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13782 return -1;
13783 }
13784 memset(&p, 0, sizeof(p));
13785 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
13786 if (res) {
13787 dahdi_close_pri_fd(pri, i);
13788 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13789 return -1;
13790 }
13791 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13792 dahdi_close_pri_fd(pri, i);
13793 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13794 return -1;
13795 }
13796 memset(&si, 0, sizeof(si));
13797 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
13798 if (res) {
13799 dahdi_close_pri_fd(pri, i);
13800 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13801 }
13802 if (!si.alarms) {
13803 pri_event_noalarm(&pri->pri, i, 1);
13804 } else {
13805 pri_event_alarm(&pri->pri, i, 1);
13806 }
13807 memset(&bi, 0, sizeof(bi));
13808 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13809 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13810 bi.numbufs = 32;
13811 bi.bufsize = 1024;
13812 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
13813 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13814 dahdi_close_pri_fd(pri, i);
13815 return -1;
13816 }
13817 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
13818 }
13819 return 0;
13820 }
13821 #endif
13822
13823 #if defined(HAVE_PRI)
13824 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13825 {
13826 int which, span;
13827 char *ret = NULL;
13828
13829 if (pos != rpos)
13830 return ret;
13831
13832 for (which = span = 0; span < NUM_SPANS; span++) {
13833 if (pris[span].pri.pri && ++which > state) {
13834 if (asprintf(&ret, "%d", span + 1) < 0) {
13835 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13836 }
13837 break;
13838 }
13839 }
13840 return ret;
13841 }
13842 #endif
13843
13844 #if defined(HAVE_PRI)
13845 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13846 {
13847 return complete_span_helper(line,word,pos,state,3);
13848 }
13849 #endif
13850
13851 #if defined(HAVE_PRI)
13852 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13853 {
13854 int myfd;
13855 switch (cmd) {
13856 case CLI_INIT:
13857 e->command = "pri set debug file";
13858 e->usage = "Usage: pri set debug file [output-file]\n"
13859 " Sends PRI debug output to the specified output file\n";
13860 return NULL;
13861 case CLI_GENERATE:
13862 return NULL;
13863 }
13864 if (a->argc < 5)
13865 return CLI_SHOWUSAGE;
13866
13867 if (ast_strlen_zero(a->argv[4]))
13868 return CLI_SHOWUSAGE;
13869
13870 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13871 if (myfd < 0) {
13872 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13873 return CLI_SUCCESS;
13874 }
13875
13876 ast_mutex_lock(&pridebugfdlock);
13877
13878 if (pridebugfd >= 0)
13879 close(pridebugfd);
13880
13881 pridebugfd = myfd;
13882 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13883 ast_mutex_unlock(&pridebugfdlock);
13884 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13885 return CLI_SUCCESS;
13886 }
13887 #endif
13888
13889 #if defined(HAVE_PRI)
13890 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13891 {
13892 int span;
13893 int x;
13894 int level = 0;
13895 switch (cmd) {
13896 case CLI_INIT:
13897 e->command = "pri set debug {on|off|0|1|2} span";
13898 e->usage =
13899 "Usage: pri set debug {<level>|on|off} span <span>\n"
13900 " Enables debugging on a given PRI span\n";
13901 return NULL;
13902 case CLI_GENERATE:
13903 return complete_span_4(a->line, a->word, a->pos, a->n);
13904 }
13905 if (a->argc < 6) {
13906 return CLI_SHOWUSAGE;
13907 }
13908
13909 if (!strcasecmp(a->argv[3], "on")) {
13910 level = 1;
13911 } else if (!strcasecmp(a->argv[3], "off")) {
13912 level = 0;
13913 } else {
13914 level = atoi(a->argv[3]);
13915 }
13916 span = atoi(a->argv[5]);
13917 if ((span < 1) || (span > NUM_SPANS)) {
13918 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13919 return CLI_SUCCESS;
13920 }
13921 if (!pris[span-1].pri.pri) {
13922 ast_cli(a->fd, "No PRI running on span %d\n", span);
13923 return CLI_SUCCESS;
13924 }
13925
13926
13927 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
13928 if (pris[span - 1].pri.dchans[x]) {
13929 switch (level) {
13930 case 0:
13931 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
13932 break;
13933 case 1:
13934 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
13935 break;
13936 default:
13937 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
13938 break;
13939 }
13940 }
13941 }
13942 if (level == 0) {
13943
13944 ast_mutex_lock(&pridebugfdlock);
13945 if (0 <= pridebugfd) {
13946 close(pridebugfd);
13947 pridebugfd = -1;
13948 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
13949 pridebugfilename);
13950 }
13951 ast_mutex_unlock(&pridebugfdlock);
13952 }
13953 pris[span - 1].pri.debug = (level) ? 1 : 0;
13954 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
13955 return CLI_SUCCESS;
13956 }
13957 #endif
13958
13959 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13960 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
13961 {
13962 unsigned *why;
13963 int channel;
13964 int trunkgroup;
13965 int x, y, fd = a->fd;
13966 int interfaceid = 0;
13967 char *c;
13968 char db_chan_name[20], db_answer[5];
13969 struct dahdi_pvt *tmp;
13970 struct dahdi_pri *pri;
13971
13972 if (a->argc < 5 || a->argc > 6)
13973 return CLI_SHOWUSAGE;
13974 if ((c = strchr(a->argv[4], ':'))) {
13975 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
13976 return CLI_SHOWUSAGE;
13977 if ((trunkgroup < 1) || (channel < 1))
13978 return CLI_SHOWUSAGE;
13979 pri = NULL;
13980 for (x=0;x<NUM_SPANS;x++) {
13981 if (pris[x].pri.trunkgroup == trunkgroup) {
13982 pri = pris + x;
13983 break;
13984 }
13985 }
13986 if (!pri) {
13987 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13988 return CLI_FAILURE;
13989 }
13990 } else
13991 channel = atoi(a->argv[4]);
13992
13993 if (a->argc == 6)
13994 interfaceid = atoi(a->argv[5]);
13995
13996
13997 for (x = 0; x < NUM_SPANS; x++) {
13998 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13999 if (pris[x].dchannels[y] == channel) {
14000 pri = pris + x;
14001 if (pri->pri.enable_service_message_support) {
14002 ast_mutex_lock(&pri->pri.lock);
14003 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
14004 ast_mutex_unlock(&pri->pri.lock);
14005 } else {
14006 ast_cli(fd,
14007 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14008 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14009 }
14010 return CLI_SUCCESS;
14011 }
14012 }
14013 }
14014
14015
14016 ast_mutex_lock(&iflock);
14017 for (tmp = iflist; tmp; tmp = tmp->next) {
14018 if (tmp->pri && tmp->channel == channel) {
14019 ast_mutex_unlock(&iflock);
14020 ast_mutex_lock(&tmp->pri->lock);
14021 if (!tmp->pri->enable_service_message_support) {
14022 ast_mutex_unlock(&tmp->pri->lock);
14023 ast_cli(fd,
14024 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
14025 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
14026 return CLI_SUCCESS;
14027 }
14028 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14029 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14030 switch(changestatus) {
14031 case 0:
14032
14033 ast_db_del(db_chan_name, SRVST_DBKEY);
14034 *why &= ~SRVST_NEAREND;
14035 if (*why) {
14036 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14037 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14038 } else {
14039 dahdi_pri_update_span_devstate(tmp->pri);
14040 }
14041 break;
14042
14043 case 2:
14044
14045 ast_db_del(db_chan_name, SRVST_DBKEY);
14046 *why |= SRVST_NEAREND;
14047 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14048 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14049 dahdi_pri_update_span_devstate(tmp->pri);
14050 break;
14051
14052
14053 default:
14054 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14055 break;
14056 }
14057 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14058 ast_mutex_unlock(&tmp->pri->lock);
14059 return CLI_SUCCESS;
14060 }
14061 }
14062 ast_mutex_unlock(&iflock);
14063
14064 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14065 return CLI_FAILURE;
14066 }
14067
14068 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14069 {
14070 switch (cmd) {
14071 case CLI_INIT:
14072 e->command = "pri service enable channel";
14073 e->usage =
14074 "Usage: pri service enable channel <channel> [<interface id>]\n"
14075 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14076 " to restore a channel to service, with optional interface id\n"
14077 " as agreed upon with remote switch operator\n";
14078 return NULL;
14079 case CLI_GENERATE:
14080 return NULL;
14081 }
14082 return handle_pri_service_generic(e, cmd, a, 0);
14083 }
14084
14085 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14086 {
14087 switch (cmd) {
14088 case CLI_INIT:
14089 e->command = "pri service disable channel";
14090 e->usage =
14091 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14092 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14093 " to remove a channel from service, with optional interface id\n"
14094 " as agreed upon with remote switch operator\n";
14095 return NULL;
14096 case CLI_GENERATE:
14097 return NULL;
14098 }
14099 return handle_pri_service_generic(e, cmd, a, 2);
14100 }
14101 #endif
14102
14103 #if defined(HAVE_PRI)
14104 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14105 {
14106 int span;
14107
14108 switch (cmd) {
14109 case CLI_INIT:
14110 e->command = "pri show spans";
14111 e->usage =
14112 "Usage: pri show spans\n"
14113 " Displays PRI Information\n";
14114 return NULL;
14115 case CLI_GENERATE:
14116 return NULL;
14117 }
14118
14119 if (a->argc != 3)
14120 return CLI_SHOWUSAGE;
14121
14122 for (span = 0; span < NUM_SPANS; span++) {
14123 if (pris[span].pri.pri) {
14124 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14125 }
14126 }
14127 return CLI_SUCCESS;
14128 }
14129 #endif
14130
14131 #if defined(HAVE_PRI)
14132 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14133 {
14134 int span;
14135
14136 switch (cmd) {
14137 case CLI_INIT:
14138 e->command = "pri show span";
14139 e->usage =
14140 "Usage: pri show span <span>\n"
14141 " Displays PRI Information on a given PRI span\n";
14142 return NULL;
14143 case CLI_GENERATE:
14144 return complete_span_4(a->line, a->word, a->pos, a->n);
14145 }
14146
14147 if (a->argc < 4)
14148 return CLI_SHOWUSAGE;
14149 span = atoi(a->argv[3]);
14150 if ((span < 1) || (span > NUM_SPANS)) {
14151 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14152 return CLI_SUCCESS;
14153 }
14154 if (!pris[span-1].pri.pri) {
14155 ast_cli(a->fd, "No PRI running on span %d\n", span);
14156 return CLI_SUCCESS;
14157 }
14158
14159 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14160
14161 return CLI_SUCCESS;
14162 }
14163 #endif
14164
14165 #if defined(HAVE_PRI)
14166 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14167 {
14168 int x;
14169 int span;
14170 int count=0;
14171 int debug;
14172
14173 switch (cmd) {
14174 case CLI_INIT:
14175 e->command = "pri show debug";
14176 e->usage =
14177 "Usage: pri show debug\n"
14178 " Show the debug state of pri spans\n";
14179 return NULL;
14180 case CLI_GENERATE:
14181 return NULL;
14182 }
14183
14184 for (span = 0; span < NUM_SPANS; span++) {
14185 if (pris[span].pri.pri) {
14186 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14187 if (pris[span].pri.dchans[x]) {
14188 debug = pri_get_debug(pris[span].pri.dchans[x]);
14189 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" );
14190 count++;
14191 }
14192 }
14193 }
14194
14195 }
14196 ast_mutex_lock(&pridebugfdlock);
14197 if (pridebugfd >= 0)
14198 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14199 ast_mutex_unlock(&pridebugfdlock);
14200
14201 if (!count)
14202 ast_cli(a->fd, "No PRI running\n");
14203 return CLI_SUCCESS;
14204 }
14205 #endif
14206
14207 #if defined(HAVE_PRI)
14208 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14209 {
14210 switch (cmd) {
14211 case CLI_INIT:
14212 e->command = "pri show version";
14213 e->usage =
14214 "Usage: pri show version\n"
14215 "Show libpri version information\n";
14216 return NULL;
14217 case CLI_GENERATE:
14218 return NULL;
14219 }
14220
14221 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14222
14223 return CLI_SUCCESS;
14224 }
14225 #endif
14226
14227 #if defined(HAVE_PRI)
14228 static struct ast_cli_entry dahdi_pri_cli[] = {
14229 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14230 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14231 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14232 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14233 #endif
14234 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14235 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14236 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14237 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14238 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14239 };
14240 #endif
14241
14242 #ifdef HAVE_OPENR2
14243
14244 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14245 {
14246 switch (cmd) {
14247 case CLI_INIT:
14248 e->command = "mfcr2 show version";
14249 e->usage =
14250 "Usage: mfcr2 show version\n"
14251 " Shows the version of the OpenR2 library being used.\n";
14252 return NULL;
14253 case CLI_GENERATE:
14254 return NULL;
14255 }
14256 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14257 return CLI_SUCCESS;
14258 }
14259
14260 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14261 {
14262 #define FORMAT "%4s %40s\n"
14263 int i = 0;
14264 int numvariants = 0;
14265 const openr2_variant_entry_t *variants;
14266 switch (cmd) {
14267 case CLI_INIT:
14268 e->command = "mfcr2 show variants";
14269 e->usage =
14270 "Usage: mfcr2 show variants\n"
14271 " Shows the list of MFC/R2 variants supported.\n";
14272 return NULL;
14273 case CLI_GENERATE:
14274 return NULL;
14275 }
14276 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14277 ast_cli(a->fd, "Failed to get list of variants.\n");
14278 return CLI_FAILURE;
14279 }
14280 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14281 for (i = 0; i < numvariants; i++) {
14282 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14283 }
14284 return CLI_SUCCESS;
14285 #undef FORMAT
14286 }
14287
14288 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14289 {
14290 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14291 int filtertype = 0;
14292 int targetnum = 0;
14293 char channo[5];
14294 char anino[5];
14295 char dnisno[5];
14296 struct dahdi_pvt *p;
14297 openr2_context_t *r2context;
14298 openr2_variant_t r2variant;
14299 switch (cmd) {
14300 case CLI_INIT:
14301 e->command = "mfcr2 show channels [group|context]";
14302 e->usage =
14303 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14304 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14305 return NULL;
14306 case CLI_GENERATE:
14307 return NULL;
14308 }
14309 if (!((a->argc == 3) || (a->argc == 5))) {
14310 return CLI_SHOWUSAGE;
14311 }
14312 if (a->argc == 5) {
14313 if (!strcasecmp(a->argv[3], "group")) {
14314 targetnum = atoi(a->argv[4]);
14315 if ((targetnum < 0) || (targetnum > 63))
14316 return CLI_SHOWUSAGE;
14317 targetnum = 1 << targetnum;
14318 filtertype = 1;
14319 } else if (!strcasecmp(a->argv[3], "context")) {
14320 filtertype = 2;
14321 } else {
14322 return CLI_SHOWUSAGE;
14323 }
14324 }
14325 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14326 ast_mutex_lock(&iflock);
14327 for (p = iflist; p; p = p->next) {
14328 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14329 continue;
14330 }
14331 if (filtertype) {
14332 switch(filtertype) {
14333 case 1:
14334 if (p->group != targetnum) {
14335 continue;
14336 }
14337 break;
14338 case 2:
14339 if (strcasecmp(p->context, a->argv[4])) {
14340 continue;
14341 }
14342 break;
14343 default:
14344 ;
14345 }
14346 }
14347 r2context = openr2_chan_get_context(p->r2chan);
14348 r2variant = openr2_context_get_variant(r2context);
14349 snprintf(channo, sizeof(channo), "%d", p->channel);
14350 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14351 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14352 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14353 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14354 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14355 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14356 }
14357 ast_mutex_unlock(&iflock);
14358 return CLI_SUCCESS;
14359 #undef FORMAT
14360 }
14361
14362 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14363 {
14364 struct dahdi_pvt *p = NULL;
14365 int channo = 0;
14366 char *toklevel = NULL;
14367 char *saveptr = NULL;
14368 char *logval = NULL;
14369 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14370 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14371 switch (cmd) {
14372 case CLI_INIT:
14373 e->command = "mfcr2 set debug";
14374 e->usage =
14375 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14376 " Set a new logging level for the specified channel.\n"
14377 " If no channel is specified the logging level will be applied to all channels.\n";
14378 return NULL;
14379 case CLI_GENERATE:
14380 return NULL;
14381 }
14382 if (a->argc < 4) {
14383 return CLI_SHOWUSAGE;
14384 }
14385 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14386 logval = ast_strdupa(a->argv[3]);
14387 toklevel = strtok_r(logval, ",", &saveptr);
14388 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14389 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14390 return CLI_FAILURE;
14391 } else if (OR2_LOG_NOTHING == tmplevel) {
14392 loglevel = tmplevel;
14393 } else {
14394 loglevel |= tmplevel;
14395 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14396 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14397 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14398 continue;
14399 }
14400 loglevel |= tmplevel;
14401 }
14402 }
14403 ast_mutex_lock(&iflock);
14404 for (p = iflist; p; p = p->next) {
14405 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14406 continue;
14407 }
14408 if ((channo != -1) && (p->channel != channo )) {
14409 continue;
14410 }
14411 openr2_chan_set_log_level(p->r2chan, loglevel);
14412 if (channo != -1) {
14413 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14414 break;
14415 }
14416 }
14417 if ((channo != -1) && !p) {
14418 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14419 }
14420 if (channo == -1) {
14421 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14422 }
14423 ast_mutex_unlock(&iflock);
14424 return CLI_SUCCESS;
14425 }
14426
14427 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14428 {
14429 struct dahdi_pvt *p = NULL;
14430 int channo = 0;
14431 switch (cmd) {
14432 case CLI_INIT:
14433 e->command = "mfcr2 call files [on|off]";
14434 e->usage =
14435 "Usage: mfcr2 call files [on|off] <channel>\n"
14436 " Enable call files creation on the specified channel.\n"
14437 " If no channel is specified call files creation policy will be applied to all channels.\n";
14438 return NULL;
14439 case CLI_GENERATE:
14440 return NULL;
14441 }
14442 if (a->argc < 4) {
14443 return CLI_SHOWUSAGE;
14444 }
14445 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14446 ast_mutex_lock(&iflock);
14447 for (p = iflist; p; p = p->next) {
14448 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14449 continue;
14450 }
14451 if ((channo != -1) && (p->channel != channo )) {
14452 continue;
14453 }
14454 if (ast_true(a->argv[3])) {
14455 openr2_chan_enable_call_files(p->r2chan);
14456 } else {
14457 openr2_chan_disable_call_files(p->r2chan);
14458 }
14459 if (channo != -1) {
14460 if (ast_true(a->argv[3])) {
14461 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14462 } else {
14463 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14464 }
14465 break;
14466 }
14467 }
14468 if ((channo != -1) && !p) {
14469 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14470 }
14471 if (channo == -1) {
14472 if (ast_true(a->argv[3])) {
14473 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14474 } else {
14475 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14476 }
14477 }
14478 ast_mutex_unlock(&iflock);
14479 return CLI_SUCCESS;
14480 }
14481
14482 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14483 {
14484 struct dahdi_pvt *p = NULL;
14485 int channo = 0;
14486 switch (cmd) {
14487 case CLI_INIT:
14488 e->command = "mfcr2 set idle";
14489 e->usage =
14490 "Usage: mfcr2 set idle <channel>\n"
14491 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14492 " Force the given channel into IDLE state.\n"
14493 " If no channel is specified, all channels will be set to IDLE.\n";
14494 return NULL;
14495 case CLI_GENERATE:
14496 return NULL;
14497 }
14498 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14499 ast_mutex_lock(&iflock);
14500 for (p = iflist; p; p = p->next) {
14501 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14502 continue;
14503 }
14504 if ((channo != -1) && (p->channel != channo )) {
14505 continue;
14506 }
14507 openr2_chan_set_idle(p->r2chan);
14508 ast_mutex_lock(&p->lock);
14509 p->locallyblocked = 0;
14510 p->mfcr2call = 0;
14511 ast_mutex_unlock(&p->lock);
14512 if (channo != -1) {
14513 break;
14514 }
14515 }
14516 if ((channo != -1) && !p) {
14517 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14518 }
14519 ast_mutex_unlock(&iflock);
14520 return CLI_SUCCESS;
14521 }
14522
14523 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14524 {
14525 struct dahdi_pvt *p = NULL;
14526 int channo = 0;
14527 switch (cmd) {
14528 case CLI_INIT:
14529 e->command = "mfcr2 set blocked";
14530 e->usage =
14531 "Usage: mfcr2 set blocked <channel>\n"
14532 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14533 " Force the given channel into BLOCKED state.\n"
14534 " If no channel is specified, all channels will be set to BLOCKED.\n";
14535 return NULL;
14536 case CLI_GENERATE:
14537 return NULL;
14538 }
14539 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14540 ast_mutex_lock(&iflock);
14541 for (p = iflist; p; p = p->next) {
14542 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14543 continue;
14544 }
14545 if ((channo != -1) && (p->channel != channo )) {
14546 continue;
14547 }
14548 openr2_chan_set_blocked(p->r2chan);
14549 ast_mutex_lock(&p->lock);
14550 p->locallyblocked = 1;
14551 ast_mutex_unlock(&p->lock);
14552 if (channo != -1) {
14553 break;
14554 }
14555 }
14556 if ((channo != -1) && !p) {
14557 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14558 }
14559 ast_mutex_unlock(&iflock);
14560 return CLI_SUCCESS;
14561 }
14562
14563 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14564 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14565 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14566 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14567 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14568 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14569 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14570 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14571 };
14572
14573 #endif
14574
14575 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14576 {
14577 int channel;
14578 int ret;
14579 switch (cmd) {
14580 case CLI_INIT:
14581 e->command = "dahdi destroy channel";
14582 e->usage =
14583 "Usage: dahdi destroy channel <chan num>\n"
14584 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14585 return NULL;
14586 case CLI_GENERATE:
14587 return NULL;
14588 }
14589 if (a->argc != 4)
14590 return CLI_SHOWUSAGE;
14591
14592 channel = atoi(a->argv[3]);
14593 ret = dahdi_destroy_channel_bynum(channel);
14594 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14595 }
14596
14597 static void dahdi_softhangup_all(void)
14598 {
14599 struct dahdi_pvt *p;
14600 retry:
14601 ast_mutex_lock(&iflock);
14602 for (p = iflist; p; p = p->next) {
14603 ast_mutex_lock(&p->lock);
14604 if (p->owner && !p->restartpending) {
14605 if (ast_channel_trylock(p->owner)) {
14606 if (option_debug > 2)
14607 ast_verbose("Avoiding deadlock\n");
14608
14609 ast_mutex_unlock(&p->lock);
14610 ast_mutex_unlock(&iflock);
14611 goto retry;
14612 }
14613 if (option_debug > 2)
14614 ast_verbose("Softhanging up on %s\n", p->owner->name);
14615 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14616 p->restartpending = 1;
14617 num_restart_pending++;
14618 ast_channel_unlock(p->owner);
14619 }
14620 ast_mutex_unlock(&p->lock);
14621 }
14622 ast_mutex_unlock(&iflock);
14623 }
14624
14625 static int setup_dahdi(int reload);
14626 static int dahdi_restart(void)
14627 {
14628 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14629 int i, j;
14630 #endif
14631 int cancel_code;
14632 struct dahdi_pvt *p;
14633
14634 ast_mutex_lock(&restart_lock);
14635 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14636 dahdi_softhangup_all();
14637 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14638 #ifdef HAVE_OPENR2
14639 dahdi_r2_destroy_links();
14640 #endif
14641
14642 #if defined(HAVE_PRI)
14643 for (i = 0; i < NUM_SPANS; i++) {
14644 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14645 cancel_code = pthread_cancel(pris[i].pri.master);
14646 pthread_kill(pris[i].pri.master, SIGURG);
14647 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);
14648 pthread_join(pris[i].pri.master, NULL);
14649 ast_debug(4, "Joined thread of span %d\n", i);
14650 }
14651 }
14652 #endif
14653
14654 #if defined(HAVE_SS7)
14655 for (i = 0; i < NUM_SPANS; i++) {
14656 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14657 cancel_code = pthread_cancel(linksets[i].ss7.master);
14658 pthread_kill(linksets[i].ss7.master, SIGURG);
14659 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);
14660 pthread_join(linksets[i].ss7.master, NULL);
14661 ast_debug(4, "Joined thread of span %d\n", i);
14662 }
14663 }
14664 #endif
14665
14666 ast_mutex_lock(&monlock);
14667 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14668 cancel_code = pthread_cancel(monitor_thread);
14669 pthread_kill(monitor_thread, SIGURG);
14670 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14671 pthread_join(monitor_thread, NULL);
14672 ast_debug(4, "Joined monitor thread\n");
14673 }
14674 monitor_thread = AST_PTHREADT_NULL;
14675
14676 ast_mutex_lock(&ss_thread_lock);
14677 while (ss_thread_count > 0) {
14678 int x = DAHDI_FLASH;
14679 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14680
14681 ast_mutex_lock(&iflock);
14682 for (p = iflist; p; p = p->next) {
14683 if (p->owner) {
14684
14685 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14686 }
14687 }
14688 ast_mutex_unlock(&iflock);
14689 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14690 }
14691
14692
14693 dahdi_softhangup_all();
14694 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14695 destroy_all_channels();
14696 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14697
14698 ast_mutex_unlock(&monlock);
14699
14700 #ifdef HAVE_PRI
14701 for (i = 0; i < NUM_SPANS; i++) {
14702 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14703 dahdi_close_pri_fd(&(pris[i]), j);
14704 }
14705
14706 memset(pris, 0, sizeof(pris));
14707 for (i = 0; i < NUM_SPANS; i++) {
14708 sig_pri_init_pri(&pris[i].pri);
14709 }
14710 pri_set_error(dahdi_pri_error);
14711 pri_set_message(dahdi_pri_message);
14712 #endif
14713 #if defined(HAVE_SS7)
14714 for (i = 0; i < NUM_SPANS; i++) {
14715 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14716 dahdi_close_ss7_fd(&(linksets[i]), j);
14717 }
14718
14719 memset(linksets, 0, sizeof(linksets));
14720 for (i = 0; i < NUM_SPANS; i++) {
14721 sig_ss7_init_linkset(&linksets[i].ss7);
14722 }
14723 ss7_set_error(dahdi_ss7_error);
14724 ss7_set_message(dahdi_ss7_message);
14725 #endif
14726
14727 if (setup_dahdi(2) != 0) {
14728 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14729 ast_mutex_unlock(&ss_thread_lock);
14730 return 1;
14731 }
14732 ast_mutex_unlock(&ss_thread_lock);
14733 ast_mutex_unlock(&restart_lock);
14734 return 0;
14735 }
14736
14737 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14738 {
14739 switch (cmd) {
14740 case CLI_INIT:
14741 e->command = "dahdi restart";
14742 e->usage =
14743 "Usage: dahdi restart\n"
14744 " Restarts the DAHDI channels: destroys them all and then\n"
14745 " re-reads them from chan_dahdi.conf.\n"
14746 " Note that this will STOP any running CALL on DAHDI channels.\n"
14747 "";
14748 return NULL;
14749 case CLI_GENERATE:
14750 return NULL;
14751 }
14752 if (a->argc != 2)
14753 return CLI_SHOWUSAGE;
14754
14755 if (dahdi_restart() != 0)
14756 return CLI_FAILURE;
14757 return CLI_SUCCESS;
14758 }
14759
14760 static int action_dahdirestart(struct mansession *s, const struct message *m)
14761 {
14762 if (dahdi_restart() != 0) {
14763 astman_send_error(s, m, "Failed rereading DAHDI configuration");
14764 return 1;
14765 }
14766 astman_send_ack(s, m, "DAHDIRestart: Success");
14767 return 0;
14768 }
14769
14770 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14771 {
14772 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14773 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14774 unsigned int targetnum = 0;
14775 int filtertype = 0;
14776 struct dahdi_pvt *tmp = NULL;
14777 char tmps[20] = "";
14778 char statestr[20] = "";
14779 char blockstr[20] = "";
14780
14781 switch (cmd) {
14782 case CLI_INIT:
14783 e->command = "dahdi show channels [group|context]";
14784 e->usage =
14785 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
14786 " Shows a list of available channels with optional filtering\n"
14787 " <group> must be a number between 0 and 63\n";
14788 return NULL;
14789 case CLI_GENERATE:
14790 return NULL;
14791 }
14792
14793
14794
14795 if (!((a->argc == 3) || (a->argc == 5)))
14796 return CLI_SHOWUSAGE;
14797
14798 if (a->argc == 5) {
14799 if (!strcasecmp(a->argv[3], "group")) {
14800 targetnum = atoi(a->argv[4]);
14801 if ((targetnum < 0) || (targetnum > 63))
14802 return CLI_SHOWUSAGE;
14803 targetnum = 1 << targetnum;
14804 filtertype = 1;
14805 } else if (!strcasecmp(a->argv[3], "context")) {
14806 filtertype = 2;
14807 }
14808 }
14809
14810 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14811 ast_mutex_lock(&iflock);
14812 for (tmp = iflist; tmp; tmp = tmp->next) {
14813 if (filtertype) {
14814 switch(filtertype) {
14815 case 1:
14816 if (!(tmp->group & targetnum)) {
14817 continue;
14818 }
14819 break;
14820 case 2:
14821 if (strcasecmp(tmp->context, a->argv[4])) {
14822 continue;
14823 }
14824 break;
14825 default:
14826 ;
14827 }
14828 }
14829 if (tmp->channel > 0) {
14830 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14831 } else
14832 ast_copy_string(tmps, "pseudo", sizeof(tmps));
14833
14834 if (tmp->locallyblocked)
14835 blockstr[0] = 'L';
14836 else
14837 blockstr[0] = ' ';
14838
14839 if (tmp->remotelyblocked)
14840 blockstr[1] = 'R';
14841 else
14842 blockstr[1] = ' ';
14843
14844 blockstr[2] = '\0';
14845
14846 snprintf(statestr, sizeof(statestr), "%s", "In Service");
14847
14848 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14849 }
14850 ast_mutex_unlock(&iflock);
14851 return CLI_SUCCESS;
14852 #undef FORMAT
14853 #undef FORMAT2
14854 }
14855
14856 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14857 {
14858 int channel;
14859 struct dahdi_pvt *tmp = NULL;
14860 struct dahdi_confinfo ci;
14861 struct dahdi_params ps;
14862 int x;
14863
14864 switch (cmd) {
14865 case CLI_INIT:
14866 e->command = "dahdi show channel";
14867 e->usage =
14868 "Usage: dahdi show channel <chan num>\n"
14869 " Detailed information about a given channel\n";
14870 return NULL;
14871 case CLI_GENERATE:
14872 return NULL;
14873 }
14874
14875 if (a->argc != 4)
14876 return CLI_SHOWUSAGE;
14877
14878 channel = atoi(a->argv[3]);
14879
14880 ast_mutex_lock(&iflock);
14881 for (tmp = iflist; tmp; tmp = tmp->next) {
14882 if (tmp->channel == channel) {
14883 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14884 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14885 ast_cli(a->fd, "Span: %d\n", tmp->span);
14886 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14887 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14888 ast_cli(a->fd, "Context: %s\n", tmp->context);
14889 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14890 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14891 #if defined(HAVE_PRI)
14892 #if defined(HAVE_PRI_SUBADDR)
14893 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
14894 #endif
14895 #endif
14896 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14897 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14898 if (tmp->vars) {
14899 struct ast_variable *v;
14900 ast_cli(a->fd, "Variables:\n");
14901 for (v = tmp->vars ; v ; v = v->next)
14902 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
14903 }
14904 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14905 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14906 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14907 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14908 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14909 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)" : "");
14910 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)" : "");
14911 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)" : "");
14912 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14913 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14914 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14915 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14916 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14917 if (tmp->busydetect) {
14918 #if defined(BUSYDETECT_TONEONLY)
14919 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14920 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14921 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14922 #endif
14923 #ifdef BUSYDETECT_DEBUG
14924 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
14925 #endif
14926 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
14927 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
14928 }
14929 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14930 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14931 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14932 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14933 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14934 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14935 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
14936 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
14937 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
14938 ast_cli(a->fd, "Echo Cancellation:\n");
14939
14940 if (tmp->echocancel.head.tap_length) {
14941 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14942 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14943 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14944 }
14945 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14946 } else {
14947 ast_cli(a->fd, "\tnone\n");
14948 }
14949 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14950 if (tmp->master)
14951 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14952 for (x = 0; x < MAX_SLAVES; x++) {
14953 if (tmp->slaves[x])
14954 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14955 }
14956 #ifdef HAVE_OPENR2
14957 if (tmp->mfcr2) {
14958 char calldir[OR2_MAX_PATH];
14959 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14960 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14961 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14962 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14963 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14964 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14965 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14966 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14967 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14968 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14969 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14970 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14971 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14972 #endif
14973 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14974 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14975 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14976 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14977 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14978 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14979 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14980 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14981 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14982 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14983 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14984 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14985 }
14986 #endif
14987 #if defined(HAVE_SS7)
14988 if (tmp->ss7) {
14989 struct sig_ss7_chan *chan = tmp->sig_pvt;
14990
14991 ast_cli(a->fd, "CIC: %d\n", chan->cic);
14992 }
14993 #endif
14994 #ifdef HAVE_PRI
14995 if (tmp->pri) {
14996 struct sig_pri_chan *chan = tmp->sig_pvt;
14997
14998 ast_cli(a->fd, "PRI Flags: ");
14999 if (chan->resetting)
15000 ast_cli(a->fd, "Resetting ");
15001 if (chan->call)
15002 ast_cli(a->fd, "Call ");
15003 ast_cli(a->fd, "\n");
15004 if (tmp->logicalspan)
15005 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
15006 else
15007 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
15008 }
15009 #endif
15010 memset(&ci, 0, sizeof(ci));
15011 ps.channo = tmp->channel;
15012 if (tmp->subs[SUB_REAL].dfd > -1) {
15013 memset(&ci, 0, sizeof(ci));
15014 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
15015 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
15016 }
15017 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
15018 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
15019 }
15020 memset(&ps, 0, sizeof(ps));
15021 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
15022 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
15023 } else {
15024 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
15025 }
15026 }
15027 if (ISTRUNK(tmp)) {
15028 ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");
15029 if (!ast_strlen_zero(progzone))
15030 ast_cli(a->fd, "Progress Zone: %s\n", progzone);
15031 ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");
15032 if(tmp->busydetect) {
15033 ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
15034 if(tmp->busytonelength > 0) {
15035 ast_cli(a->fd, "Busy Pattern:\n");
15036 ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
15037 if (tmp->busyquietlength > 0)
15038 ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
15039 else
15040 ast_cli(a->fd, " -- Detect Tone Only\n");
15041 if(tmp->busyfuzziness > 0)
15042 ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
15043 }
15044 }
15045 }
15046 ast_mutex_unlock(&iflock);
15047 return CLI_SUCCESS;
15048 }
15049 }
15050 ast_mutex_unlock(&iflock);
15051
15052 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15053 return CLI_FAILURE;
15054 }
15055
15056 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15057 {
15058 int i, j;
15059 switch (cmd) {
15060 case CLI_INIT:
15061 e->command = "dahdi show cadences";
15062 e->usage =
15063 "Usage: dahdi show cadences\n"
15064 " Shows all cadences currently defined\n";
15065 return NULL;
15066 case CLI_GENERATE:
15067 return NULL;
15068 }
15069 for (i = 0; i < num_cadence; i++) {
15070 char output[1024];
15071 char tmp[16], tmp2[64];
15072 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15073 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15074
15075 for (j = 0; j < 16; j++) {
15076 if (cadences[i].ringcadence[j] == 0)
15077 break;
15078 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15079 if (cidrings[i] * 2 - 1 == j)
15080 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15081 else
15082 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15083 if (j != 0)
15084 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15085 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15086 }
15087 ast_cli(a->fd,"%s\n",output);
15088 }
15089 return CLI_SUCCESS;
15090 }
15091
15092
15093 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15094 {
15095 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15096 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15097 int span;
15098 int res;
15099 char alarmstr[50];
15100
15101 int ctl;
15102 struct dahdi_spaninfo s;
15103
15104 switch (cmd) {
15105 case CLI_INIT:
15106 e->command = "dahdi show status";
15107 e->usage =
15108 "Usage: dahdi show status\n"
15109 " Shows a list of DAHDI cards with status\n";
15110 return NULL;
15111 case CLI_GENERATE:
15112 return NULL;
15113 }
15114 ctl = open("/dev/dahdi/ctl", O_RDWR);
15115 if (ctl < 0) {
15116 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15117 return CLI_FAILURE;
15118 }
15119 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15120
15121 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15122 s.spanno = span;
15123 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15124 if (res) {
15125 continue;
15126 }
15127 alarmstr[0] = '\0';
15128 if (s.alarms > 0) {
15129 if (s.alarms & DAHDI_ALARM_BLUE)
15130 strcat(alarmstr, "BLU/");
15131 if (s.alarms & DAHDI_ALARM_YELLOW)
15132 strcat(alarmstr, "YEL/");
15133 if (s.alarms & DAHDI_ALARM_RED)
15134 strcat(alarmstr, "RED/");
15135 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15136 strcat(alarmstr, "LB/");
15137 if (s.alarms & DAHDI_ALARM_RECOVER)
15138 strcat(alarmstr, "REC/");
15139 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15140 strcat(alarmstr, "NOP/");
15141 if (!strlen(alarmstr))
15142 strcat(alarmstr, "UUU/");
15143 if (strlen(alarmstr)) {
15144
15145 alarmstr[strlen(alarmstr) - 1] = '\0';
15146 }
15147 } else {
15148 if (s.numchans)
15149 strcpy(alarmstr, "OK");
15150 else
15151 strcpy(alarmstr, "UNCONFIGURED");
15152 }
15153
15154 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15155 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15156 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15157 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15158 "CAS",
15159 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15160 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15161 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15162 "Unk",
15163 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15164 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15165 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15166 lbostr[s.lbo]
15167 );
15168 }
15169 close(ctl);
15170
15171 return CLI_SUCCESS;
15172 #undef FORMAT
15173 #undef FORMAT2
15174 }
15175
15176 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15177 {
15178 int pseudo_fd = -1;
15179 struct dahdi_versioninfo vi;
15180
15181 switch (cmd) {
15182 case CLI_INIT:
15183 e->command = "dahdi show version";
15184 e->usage =
15185 "Usage: dahdi show version\n"
15186 " Shows the DAHDI version in use\n";
15187 return NULL;
15188 case CLI_GENERATE:
15189 return NULL;
15190 }
15191 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15192 ast_cli(a->fd, "Failed to open control file to get version.\n");
15193 return CLI_SUCCESS;
15194 }
15195
15196 strcpy(vi.version, "Unknown");
15197 strcpy(vi.echo_canceller, "Unknown");
15198
15199 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15200 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15201 else
15202 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15203
15204 close(pseudo_fd);
15205
15206 return CLI_SUCCESS;
15207 }
15208
15209 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15210 {
15211 int channel;
15212 int gain;
15213 int tx;
15214 struct dahdi_hwgain hwgain;
15215 struct dahdi_pvt *tmp = NULL;
15216
15217 switch (cmd) {
15218 case CLI_INIT:
15219 e->command = "dahdi set hwgain";
15220 e->usage =
15221 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15222 " Sets the hardware gain on a a given channel, overriding the\n"
15223 " value provided at module loadtime, whether the channel is in\n"
15224 " use or not. Changes take effect immediately.\n"
15225 " <rx|tx> which direction do you want to change (relative to our module)\n"
15226 " <chan num> is the channel number relative to the device\n"
15227 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15228 return NULL;
15229 case CLI_GENERATE:
15230 return NULL;
15231 }
15232
15233 if (a->argc != 6)
15234 return CLI_SHOWUSAGE;
15235
15236 if (!strcasecmp("rx", a->argv[3]))
15237 tx = 0;
15238 else if (!strcasecmp("tx", a->argv[3]))
15239 tx = 1;
15240 else
15241 return CLI_SHOWUSAGE;
15242
15243 channel = atoi(a->argv[4]);
15244 gain = atof(a->argv[5])*10.0;
15245
15246 ast_mutex_lock(&iflock);
15247
15248 for (tmp = iflist; tmp; tmp = tmp->next) {
15249
15250 if (tmp->channel != channel)
15251 continue;
15252
15253 if (tmp->subs[SUB_REAL].dfd == -1)
15254 break;
15255
15256 hwgain.newgain = gain;
15257 hwgain.tx = tx;
15258 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15259 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15260 ast_mutex_unlock(&iflock);
15261 return CLI_FAILURE;
15262 }
15263 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15264 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15265 break;
15266 }
15267
15268 ast_mutex_unlock(&iflock);
15269
15270 if (tmp)
15271 return CLI_SUCCESS;
15272
15273 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15274 return CLI_FAILURE;
15275
15276 }
15277
15278 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15279 {
15280 int channel;
15281 float gain;
15282 int tx;
15283 int res;
15284 struct dahdi_pvt *tmp = NULL;
15285
15286 switch (cmd) {
15287 case CLI_INIT:
15288 e->command = "dahdi set swgain";
15289 e->usage =
15290 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15291 " Sets the software gain on a a given channel, overriding the\n"
15292 " value provided at module loadtime, whether the channel is in\n"
15293 " use or not. Changes take effect immediately.\n"
15294 " <rx|tx> which direction do you want to change (relative to our module)\n"
15295 " <chan num> is the channel number relative to the device\n"
15296 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15297 return NULL;
15298 case CLI_GENERATE:
15299 return NULL;
15300 }
15301
15302 if (a->argc != 6)
15303 return CLI_SHOWUSAGE;
15304
15305 if (!strcasecmp("rx", a->argv[3]))
15306 tx = 0;
15307 else if (!strcasecmp("tx", a->argv[3]))
15308 tx = 1;
15309 else
15310 return CLI_SHOWUSAGE;
15311
15312 channel = atoi(a->argv[4]);
15313 gain = atof(a->argv[5]);
15314
15315 ast_mutex_lock(&iflock);
15316 for (tmp = iflist; tmp; tmp = tmp->next) {
15317
15318 if (tmp->channel != channel)
15319 continue;
15320
15321 if (tmp->subs[SUB_REAL].dfd == -1)
15322 break;
15323
15324 if (tx)
15325 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15326 else
15327 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15328
15329 if (res) {
15330 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15331 ast_mutex_unlock(&iflock);
15332 return CLI_FAILURE;
15333 }
15334
15335 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15336 tx ? "tx" : "rx", gain, channel);
15337 break;
15338 }
15339 ast_mutex_unlock(&iflock);
15340
15341 if (tmp)
15342 return CLI_SUCCESS;
15343
15344 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15345 return CLI_FAILURE;
15346
15347 }
15348
15349 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15350 {
15351 int channel;
15352 int on;
15353 struct dahdi_pvt *dahdi_chan = NULL;
15354
15355 switch (cmd) {
15356 case CLI_INIT:
15357 e->command = "dahdi set dnd";
15358 e->usage =
15359 "Usage: dahdi set dnd <chan#> <on|off>\n"
15360 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15361 " Changes take effect immediately.\n"
15362 " <chan num> is the channel number\n"
15363 " <on|off> Enable or disable DND mode?\n"
15364 ;
15365 return NULL;
15366 case CLI_GENERATE:
15367 return NULL;
15368 }
15369
15370 if (a->argc != 5)
15371 return CLI_SHOWUSAGE;
15372
15373 if ((channel = atoi(a->argv[3])) <= 0) {
15374 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15375 return CLI_SHOWUSAGE;
15376 }
15377
15378 if (ast_true(a->argv[4]))
15379 on = 1;
15380 else if (ast_false(a->argv[4]))
15381 on = 0;
15382 else {
15383 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15384 return CLI_SHOWUSAGE;
15385 }
15386
15387 ast_mutex_lock(&iflock);
15388 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15389 if (dahdi_chan->channel != channel)
15390 continue;
15391
15392
15393 dahdi_dnd(dahdi_chan, on);
15394 break;
15395 }
15396 ast_mutex_unlock(&iflock);
15397
15398 if (!dahdi_chan) {
15399 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15400 return CLI_FAILURE;
15401 }
15402
15403 return CLI_SUCCESS;
15404 }
15405
15406 static struct ast_cli_entry dahdi_cli[] = {
15407 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15408 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15409 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15410 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15411 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15412 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15413 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15414 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15415 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15416 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15417 };
15418
15419 #define TRANSFER 0
15420 #define HANGUP 1
15421
15422 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15423 {
15424 if (p) {
15425 switch (mode) {
15426 case TRANSFER:
15427 p->fake_event = DAHDI_EVENT_WINKFLASH;
15428 break;
15429 case HANGUP:
15430 p->fake_event = DAHDI_EVENT_ONHOOK;
15431 break;
15432 default:
15433 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15434 }
15435 }
15436 return 0;
15437 }
15438 static struct dahdi_pvt *find_channel(int channel)
15439 {
15440 struct dahdi_pvt *p;
15441
15442 ast_mutex_lock(&iflock);
15443 for (p = iflist; p; p = p->next) {
15444 if (p->channel == channel) {
15445 break;
15446 }
15447 }
15448 ast_mutex_unlock(&iflock);
15449 return p;
15450 }
15451
15452 static int action_dahdidndon(struct mansession *s, const struct message *m)
15453 {
15454 struct dahdi_pvt *p = NULL;
15455 const char *channel = astman_get_header(m, "DAHDIChannel");
15456
15457 if (ast_strlen_zero(channel)) {
15458 astman_send_error(s, m, "No channel specified");
15459 return 0;
15460 }
15461 p = find_channel(atoi(channel));
15462 if (!p) {
15463 astman_send_error(s, m, "No such channel");
15464 return 0;
15465 }
15466 dahdi_dnd(p, 1);
15467 astman_send_ack(s, m, "DND Enabled");
15468 return 0;
15469 }
15470
15471 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15472 {
15473 struct dahdi_pvt *p = NULL;
15474 const char *channel = astman_get_header(m, "DAHDIChannel");
15475
15476 if (ast_strlen_zero(channel)) {
15477 astman_send_error(s, m, "No channel specified");
15478 return 0;
15479 }
15480 p = find_channel(atoi(channel));
15481 if (!p) {
15482 astman_send_error(s, m, "No such channel");
15483 return 0;
15484 }
15485 dahdi_dnd(p, 0);
15486 astman_send_ack(s, m, "DND Disabled");
15487 return 0;
15488 }
15489
15490 static int action_transfer(struct mansession *s, const struct message *m)
15491 {
15492 struct dahdi_pvt *p = NULL;
15493 const char *channel = astman_get_header(m, "DAHDIChannel");
15494
15495 if (ast_strlen_zero(channel)) {
15496 astman_send_error(s, m, "No channel specified");
15497 return 0;
15498 }
15499 p = find_channel(atoi(channel));
15500 if (!p) {
15501 astman_send_error(s, m, "No such channel");
15502 return 0;
15503 }
15504 dahdi_fake_event(p,TRANSFER);
15505 astman_send_ack(s, m, "DAHDITransfer");
15506 return 0;
15507 }
15508
15509 static int action_transferhangup(struct mansession *s, const struct message *m)
15510 {
15511 struct dahdi_pvt *p = NULL;
15512 const char *channel = astman_get_header(m, "DAHDIChannel");
15513
15514 if (ast_strlen_zero(channel)) {
15515 astman_send_error(s, m, "No channel specified");
15516 return 0;
15517 }
15518 p = find_channel(atoi(channel));
15519 if (!p) {
15520 astman_send_error(s, m, "No such channel");
15521 return 0;
15522 }
15523 dahdi_fake_event(p,HANGUP);
15524 astman_send_ack(s, m, "DAHDIHangup");
15525 return 0;
15526 }
15527
15528 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15529 {
15530 struct dahdi_pvt *p = NULL;
15531 const char *channel = astman_get_header(m, "DAHDIChannel");
15532 const char *number = astman_get_header(m, "Number");
15533 int i;
15534
15535 if (ast_strlen_zero(channel)) {
15536 astman_send_error(s, m, "No channel specified");
15537 return 0;
15538 }
15539 if (ast_strlen_zero(number)) {
15540 astman_send_error(s, m, "No number specified");
15541 return 0;
15542 }
15543 p = find_channel(atoi(channel));
15544 if (!p) {
15545 astman_send_error(s, m, "No such channel");
15546 return 0;
15547 }
15548 if (!p->owner) {
15549 astman_send_error(s, m, "Channel does not have it's owner");
15550 return 0;
15551 }
15552 for (i = 0; i < strlen(number); i++) {
15553 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15554 dahdi_queue_frame(p, &f);
15555 }
15556 astman_send_ack(s, m, "DAHDIDialOffhook");
15557 return 0;
15558 }
15559
15560 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15561 {
15562 struct dahdi_pvt *tmp = NULL;
15563 const char *id = astman_get_header(m, "ActionID");
15564 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15565 char idText[256] = "";
15566 int channels = 0;
15567 int dahdichanquery = -1;
15568 if (!ast_strlen_zero(dahdichannel)) {
15569 dahdichanquery = atoi(dahdichannel);
15570 }
15571
15572 astman_send_ack(s, m, "DAHDI channel status will follow");
15573 if (!ast_strlen_zero(id))
15574 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15575
15576 ast_mutex_lock(&iflock);
15577
15578 for (tmp = iflist; tmp; tmp = tmp->next) {
15579 if (tmp->channel > 0) {
15580 int alm;
15581
15582
15583 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15584 continue;
15585
15586 alm = get_alarms(tmp);
15587 channels++;
15588 if (tmp->owner) {
15589
15590 astman_append(s,
15591 "Event: DAHDIShowChannels\r\n"
15592 "DAHDIChannel: %d\r\n"
15593 "Channel: %s\r\n"
15594 "Uniqueid: %s\r\n"
15595 "AccountCode: %s\r\n"
15596 "Signalling: %s\r\n"
15597 "SignallingCode: %d\r\n"
15598 "Context: %s\r\n"
15599 "DND: %s\r\n"
15600 "Alarm: %s\r\n"
15601 "%s"
15602 "\r\n",
15603 tmp->channel,
15604 tmp->owner->name,
15605 tmp->owner->uniqueid,
15606 tmp->owner->accountcode,
15607 sig2str(tmp->sig),
15608 tmp->sig,
15609 tmp->context,
15610 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15611 alarm2str(alm), idText);
15612 } else {
15613 astman_append(s,
15614 "Event: DAHDIShowChannels\r\n"
15615 "DAHDIChannel: %d\r\n"
15616 "Signalling: %s\r\n"
15617 "SignallingCode: %d\r\n"
15618 "Context: %s\r\n"
15619 "DND: %s\r\n"
15620 "Alarm: %s\r\n"
15621 "%s"
15622 "\r\n",
15623 tmp->channel, sig2str(tmp->sig), tmp->sig,
15624 tmp->context,
15625 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15626 alarm2str(alm), idText);
15627 }
15628 }
15629 }
15630
15631 ast_mutex_unlock(&iflock);
15632
15633 astman_append(s,
15634 "Event: DAHDIShowChannelsComplete\r\n"
15635 "%s"
15636 "Items: %d\r\n"
15637 "\r\n",
15638 idText,
15639 channels);
15640 return 0;
15641 }
15642
15643 #if defined(HAVE_SS7)
15644 static int linkset_addsigchan(int sigchan)
15645 {
15646 struct dahdi_ss7 *link;
15647 int res;
15648 int curfd;
15649 struct dahdi_params params;
15650 struct dahdi_bufferinfo bi;
15651 struct dahdi_spaninfo si;
15652
15653 if (sigchan < 0) {
15654 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15655 return -1;
15656 }
15657 if (cur_ss7type < 0) {
15658 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15659 return -1;
15660 }
15661 if (cur_pointcode < 0) {
15662 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15663 return -1;
15664 }
15665 if (cur_adjpointcode < 0) {
15666 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15667 return -1;
15668 }
15669 if (cur_defaultdpc < 0) {
15670 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15671 return -1;
15672 }
15673 if (cur_networkindicator < 0) {
15674 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15675 return -1;
15676 }
15677 link = ss7_resolve_linkset(cur_linkset);
15678 if (!link) {
15679 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15680 return -1;
15681 }
15682 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15683 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15684 return -1;
15685 }
15686
15687 curfd = link->ss7.numsigchans;
15688
15689
15690 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15691 if (link->ss7.fds[curfd] < 0) {
15692 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15693 strerror(errno));
15694 return -1;
15695 }
15696 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15697 dahdi_close_ss7_fd(link, curfd);
15698 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15699 strerror(errno));
15700 return -1;
15701 }
15702
15703
15704 memset(¶ms, 0, sizeof(params));
15705 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
15706 if (res) {
15707 dahdi_close_ss7_fd(link, curfd);
15708 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15709 strerror(errno));
15710 return -1;
15711 }
15712 if (params.sigtype != DAHDI_SIG_HDLCFCS
15713 && params.sigtype != DAHDI_SIG_HARDHDLC
15714 && params.sigtype != DAHDI_SIG_MTP2) {
15715 dahdi_close_ss7_fd(link, curfd);
15716 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15717 return -1;
15718 }
15719
15720
15721 memset(&bi, 0, sizeof(bi));
15722 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15723 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15724 bi.numbufs = 32;
15725 bi.bufsize = 512;
15726 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15727 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
15728 sigchan, strerror(errno));
15729 dahdi_close_ss7_fd(link, curfd);
15730 return -1;
15731 }
15732
15733
15734 memset(&si, 0, sizeof(si));
15735 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
15736 if (res) {
15737 dahdi_close_ss7_fd(link, curfd);
15738 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
15739 strerror(errno));
15740 }
15741
15742 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
15743 (params.sigtype == DAHDI_SIG_MTP2)
15744 ? SS7_TRANSPORT_DAHDIMTP2
15745 : SS7_TRANSPORT_DAHDIDCHAN,
15746 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
15747 if (res) {
15748 dahdi_close_ss7_fd(link, curfd);
15749 return -1;
15750 }
15751
15752 ++link->ss7.numsigchans;
15753
15754 return 0;
15755 }
15756 #endif
15757
15758 #if defined(HAVE_SS7)
15759 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15760 {
15761 int span;
15762 switch (cmd) {
15763 case CLI_INIT:
15764 e->command = "ss7 set debug {on|off} linkset";
15765 e->usage =
15766 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15767 " Enables debugging on a given SS7 linkset\n";
15768 return NULL;
15769 case CLI_GENERATE:
15770 return NULL;
15771 }
15772 if (a->argc < 6)
15773 return CLI_SHOWUSAGE;
15774 span = atoi(a->argv[5]);
15775 if ((span < 1) || (span > NUM_SPANS)) {
15776 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15777 return CLI_SUCCESS;
15778 }
15779 if (!linksets[span-1].ss7.ss7) {
15780 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15781 } else {
15782 if (!strcasecmp(a->argv[3], "on")) {
15783 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
15784 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15785 } else {
15786 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
15787 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15788 }
15789 }
15790
15791 return CLI_SUCCESS;
15792 }
15793 #endif
15794
15795 #if defined(HAVE_SS7)
15796 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15797 {
15798 int linkset, cic;
15799 int blocked = -1, i;
15800 switch (cmd) {
15801 case CLI_INIT:
15802 e->command = "ss7 block cic";
15803 e->usage =
15804 "Usage: ss7 block cic <linkset> <CIC>\n"
15805 " Sends a remote blocking request for the given CIC on the specified linkset\n";
15806 return NULL;
15807 case CLI_GENERATE:
15808 return NULL;
15809 }
15810 if (a->argc == 5)
15811 linkset = atoi(a->argv[3]);
15812 else
15813 return CLI_SHOWUSAGE;
15814
15815 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15816 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15817 return CLI_SUCCESS;
15818 }
15819
15820 if (!linksets[linkset-1].ss7.ss7) {
15821 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15822 return CLI_SUCCESS;
15823 }
15824
15825 cic = atoi(a->argv[4]);
15826
15827 if (cic < 1) {
15828 ast_cli(a->fd, "Invalid CIC specified!\n");
15829 return CLI_SUCCESS;
15830 }
15831
15832 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15833 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15834 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15835 if (!blocked) {
15836 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15837 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15838 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15839 }
15840 }
15841 }
15842
15843 if (blocked < 0) {
15844 ast_cli(a->fd, "Invalid CIC specified!\n");
15845 return CLI_SUCCESS;
15846 }
15847
15848 if (!blocked)
15849 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15850 else
15851 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15852
15853
15854 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15855
15856 return CLI_SUCCESS;
15857 }
15858 #endif
15859
15860 #if defined(HAVE_SS7)
15861 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15862 {
15863 int linkset;
15864 int i;
15865 switch (cmd) {
15866 case CLI_INIT:
15867 e->command = "ss7 block linkset";
15868 e->usage =
15869 "Usage: ss7 block linkset <linkset number>\n"
15870 " Sends a remote blocking request for all CICs on the given linkset\n";
15871 return NULL;
15872 case CLI_GENERATE:
15873 return NULL;
15874 }
15875 if (a->argc == 4)
15876 linkset = atoi(a->argv[3]);
15877 else
15878 return CLI_SHOWUSAGE;
15879
15880 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15881 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15882 return CLI_SUCCESS;
15883 }
15884
15885 if (!linksets[linkset-1].ss7.ss7) {
15886 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15887 return CLI_SUCCESS;
15888 }
15889
15890 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15891 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15892 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15893 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15894 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15895 }
15896
15897
15898 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15899
15900 return CLI_SUCCESS;
15901 }
15902 #endif
15903
15904 #if defined(HAVE_SS7)
15905 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15906 {
15907 int linkset, cic;
15908 int i, blocked = -1;
15909 switch (cmd) {
15910 case CLI_INIT:
15911 e->command = "ss7 unblock cic";
15912 e->usage =
15913 "Usage: ss7 unblock cic <linkset> <CIC>\n"
15914 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
15915 return NULL;
15916 case CLI_GENERATE:
15917 return NULL;
15918 }
15919
15920 if (a->argc == 5)
15921 linkset = atoi(a->argv[3]);
15922 else
15923 return CLI_SHOWUSAGE;
15924
15925 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15926 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15927 return CLI_SUCCESS;
15928 }
15929
15930 if (!linksets[linkset-1].ss7.ss7) {
15931 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15932 return CLI_SUCCESS;
15933 }
15934
15935 cic = atoi(a->argv[4]);
15936
15937 if (cic < 1) {
15938 ast_cli(a->fd, "Invalid CIC specified!\n");
15939 return CLI_SUCCESS;
15940 }
15941
15942 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15943 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15944 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15945 if (blocked) {
15946 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15947 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15948 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15949 }
15950 }
15951 }
15952
15953 if (blocked > 0)
15954 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15955
15956
15957 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15958
15959 return CLI_SUCCESS;
15960 }
15961 #endif
15962
15963 #if defined(HAVE_SS7)
15964 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15965 {
15966 int linkset;
15967 int i;
15968 switch (cmd) {
15969 case CLI_INIT:
15970 e->command = "ss7 unblock linkset";
15971 e->usage =
15972 "Usage: ss7 unblock linkset <linkset number>\n"
15973 " Sends a remote unblocking request for all CICs on the specified linkset\n";
15974 return NULL;
15975 case CLI_GENERATE:
15976 return NULL;
15977 }
15978
15979 if (a->argc == 4)
15980 linkset = atoi(a->argv[3]);
15981 else
15982 return CLI_SHOWUSAGE;
15983
15984 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15985 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15986 return CLI_SUCCESS;
15987 }
15988
15989 if (!linksets[linkset-1].ss7.ss7) {
15990 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15991 return CLI_SUCCESS;
15992 }
15993
15994 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15995 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15996 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15997 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15998 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15999 }
16000
16001
16002 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
16003
16004 return CLI_SUCCESS;
16005 }
16006 #endif
16007
16008 #if defined(HAVE_SS7)
16009 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16010 {
16011 int linkset;
16012 struct sig_ss7_linkset *ss7;
16013 switch (cmd) {
16014 case CLI_INIT:
16015 e->command = "ss7 show linkset";
16016 e->usage =
16017 "Usage: ss7 show linkset <span>\n"
16018 " Shows the status of an SS7 linkset.\n";
16019 return NULL;
16020 case CLI_GENERATE:
16021 return NULL;
16022 }
16023
16024 if (a->argc < 4)
16025 return CLI_SHOWUSAGE;
16026 linkset = atoi(a->argv[3]);
16027 if ((linkset < 1) || (linkset > NUM_SPANS)) {
16028 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
16029 return CLI_SUCCESS;
16030 }
16031 ss7 = &linksets[linkset - 1].ss7;
16032 if (!ss7->ss7) {
16033 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
16034 return CLI_SUCCESS;
16035 }
16036
16037 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
16038
16039 return CLI_SUCCESS;
16040 }
16041 #endif
16042
16043 #if defined(HAVE_SS7)
16044 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
16045 {
16046 switch (cmd) {
16047 case CLI_INIT:
16048 e->command = "ss7 show version";
16049 e->usage =
16050 "Usage: ss7 show version\n"
16051 " Show the libss7 version\n";
16052 return NULL;
16053 case CLI_GENERATE:
16054 return NULL;
16055 }
16056
16057 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16058
16059 return CLI_SUCCESS;
16060 }
16061 #endif
16062
16063 #if defined(HAVE_SS7)
16064 static struct ast_cli_entry dahdi_ss7_cli[] = {
16065 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16066 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16067 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16068 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16069 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16070 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16071 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16072 };
16073 #endif
16074
16075 #if defined(HAVE_PRI)
16076 #if defined(HAVE_PRI_CCSS)
16077
16078
16079
16080
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091
16092
16093
16094 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16095 {
16096 struct dahdi_pvt *pvt;
16097 struct sig_pri_chan *pvt_chan;
16098 int res;
16099
16100 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16101
16102 pvt = chan->tech_pvt;
16103 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16104 pvt_chan = pvt->sig_pvt;
16105 } else {
16106 pvt_chan = NULL;
16107 }
16108 if (!pvt_chan) {
16109 return -1;
16110 }
16111
16112 ast_module_ref(ast_module_info->self);
16113
16114 res = sig_pri_cc_agent_init(agent, pvt_chan);
16115 if (res) {
16116 ast_module_unref(ast_module_info->self);
16117 }
16118 return res;
16119 }
16120 #endif
16121 #endif
16122
16123 #if defined(HAVE_PRI)
16124 #if defined(HAVE_PRI_CCSS)
16125
16126
16127
16128
16129
16130
16131
16132
16133
16134
16135
16136
16137
16138 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16139 {
16140 sig_pri_cc_agent_destructor(agent);
16141
16142 ast_module_unref(ast_module_info->self);
16143 }
16144 #endif
16145 #endif
16146
16147 #if defined(HAVE_PRI)
16148 #if defined(HAVE_PRI_CCSS)
16149 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16150 .type = dahdi_pri_cc_type,
16151 .init = dahdi_pri_cc_agent_init,
16152 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16153 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16154 .ack = sig_pri_cc_agent_req_ack,
16155 .status_request = sig_pri_cc_agent_status_req,
16156 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16157 .party_b_free = sig_pri_cc_agent_party_b_free,
16158 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16159 .callee_available = sig_pri_cc_agent_callee_available,
16160 .destructor = dahdi_pri_cc_agent_destructor,
16161 };
16162 #endif
16163 #endif
16164
16165 #if defined(HAVE_PRI)
16166 #if defined(HAVE_PRI_CCSS)
16167 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16168 .type = dahdi_pri_cc_type,
16169 .request_cc = sig_pri_cc_monitor_req_cc,
16170 .suspend = sig_pri_cc_monitor_suspend,
16171 .unsuspend = sig_pri_cc_monitor_unsuspend,
16172 .status_response = sig_pri_cc_monitor_status_rsp,
16173 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16174 .destructor = sig_pri_cc_monitor_destructor,
16175 };
16176 #endif
16177 #endif
16178
16179 static int __unload_module(void)
16180 {
16181 struct dahdi_pvt *p;
16182 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16183 int i, j;
16184 #endif
16185
16186 #ifdef HAVE_PRI
16187 for (i = 0; i < NUM_SPANS; i++) {
16188 if (pris[i].pri.master != AST_PTHREADT_NULL)
16189 pthread_cancel(pris[i].pri.master);
16190 }
16191 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16192 ast_unregister_application(dahdi_send_keypad_facility_app);
16193 #ifdef HAVE_PRI_PROG_W_CAUSE
16194 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16195 #endif
16196 #endif
16197 #if defined(HAVE_SS7)
16198 for (i = 0; i < NUM_SPANS; i++) {
16199 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16200 pthread_cancel(linksets[i].ss7.master);
16201 }
16202 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16203 #endif
16204 #if defined(HAVE_OPENR2)
16205 dahdi_r2_destroy_links();
16206 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16207 ast_unregister_application(dahdi_accept_r2_call_app);
16208 #endif
16209
16210 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16211 ast_manager_unregister("DAHDIDialOffhook");
16212 ast_manager_unregister("DAHDIHangup");
16213 ast_manager_unregister("DAHDITransfer");
16214 ast_manager_unregister("DAHDIDNDoff");
16215 ast_manager_unregister("DAHDIDNDon");
16216 ast_manager_unregister("DAHDIShowChannels");
16217 ast_manager_unregister("DAHDIRestart");
16218 ast_data_unregister(NULL);
16219 ast_channel_unregister(&dahdi_tech);
16220
16221
16222 ast_mutex_lock(&iflock);
16223 for (p = iflist; p; p = p->next) {
16224 if (p->owner)
16225 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16226 }
16227 ast_mutex_unlock(&iflock);
16228
16229 ast_mutex_lock(&monlock);
16230 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16231 pthread_cancel(monitor_thread);
16232 pthread_kill(monitor_thread, SIGURG);
16233 pthread_join(monitor_thread, NULL);
16234 }
16235 monitor_thread = AST_PTHREADT_STOP;
16236 ast_mutex_unlock(&monlock);
16237
16238 destroy_all_channels();
16239
16240 #if defined(HAVE_PRI)
16241 for (i = 0; i < NUM_SPANS; i++) {
16242 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16243 pthread_join(pris[i].pri.master, NULL);
16244 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16245 dahdi_close_pri_fd(&(pris[i]), j);
16246 }
16247 sig_pri_stop_pri(&pris[i].pri);
16248 }
16249 #if defined(HAVE_PRI_CCSS)
16250 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16251 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16252 #endif
16253 sig_pri_unload();
16254 #endif
16255
16256 #if defined(HAVE_SS7)
16257 for (i = 0; i < NUM_SPANS; i++) {
16258 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16259 pthread_join(linksets[i].ss7.master, NULL);
16260 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16261 dahdi_close_ss7_fd(&(linksets[i]), j);
16262 }
16263 }
16264 #endif
16265 ast_cond_destroy(&ss_thread_complete);
16266 return 0;
16267 }
16268
16269 static int unload_module(void)
16270 {
16271 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16272 int y;
16273 #endif
16274 #ifdef HAVE_PRI
16275 for (y = 0; y < NUM_SPANS; y++)
16276 ast_mutex_destroy(&pris[y].pri.lock);
16277 #endif
16278 #if defined(HAVE_SS7)
16279 for (y = 0; y < NUM_SPANS; y++)
16280 ast_mutex_destroy(&linksets[y].ss7.lock);
16281 #endif
16282 return __unload_module();
16283 }
16284
16285 static void string_replace(char *str, int char1, int char2)
16286 {
16287 for (; *str; str++) {
16288 if (*str == char1) {
16289 *str = char2;
16290 }
16291 }
16292 }
16293
16294 static char *parse_spanchan(char *chanstr, char **subdir)
16295 {
16296 char *p;
16297
16298 if ((p = strrchr(chanstr, '!')) == NULL) {
16299 *subdir = NULL;
16300 return chanstr;
16301 }
16302 *p++ = '\0';
16303 string_replace(chanstr, '!', '/');
16304 *subdir = chanstr;
16305 return p;
16306 }
16307
16308 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16309 {
16310 char *c, *chan;
16311 char *subdir;
16312 int x, start, finish;
16313 struct dahdi_pvt *tmp;
16314
16315 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16316 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16317 return -1;
16318 }
16319
16320 c = ast_strdupa(value);
16321 c = parse_spanchan(c, &subdir);
16322
16323 while ((chan = strsep(&c, ","))) {
16324 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16325
16326 } else if (sscanf(chan, "%30d", &start)) {
16327
16328 finish = start;
16329 } else if (!strcasecmp(chan, "pseudo")) {
16330 finish = start = CHAN_PSEUDO;
16331 if (found_pseudo)
16332 *found_pseudo = 1;
16333 } else {
16334 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16335 return -1;
16336 }
16337 if (finish < start) {
16338 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16339 x = finish;
16340 finish = start;
16341 start = x;
16342 }
16343
16344 for (x = start; x <= finish; x++) {
16345 char fn[PATH_MAX];
16346 int real_channel = x;
16347
16348 if (!ast_strlen_zero(subdir)) {
16349 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16350 if (real_channel < 0) {
16351 if (conf->ignore_failed_channels) {
16352 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16353 subdir, x, real_channel);
16354 continue;
16355 } else {
16356 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16357 subdir, x, real_channel);
16358 return -1;
16359 }
16360 }
16361 }
16362 tmp = mkintf(real_channel, conf, reload);
16363
16364 if (tmp) {
16365 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16366 } else {
16367 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16368 (reload == 1) ? "reconfigure" : "register", value);
16369 return -1;
16370 }
16371 }
16372 }
16373
16374 return 0;
16375 }
16376
16377
16378
16379 #define MAX_CHANLIST_LEN 80
16380
16381 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16382 {
16383 char *parse = ast_strdupa(data);
16384 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16385 unsigned int param_count;
16386 unsigned int x;
16387
16388 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16389 return;
16390
16391 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16392
16393
16394
16395 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16396
16397 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16398 confp->chan.echocancel.head.tap_length = x;
16399 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16400 confp->chan.echocancel.head.tap_length = 128;
16401
16402
16403
16404 for (x = 1; x < param_count; x++) {
16405 struct {
16406 char *name;
16407 char *value;
16408 } param;
16409
16410 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16411 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16412 continue;
16413 }
16414
16415 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16416 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16417 continue;
16418 }
16419
16420 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16421
16422 if (param.value) {
16423 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16424 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16425 continue;
16426 }
16427 }
16428 confp->chan.echocancel.head.param_count++;
16429 }
16430 }
16431
16432
16433 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16434
16435 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16436
16437 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16438 {
16439 struct dahdi_pvt *tmp;
16440 int y;
16441 int found_pseudo = 0;
16442 char dahdichan[MAX_CHANLIST_LEN] = {};
16443
16444 for (; v; v = v->next) {
16445 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16446 continue;
16447
16448
16449 if (!strcasecmp(v->name, "parkinglot")) {
16450 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16451 }
16452
16453
16454 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16455 if (options & PROC_DAHDI_OPT_NOCHAN) {
16456 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16457 continue;
16458 }
16459 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16460 if (confp->ignore_failed_channels) {
16461 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16462 continue;
16463 } else {
16464 return -1;
16465 }
16466 }
16467 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16468 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16469 confp->ignore_failed_channels = ast_true(v->value);
16470 } else if (!strcasecmp(v->name, "buffers")) {
16471 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16472 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16473 confp->chan.buf_no = numbufs;
16474 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16475 }
16476 } else if (!strcasecmp(v->name, "faxbuffers")) {
16477 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16478 confp->chan.usefaxbuffers = 1;
16479 }
16480 } else if (!strcasecmp(v->name, "dahdichan")) {
16481 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16482 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16483 usedistinctiveringdetection = ast_true(v->value);
16484 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16485 distinctiveringaftercid = ast_true(v->value);
16486 } else if (!strcasecmp(v->name, "dring1context")) {
16487 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16488 } else if (!strcasecmp(v->name, "dring2context")) {
16489 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16490 } else if (!strcasecmp(v->name, "dring3context")) {
16491 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16492 } else if (!strcasecmp(v->name, "dring1range")) {
16493 confp->chan.drings.ringnum[0].range = atoi(v->value);
16494 } else if (!strcasecmp(v->name, "dring2range")) {
16495 confp->chan.drings.ringnum[1].range = atoi(v->value);
16496 } else if (!strcasecmp(v->name, "dring3range")) {
16497 confp->chan.drings.ringnum[2].range = atoi(v->value);
16498 } else if (!strcasecmp(v->name, "dring1")) {
16499 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]);
16500 } else if (!strcasecmp(v->name, "dring2")) {
16501 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]);
16502 } else if (!strcasecmp(v->name, "dring3")) {
16503 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]);
16504 } else if (!strcasecmp(v->name, "usecallerid")) {
16505 confp->chan.use_callerid = ast_true(v->value);
16506 } else if (!strcasecmp(v->name, "cidsignalling")) {
16507 if (!strcasecmp(v->value, "bell"))
16508 confp->chan.cid_signalling = CID_SIG_BELL;
16509 else if (!strcasecmp(v->value, "v23"))
16510 confp->chan.cid_signalling = CID_SIG_V23;
16511 else if (!strcasecmp(v->value, "dtmf"))
16512 confp->chan.cid_signalling = CID_SIG_DTMF;
16513 else if (!strcasecmp(v->value, "smdi"))
16514 confp->chan.cid_signalling = CID_SIG_SMDI;
16515 else if (!strcasecmp(v->value, "v23_jp"))
16516 confp->chan.cid_signalling = CID_SIG_V23_JP;
16517 else if (ast_true(v->value))
16518 confp->chan.cid_signalling = CID_SIG_BELL;
16519 } else if (!strcasecmp(v->name, "cidstart")) {
16520 if (!strcasecmp(v->value, "ring"))
16521 confp->chan.cid_start = CID_START_RING;
16522 else if (!strcasecmp(v->value, "polarity_in"))
16523 confp->chan.cid_start = CID_START_POLARITY_IN;
16524 else if (!strcasecmp(v->value, "polarity"))
16525 confp->chan.cid_start = CID_START_POLARITY;
16526 else if (!strcasecmp(v->value, "dtmf"))
16527 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16528 else if (ast_true(v->value))
16529 confp->chan.cid_start = CID_START_RING;
16530 } else if (!strcasecmp(v->name, "threewaycalling")) {
16531 confp->chan.threewaycalling = ast_true(v->value);
16532 } else if (!strcasecmp(v->name, "cancallforward")) {
16533 confp->chan.cancallforward = ast_true(v->value);
16534 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16535 if (ast_true(v->value))
16536 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16537 else
16538 confp->chan.dtmfrelax = 0;
16539 } else if (!strcasecmp(v->name, "mailbox")) {
16540 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16541 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16542 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16543 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16544 }
16545 } else if (!strcasecmp(v->name, "adsi")) {
16546 confp->chan.adsi = ast_true(v->value);
16547 } else if (!strcasecmp(v->name, "usesmdi")) {
16548 confp->chan.use_smdi = ast_true(v->value);
16549 } else if (!strcasecmp(v->name, "smdiport")) {
16550 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16551 } else if (!strcasecmp(v->name, "transfer")) {
16552 confp->chan.transfer = ast_true(v->value);
16553 } else if (!strcasecmp(v->name, "canpark")) {
16554 confp->chan.canpark = ast_true(v->value);
16555 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16556 confp->chan.echocanbridged = ast_true(v->value);
16557 } else if (!strcasecmp(v->name, "busydetect")) {
16558 confp->chan.busydetect = ast_true(v->value);
16559 } else if (!strcasecmp(v->name, "busycount")) {
16560 confp->chan.busycount = atoi(v->value);
16561 } else if (!strcasecmp(v->name, "silencethreshold")) {
16562 confp->chan.silencethreshold = atoi(v->value);
16563 } else if (!strcasecmp(v->name, "busycompare")) {
16564 confp->chan.busycompare = ast_true(v->value);
16565 } else if (!strcasecmp(v->name, "busypattern")) {
16566 if (sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
16567 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16568 }
16569 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
16570 if (count == 1)
16571 confp->chan.busyquietlength = 0;
16572 else if (count < 1)
16573 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
16574 } else if (!strcasecmp(v->name, "busyfuzziness")) {
16575 confp->chan.busyfuzziness = atoi(v->value);
16576 } else if (!strcasecmp(v->name, "callprogress")) {
16577 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16578 if (ast_true(v->value))
16579 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16580 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16581 confp->chan.waitfordialtone = atoi(v->value);
16582 } else if (!strcasecmp(v->name, "faxdetect")) {
16583 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16584 if (!strcasecmp(v->value, "incoming")) {
16585 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16586 } else if (!strcasecmp(v->value, "outgoing")) {
16587 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16588 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16589 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16590 } else if (!strcasecmp(v->name, "echocancel")) {
16591 process_echocancel(confp, v->value, v->lineno);
16592 } else if (!strcasecmp(v->name, "echotraining")) {
16593 if (sscanf(v->value, "%30d", &y) == 1) {
16594 if ((y < 10) || (y > 4000)) {
16595 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16596 } else {
16597 confp->chan.echotraining = y;
16598 }
16599 } else if (ast_true(v->value)) {
16600 confp->chan.echotraining = 400;
16601 } else
16602 confp->chan.echotraining = 0;
16603 } else if (!strcasecmp(v->name, "hidecallerid")) {
16604 confp->chan.hidecallerid = ast_true(v->value);
16605 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16606 confp->chan.hidecalleridname = ast_true(v->value);
16607 } else if (!strcasecmp(v->name, "pulsedial")) {
16608 confp->chan.pulse = ast_true(v->value);
16609 } else if (!strcasecmp(v->name, "callreturn")) {
16610 confp->chan.callreturn = ast_true(v->value);
16611 } else if (!strcasecmp(v->name, "callwaiting")) {
16612 confp->chan.callwaiting = ast_true(v->value);
16613 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16614 confp->chan.callwaitingcallerid = ast_true(v->value);
16615 } else if (!strcasecmp(v->name, "context")) {
16616 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16617 } else if (!strcasecmp(v->name, "language")) {
16618 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16619 } else if (!strcasecmp(v->name, "progzone")) {
16620 ast_copy_string(progzone, v->value, sizeof(progzone));
16621 } else if (!strcasecmp(v->name, "mohinterpret")
16622 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16623 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16624 } else if (!strcasecmp(v->name, "mohsuggest")) {
16625 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16626 } else if (!strcasecmp(v->name, "parkinglot")) {
16627 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16628 } else if (!strcasecmp(v->name, "stripmsd")) {
16629 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16630 confp->chan.stripmsd = atoi(v->value);
16631 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16632 numbufs = atoi(v->value);
16633 } else if (!strcasecmp(v->name, "group")) {
16634 confp->chan.group = ast_get_group(v->value);
16635 } else if (!strcasecmp(v->name, "callgroup")) {
16636 if (!strcasecmp(v->value, "none"))
16637 confp->chan.callgroup = 0;
16638 else
16639 confp->chan.callgroup = ast_get_group(v->value);
16640 } else if (!strcasecmp(v->name, "pickupgroup")) {
16641 if (!strcasecmp(v->value, "none"))
16642 confp->chan.pickupgroup = 0;
16643 else
16644 confp->chan.pickupgroup = ast_get_group(v->value);
16645 } else if (!strcasecmp(v->name, "setvar")) {
16646 char *varname = ast_strdupa(v->value), *varval = NULL;
16647 struct ast_variable *tmpvar;
16648 if (varname && (varval = strchr(varname, '='))) {
16649 *varval++ = '\0';
16650 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16651 tmpvar->next = confp->chan.vars;
16652 confp->chan.vars = tmpvar;
16653 }
16654 }
16655 } else if (!strcasecmp(v->name, "immediate")) {
16656 confp->chan.immediate = ast_true(v->value);
16657 } else if (!strcasecmp(v->name, "transfertobusy")) {
16658 confp->chan.transfertobusy = ast_true(v->value);
16659 } else if (!strcasecmp(v->name, "mwimonitor")) {
16660 confp->chan.mwimonitor_neon = 0;
16661 confp->chan.mwimonitor_fsk = 0;
16662 confp->chan.mwimonitor_rpas = 0;
16663 if (strcasestr(v->value, "fsk")) {
16664 confp->chan.mwimonitor_fsk = 1;
16665 }
16666 if (strcasestr(v->value, "rpas")) {
16667 confp->chan.mwimonitor_rpas = 1;
16668 }
16669 if (strcasestr(v->value, "neon")) {
16670 confp->chan.mwimonitor_neon = 1;
16671 }
16672
16673 if (ast_true(v->value)) {
16674 confp->chan.mwimonitor_fsk = 1;
16675 }
16676 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16677 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16678 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16679 }
16680 } else if (!strcasecmp(v->name, "rxgain")) {
16681 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16682 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16683 }
16684 } else if (!strcasecmp(v->name, "txgain")) {
16685 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16686 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16687 }
16688 } else if (!strcasecmp(v->name, "txdrc")) {
16689 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16690 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16691 }
16692 } else if (!strcasecmp(v->name, "rxdrc")) {
16693 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16694 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16695 }
16696 } else if (!strcasecmp(v->name, "tonezone")) {
16697 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16698 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16699 }
16700 } else if (!strcasecmp(v->name, "callerid")) {
16701 if (!strcasecmp(v->value, "asreceived")) {
16702 confp->chan.cid_num[0] = '\0';
16703 confp->chan.cid_name[0] = '\0';
16704 } else {
16705 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16706 }
16707 } else if (!strcasecmp(v->name, "fullname")) {
16708 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16709 } else if (!strcasecmp(v->name, "cid_number")) {
16710 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16711 } else if (!strcasecmp(v->name, "cid_tag")) {
16712 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16713 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16714 confp->chan.dahditrcallerid = ast_true(v->value);
16715 } else if (!strcasecmp(v->name, "restrictcid")) {
16716 confp->chan.restrictcid = ast_true(v->value);
16717 } else if (!strcasecmp(v->name, "usecallingpres")) {
16718 confp->chan.use_callingpres = ast_true(v->value);
16719 } else if (!strcasecmp(v->name, "accountcode")) {
16720 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16721 } else if (!strcasecmp(v->name, "amaflags")) {
16722 y = ast_cdr_amaflags2int(v->value);
16723 if (y < 0)
16724 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16725 else
16726 confp->chan.amaflags = y;
16727 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16728 confp->chan.polarityonanswerdelay = atoi(v->value);
16729 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16730 confp->chan.answeronpolarityswitch = ast_true(v->value);
16731 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16732 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16733 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16734 confp->chan.sendcalleridafter = atoi(v->value);
16735 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16736 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16737 } else if (ast_cc_is_config_param(v->name)) {
16738 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
16739 } else if (!strcasecmp(v->name, "mwisendtype")) {
16740 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16741 if (!strcasecmp(v->value, "rpas")) {
16742 mwisend_rpas = 1;
16743 } else {
16744 mwisend_rpas = 0;
16745 }
16746 #else
16747
16748 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16749 if (strcasestr(v->value, "nofsk")) {
16750 confp->chan.mwisend_fsk = 0;
16751 } else {
16752 confp->chan.mwisend_fsk = 1;
16753 }
16754 if (strcasestr(v->value, "rpas")) {
16755 confp->chan.mwisend_rpas = 1;
16756 } else {
16757 confp->chan.mwisend_rpas = 0;
16758 }
16759 if (strcasestr(v->value, "lrev")) {
16760 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16761 }
16762 if (strcasestr(v->value, "hvdc")) {
16763 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16764 }
16765 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
16766 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16767 }
16768 #endif
16769 } else if (reload != 1) {
16770 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16771 int orig_radio = confp->chan.radio;
16772 int orig_outsigmod = confp->chan.outsigmod;
16773 int orig_auto = confp->is_sig_auto;
16774
16775 confp->chan.radio = 0;
16776 confp->chan.outsigmod = -1;
16777 confp->is_sig_auto = 0;
16778 if (!strcasecmp(v->value, "em")) {
16779 confp->chan.sig = SIG_EM;
16780 } else if (!strcasecmp(v->value, "em_e1")) {
16781 confp->chan.sig = SIG_EM_E1;
16782 } else if (!strcasecmp(v->value, "em_w")) {
16783 confp->chan.sig = SIG_EMWINK;
16784 } else if (!strcasecmp(v->value, "fxs_ls")) {
16785 confp->chan.sig = SIG_FXSLS;
16786 } else if (!strcasecmp(v->value, "fxs_gs")) {
16787 confp->chan.sig = SIG_FXSGS;
16788 } else if (!strcasecmp(v->value, "fxs_ks")) {
16789 confp->chan.sig = SIG_FXSKS;
16790 } else if (!strcasecmp(v->value, "fxo_ls")) {
16791 confp->chan.sig = SIG_FXOLS;
16792 } else if (!strcasecmp(v->value, "fxo_gs")) {
16793 confp->chan.sig = SIG_FXOGS;
16794 } else if (!strcasecmp(v->value, "fxo_ks")) {
16795 confp->chan.sig = SIG_FXOKS;
16796 } else if (!strcasecmp(v->value, "fxs_rx")) {
16797 confp->chan.sig = SIG_FXSKS;
16798 confp->chan.radio = 1;
16799 } else if (!strcasecmp(v->value, "fxo_rx")) {
16800 confp->chan.sig = SIG_FXOLS;
16801 confp->chan.radio = 1;
16802 } else if (!strcasecmp(v->value, "fxs_tx")) {
16803 confp->chan.sig = SIG_FXSLS;
16804 confp->chan.radio = 1;
16805 } else if (!strcasecmp(v->value, "fxo_tx")) {
16806 confp->chan.sig = SIG_FXOGS;
16807 confp->chan.radio = 1;
16808 } else if (!strcasecmp(v->value, "em_rx")) {
16809 confp->chan.sig = SIG_EM;
16810 confp->chan.radio = 1;
16811 } else if (!strcasecmp(v->value, "em_tx")) {
16812 confp->chan.sig = SIG_EM;
16813 confp->chan.radio = 1;
16814 } else if (!strcasecmp(v->value, "em_rxtx")) {
16815 confp->chan.sig = SIG_EM;
16816 confp->chan.radio = 2;
16817 } else if (!strcasecmp(v->value, "em_txrx")) {
16818 confp->chan.sig = SIG_EM;
16819 confp->chan.radio = 2;
16820 } else if (!strcasecmp(v->value, "sf")) {
16821 confp->chan.sig = SIG_SF;
16822 } else if (!strcasecmp(v->value, "sf_w")) {
16823 confp->chan.sig = SIG_SFWINK;
16824 } else if (!strcasecmp(v->value, "sf_featd")) {
16825 confp->chan.sig = SIG_FEATD;
16826 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16827 confp->chan.sig = SIG_FEATDMF;
16828 } else if (!strcasecmp(v->value, "sf_featb")) {
16829 confp->chan.sig = SIG_SF_FEATB;
16830 } else if (!strcasecmp(v->value, "sf")) {
16831 confp->chan.sig = SIG_SF;
16832 } else if (!strcasecmp(v->value, "sf_rx")) {
16833 confp->chan.sig = SIG_SF;
16834 confp->chan.radio = 1;
16835 } else if (!strcasecmp(v->value, "sf_tx")) {
16836 confp->chan.sig = SIG_SF;
16837 confp->chan.radio = 1;
16838 } else if (!strcasecmp(v->value, "sf_rxtx")) {
16839 confp->chan.sig = SIG_SF;
16840 confp->chan.radio = 2;
16841 } else if (!strcasecmp(v->value, "sf_txrx")) {
16842 confp->chan.sig = SIG_SF;
16843 confp->chan.radio = 2;
16844 } else if (!strcasecmp(v->value, "featd")) {
16845 confp->chan.sig = SIG_FEATD;
16846 } else if (!strcasecmp(v->value, "featdmf")) {
16847 confp->chan.sig = SIG_FEATDMF;
16848 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16849 confp->chan.sig = SIG_FEATDMF_TA;
16850 } else if (!strcasecmp(v->value, "e911")) {
16851 confp->chan.sig = SIG_E911;
16852 } else if (!strcasecmp(v->value, "fgccama")) {
16853 confp->chan.sig = SIG_FGC_CAMA;
16854 } else if (!strcasecmp(v->value, "fgccamamf")) {
16855 confp->chan.sig = SIG_FGC_CAMAMF;
16856 } else if (!strcasecmp(v->value, "featb")) {
16857 confp->chan.sig = SIG_FEATB;
16858 #ifdef HAVE_PRI
16859 } else if (!strcasecmp(v->value, "pri_net")) {
16860 confp->chan.sig = SIG_PRI;
16861 confp->pri.pri.nodetype = PRI_NETWORK;
16862 } else if (!strcasecmp(v->value, "pri_cpe")) {
16863 confp->chan.sig = SIG_PRI;
16864 confp->pri.pri.nodetype = PRI_CPE;
16865 } else if (!strcasecmp(v->value, "bri_cpe")) {
16866 confp->chan.sig = SIG_BRI;
16867 confp->pri.pri.nodetype = PRI_CPE;
16868 } else if (!strcasecmp(v->value, "bri_net")) {
16869 confp->chan.sig = SIG_BRI;
16870 confp->pri.pri.nodetype = PRI_NETWORK;
16871 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16872 confp->chan.sig = SIG_BRI_PTMP;
16873 confp->pri.pri.nodetype = PRI_CPE;
16874 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16875 #if defined(HAVE_PRI_CALL_HOLD)
16876 confp->chan.sig = SIG_BRI_PTMP;
16877 confp->pri.pri.nodetype = PRI_NETWORK;
16878 #else
16879 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
16880 #endif
16881 #endif
16882 #if defined(HAVE_SS7)
16883 } else if (!strcasecmp(v->value, "ss7")) {
16884 confp->chan.sig = SIG_SS7;
16885 #endif
16886 #ifdef HAVE_OPENR2
16887 } else if (!strcasecmp(v->value, "mfcr2")) {
16888 confp->chan.sig = SIG_MFCR2;
16889 #endif
16890 } else if (!strcasecmp(v->value, "auto")) {
16891 confp->is_sig_auto = 1;
16892 } else {
16893 confp->chan.outsigmod = orig_outsigmod;
16894 confp->chan.radio = orig_radio;
16895 confp->is_sig_auto = orig_auto;
16896 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16897 }
16898 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16899 if (!strcasecmp(v->value, "em")) {
16900 confp->chan.outsigmod = SIG_EM;
16901 } else if (!strcasecmp(v->value, "em_e1")) {
16902 confp->chan.outsigmod = SIG_EM_E1;
16903 } else if (!strcasecmp(v->value, "em_w")) {
16904 confp->chan.outsigmod = SIG_EMWINK;
16905 } else if (!strcasecmp(v->value, "sf")) {
16906 confp->chan.outsigmod = SIG_SF;
16907 } else if (!strcasecmp(v->value, "sf_w")) {
16908 confp->chan.outsigmod = SIG_SFWINK;
16909 } else if (!strcasecmp(v->value, "sf_featd")) {
16910 confp->chan.outsigmod = SIG_FEATD;
16911 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16912 confp->chan.outsigmod = SIG_FEATDMF;
16913 } else if (!strcasecmp(v->value, "sf_featb")) {
16914 confp->chan.outsigmod = SIG_SF_FEATB;
16915 } else if (!strcasecmp(v->value, "sf")) {
16916 confp->chan.outsigmod = SIG_SF;
16917 } else if (!strcasecmp(v->value, "featd")) {
16918 confp->chan.outsigmod = SIG_FEATD;
16919 } else if (!strcasecmp(v->value, "featdmf")) {
16920 confp->chan.outsigmod = SIG_FEATDMF;
16921 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16922 confp->chan.outsigmod = SIG_FEATDMF_TA;
16923 } else if (!strcasecmp(v->value, "e911")) {
16924 confp->chan.outsigmod = SIG_E911;
16925 } else if (!strcasecmp(v->value, "fgccama")) {
16926 confp->chan.outsigmod = SIG_FGC_CAMA;
16927 } else if (!strcasecmp(v->value, "fgccamamf")) {
16928 confp->chan.outsigmod = SIG_FGC_CAMAMF;
16929 } else if (!strcasecmp(v->value, "featb")) {
16930 confp->chan.outsigmod = SIG_FEATB;
16931 } else {
16932 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16933 }
16934 #ifdef HAVE_PRI
16935 } else if (!strcasecmp(v->name, "pridialplan")) {
16936 if (!strcasecmp(v->value, "national")) {
16937 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
16938 } else if (!strcasecmp(v->value, "unknown")) {
16939 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
16940 } else if (!strcasecmp(v->value, "private")) {
16941 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
16942 } else if (!strcasecmp(v->value, "international")) {
16943 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16944 } else if (!strcasecmp(v->value, "local")) {
16945 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
16946 } else if (!strcasecmp(v->value, "dynamic")) {
16947 confp->pri.pri.dialplan = -1;
16948 } else if (!strcasecmp(v->value, "redundant")) {
16949 confp->pri.pri.dialplan = -2;
16950 } else {
16951 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16952 }
16953 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16954 if (!strcasecmp(v->value, "national")) {
16955 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16956 } else if (!strcasecmp(v->value, "unknown")) {
16957 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
16958 } else if (!strcasecmp(v->value, "private")) {
16959 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
16960 } else if (!strcasecmp(v->value, "international")) {
16961 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16962 } else if (!strcasecmp(v->value, "local")) {
16963 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
16964 } else if (!strcasecmp(v->value, "dynamic")) {
16965 confp->pri.pri.localdialplan = -1;
16966 } else if (!strcasecmp(v->value, "redundant")) {
16967 confp->pri.pri.localdialplan = -2;
16968 } else {
16969 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16970 }
16971 } else if (!strcasecmp(v->name, "switchtype")) {
16972 if (!strcasecmp(v->value, "national"))
16973 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
16974 else if (!strcasecmp(v->value, "ni1"))
16975 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
16976 else if (!strcasecmp(v->value, "dms100"))
16977 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
16978 else if (!strcasecmp(v->value, "4ess"))
16979 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
16980 else if (!strcasecmp(v->value, "5ess"))
16981 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
16982 else if (!strcasecmp(v->value, "euroisdn"))
16983 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16984 else if (!strcasecmp(v->value, "qsig"))
16985 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
16986 else {
16987 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16988 return -1;
16989 }
16990 } else if (!strcasecmp(v->name, "msn")) {
16991 ast_copy_string(confp->pri.pri.msn_list, v->value,
16992 sizeof(confp->pri.pri.msn_list));
16993 } else if (!strcasecmp(v->name, "nsf")) {
16994 if (!strcasecmp(v->value, "sdn"))
16995 confp->pri.pri.nsf = PRI_NSF_SDN;
16996 else if (!strcasecmp(v->value, "megacom"))
16997 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
16998 else if (!strcasecmp(v->value, "tollfreemegacom"))
16999 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
17000 else if (!strcasecmp(v->value, "accunet"))
17001 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
17002 else if (!strcasecmp(v->value, "none"))
17003 confp->pri.pri.nsf = PRI_NSF_NONE;
17004 else {
17005 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
17006 confp->pri.pri.nsf = PRI_NSF_NONE;
17007 }
17008 } else if (!strcasecmp(v->name, "priindication")) {
17009 if (!strcasecmp(v->value, "outofband"))
17010 confp->chan.priindication_oob = 1;
17011 else if (!strcasecmp(v->value, "inband"))
17012 confp->chan.priindication_oob = 0;
17013 else
17014 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
17015 v->value, v->lineno);
17016 } else if (!strcasecmp(v->name, "priexclusive")) {
17017 confp->chan.priexclusive = ast_true(v->value);
17018 } else if (!strcasecmp(v->name, "internationalprefix")) {
17019 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
17020 } else if (!strcasecmp(v->name, "nationalprefix")) {
17021 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
17022 } else if (!strcasecmp(v->name, "localprefix")) {
17023 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
17024 } else if (!strcasecmp(v->name, "privateprefix")) {
17025 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
17026 } else if (!strcasecmp(v->name, "unknownprefix")) {
17027 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
17028 } else if (!strcasecmp(v->name, "resetinterval")) {
17029 if (!strcasecmp(v->value, "never"))
17030 confp->pri.pri.resetinterval = -1;
17031 else if (atoi(v->value) >= 60)
17032 confp->pri.pri.resetinterval = atoi(v->value);
17033 else
17034 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
17035 v->value, v->lineno);
17036 } else if (!strcasecmp(v->name, "minunused")) {
17037 confp->pri.pri.minunused = atoi(v->value);
17038 } else if (!strcasecmp(v->name, "minidle")) {
17039 confp->pri.pri.minidle = atoi(v->value);
17040 } else if (!strcasecmp(v->name, "idleext")) {
17041 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
17042 } else if (!strcasecmp(v->name, "idledial")) {
17043 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
17044 } else if (!strcasecmp(v->name, "overlapdial")) {
17045 if (ast_true(v->value)) {
17046 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17047 } else if (!strcasecmp(v->value, "incoming")) {
17048 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
17049 } else if (!strcasecmp(v->value, "outgoing")) {
17050 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
17051 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
17052 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
17053 } else {
17054 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
17055 }
17056 #ifdef HAVE_PRI_PROG_W_CAUSE
17057 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17058 if (!strcasecmp(v->value, "logical")) {
17059 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17060 } else if (!strcasecmp(v->value, "physical")) {
17061 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17062 } else {
17063 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17064 }
17065 #endif
17066 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17067 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17068 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17069 } else if (!strcasecmp(v->name, "service_message_support")) {
17070
17071 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17072 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17073 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17074 confp->pri.pri.enable_service_message_support = 1;
17075 } else {
17076 confp->pri.pri.enable_service_message_support = 0;
17077 }
17078 #endif
17079 #ifdef HAVE_PRI_INBANDDISCONNECT
17080 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17081 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17082 #endif
17083 } else if (!strcasecmp(v->name, "pritimer")) {
17084 #ifdef PRI_GETSET_TIMERS
17085 char tmp[20];
17086 char *timerc;
17087 char *c;
17088 int timer;
17089 int timeridx;
17090
17091 ast_copy_string(tmp, v->value, sizeof(tmp));
17092 c = tmp;
17093 timerc = strsep(&c, ",");
17094 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17095 timeridx = pri_timer2idx(timerc);
17096 timer = atoi(c);
17097 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17098 ast_log(LOG_WARNING,
17099 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17100 v->lineno);
17101 } else if (!timer) {
17102 ast_log(LOG_WARNING,
17103 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17104 c, timerc, v->lineno);
17105 } else {
17106 confp->pri.pri.pritimers[timeridx] = timer;
17107 }
17108 } else {
17109 ast_log(LOG_WARNING,
17110 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17111 v->value, v->lineno);
17112 }
17113 #endif
17114 } else if (!strcasecmp(v->name, "facilityenable")) {
17115 confp->pri.pri.facilityenable = ast_true(v->value);
17116 #if defined(HAVE_PRI_AOC_EVENTS)
17117 } else if (!strcasecmp(v->name, "aoc_enable")) {
17118 confp->pri.pri.aoc_passthrough_flag = 0;
17119 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17120 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17121 }
17122 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17123 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17124 }
17125 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17126 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17127 }
17128 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17129 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17130 #endif
17131 #if defined(HAVE_PRI_CALL_HOLD)
17132 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17133 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17134 #endif
17135 #if defined(HAVE_PRI_CCSS)
17136 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17137 if (!strcasecmp(v->value, "global")) {
17138 confp->pri.pri.cc_ptmp_recall_mode = 0;
17139 } else if (!strcasecmp(v->value, "specific")) {
17140 confp->pri.pri.cc_ptmp_recall_mode = 1;
17141 } else {
17142 confp->pri.pri.cc_ptmp_recall_mode = 1;
17143 }
17144 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17145 if (!strcasecmp(v->value, "release")) {
17146 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17147 } else if (!strcasecmp(v->value, "retain")) {
17148 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17149 } else if (!strcasecmp(v->value, "do_not_care")) {
17150 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17151 } else {
17152 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17153 }
17154 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17155 if (!strcasecmp(v->value, "release")) {
17156 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17157 } else if (!strcasecmp(v->value, "retain")) {
17158 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17159 } else {
17160 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17161 }
17162 #endif
17163 #if defined(HAVE_PRI_CALL_WAITING)
17164 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17165 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17166 if (confp->pri.pri.max_call_waiting_calls < 0) {
17167
17168 confp->pri.pri.max_call_waiting_calls = 0;
17169 }
17170 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17171 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17172 #endif
17173 #if defined(HAVE_PRI_MWI)
17174 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17175 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17176 sizeof(confp->pri.pri.mwi_mailboxes));
17177 #endif
17178 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17179 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17180 #endif
17181 #if defined(HAVE_SS7)
17182 } else if (!strcasecmp(v->name, "ss7type")) {
17183 if (!strcasecmp(v->value, "itu")) {
17184 cur_ss7type = SS7_ITU;
17185 } else if (!strcasecmp(v->value, "ansi")) {
17186 cur_ss7type = SS7_ANSI;
17187 } else
17188 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17189 } else if (!strcasecmp(v->name, "linkset")) {
17190 cur_linkset = atoi(v->value);
17191 } else if (!strcasecmp(v->name, "pointcode")) {
17192 cur_pointcode = parse_pointcode(v->value);
17193 } else if (!strcasecmp(v->name, "adjpointcode")) {
17194 cur_adjpointcode = parse_pointcode(v->value);
17195 } else if (!strcasecmp(v->name, "defaultdpc")) {
17196 cur_defaultdpc = parse_pointcode(v->value);
17197 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17198 cur_cicbeginswith = atoi(v->value);
17199 } else if (!strcasecmp(v->name, "networkindicator")) {
17200 if (!strcasecmp(v->value, "national"))
17201 cur_networkindicator = SS7_NI_NAT;
17202 else if (!strcasecmp(v->value, "national_spare"))
17203 cur_networkindicator = SS7_NI_NAT_SPARE;
17204 else if (!strcasecmp(v->value, "international"))
17205 cur_networkindicator = SS7_NI_INT;
17206 else if (!strcasecmp(v->value, "international_spare"))
17207 cur_networkindicator = SS7_NI_INT_SPARE;
17208 else
17209 cur_networkindicator = -1;
17210 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17211 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17212 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17213 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17214 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17215 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17216 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17217 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17218 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17219 if (!strcasecmp(v->value, "national")) {
17220 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17221 } else if (!strcasecmp(v->value, "international")) {
17222 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17223 } else if (!strcasecmp(v->value, "subscriber")) {
17224 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17225 } else if (!strcasecmp(v->value, "unknown")) {
17226 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17227 } else if (!strcasecmp(v->value, "dynamic")) {
17228 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17229 } else {
17230 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17231 }
17232 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17233 if (!strcasecmp(v->value, "national")) {
17234 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17235 } else if (!strcasecmp(v->value, "international")) {
17236 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17237 } else if (!strcasecmp(v->value, "subscriber")) {
17238 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17239 } else if (!strcasecmp(v->value, "unknown")) {
17240 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17241 } else if (!strcasecmp(v->value, "dynamic")) {
17242 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17243 } else {
17244 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17245 }
17246 } else if (!strcasecmp(v->name, "sigchan")) {
17247 int sigchan, res;
17248 sigchan = atoi(v->value);
17249 res = linkset_addsigchan(sigchan);
17250 if (res < 0)
17251 return -1;
17252
17253 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17254 struct dahdi_ss7 *link;
17255 link = ss7_resolve_linkset(cur_linkset);
17256 if (!link) {
17257 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17258 return -1;
17259 }
17260 if (ast_true(v->value))
17261 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17262 #endif
17263 #ifdef HAVE_OPENR2
17264 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17265 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17266 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);
17267 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17268 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17269 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17270 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17271 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17272 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17273 confp->mfcr2.variant = OR2_VAR_ITU;
17274 }
17275 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17276 confp->mfcr2.mfback_timeout = atoi(v->value);
17277 if (!confp->mfcr2.mfback_timeout) {
17278 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17279 confp->mfcr2.mfback_timeout = -1;
17280 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17281 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17282 }
17283 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17284 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17285 if (confp->mfcr2.metering_pulse_timeout > 500) {
17286 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17287 }
17288 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17289 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17290 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17291 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17292 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17293 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17294 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17295 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17296 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17297 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17298 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17299 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17300 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17301 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17302 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17303 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17304 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17305 #endif
17306 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17307 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17308 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17309 confp->mfcr2.max_ani = atoi(v->value);
17310 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17311 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17312 }
17313 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17314 confp->mfcr2.max_dnis = atoi(v->value);
17315 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17316 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17317 }
17318 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17319 confp->mfcr2.category = openr2_proto_get_category(v->value);
17320 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17321 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17322 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17323 v->value, v->lineno);
17324 }
17325 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17326 openr2_log_level_t tmplevel;
17327 char *clevel;
17328 char *logval = ast_strdupa(v->value);
17329 while (logval) {
17330 clevel = strsep(&logval,",");
17331 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17332 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17333 continue;
17334 }
17335 confp->mfcr2.loglevel |= tmplevel;
17336 }
17337 #endif
17338 } else if (!strcasecmp(v->name, "cadence")) {
17339
17340 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17341 int i;
17342 struct dahdi_ring_cadence new_cadence;
17343 int cid_location = -1;
17344 int firstcadencepos = 0;
17345 char original_args[80];
17346 int cadence_is_ok = 1;
17347
17348 ast_copy_string(original_args, v->value, sizeof(original_args));
17349
17350 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]);
17351
17352
17353 if (element_count % 2 == 1) {
17354 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17355 cadence_is_ok = 0;
17356 }
17357
17358
17359 for (i = 0; i < element_count; i++) {
17360 if (c[i] == 0) {
17361 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17362 cadence_is_ok = 0;
17363 break;
17364 } else if (c[i] < 0) {
17365 if (i % 2 == 1) {
17366
17367 if (cid_location == -1) {
17368 cid_location = i;
17369 c[i] *= -1;
17370 } else {
17371 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17372 cadence_is_ok = 0;
17373 break;
17374 }
17375 } else {
17376 if (firstcadencepos == 0) {
17377 firstcadencepos = i;
17378
17379 } else {
17380 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17381 cadence_is_ok = 0;
17382 break;
17383 }
17384 }
17385 }
17386 }
17387
17388
17389 for (i = 0; i < 16; i++) {
17390 new_cadence.ringcadence[i] = c[i];
17391 }
17392
17393 if (cadence_is_ok) {
17394
17395 if (element_count < 2) {
17396 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17397 } else {
17398 if (cid_location == -1) {
17399
17400 cid_location = 1;
17401 } else {
17402
17403 cid_location = (cid_location + 1) / 2;
17404 }
17405
17406 if (!user_has_defined_cadences++)
17407
17408 num_cadence = 0;
17409 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17410 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17411 else {
17412 cadences[num_cadence] = new_cadence;
17413 cidrings[num_cadence++] = cid_location;
17414 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17415 }
17416 }
17417 }
17418 } else if (!strcasecmp(v->name, "ringtimeout")) {
17419 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17420 } else if (!strcasecmp(v->name, "prewink")) {
17421 confp->timing.prewinktime = atoi(v->value);
17422 } else if (!strcasecmp(v->name, "preflash")) {
17423 confp->timing.preflashtime = atoi(v->value);
17424 } else if (!strcasecmp(v->name, "wink")) {
17425 confp->timing.winktime = atoi(v->value);
17426 } else if (!strcasecmp(v->name, "flash")) {
17427 confp->timing.flashtime = atoi(v->value);
17428 } else if (!strcasecmp(v->name, "start")) {
17429 confp->timing.starttime = atoi(v->value);
17430 } else if (!strcasecmp(v->name, "rxwink")) {
17431 confp->timing.rxwinktime = atoi(v->value);
17432 } else if (!strcasecmp(v->name, "rxflash")) {
17433 confp->timing.rxflashtime = atoi(v->value);
17434 } else if (!strcasecmp(v->name, "debounce")) {
17435 confp->timing.debouncetime = atoi(v->value);
17436 } else if (!strcasecmp(v->name, "toneduration")) {
17437 int toneduration;
17438 int ctlfd;
17439 int res;
17440 struct dahdi_dialparams dps;
17441
17442 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17443 if (ctlfd == -1) {
17444 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17445 return -1;
17446 }
17447
17448 toneduration = atoi(v->value);
17449 if (toneduration > -1) {
17450 memset(&dps, 0, sizeof(dps));
17451
17452 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17453 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17454 if (res < 0) {
17455 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17456 close(ctlfd);
17457 return -1;
17458 }
17459 }
17460 close(ctlfd);
17461 } else if (!strcasecmp(v->name, "defaultcic")) {
17462 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17463 } else if (!strcasecmp(v->name, "defaultozz")) {
17464 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17465 } else if (!strcasecmp(v->name, "mwilevel")) {
17466 mwilevel = atoi(v->value);
17467 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17468 dtmfcid_level = atoi(v->value);
17469 } else if (!strcasecmp(v->name, "reportalarms")) {
17470 if (!strcasecmp(v->value, "all"))
17471 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17472 if (!strcasecmp(v->value, "none"))
17473 report_alarms = 0;
17474 else if (!strcasecmp(v->value, "channels"))
17475 report_alarms = REPORT_CHANNEL_ALARMS;
17476 else if (!strcasecmp(v->value, "spans"))
17477 report_alarms = REPORT_SPAN_ALARMS;
17478 }
17479 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17480 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17481 }
17482 if (dahdichan[0]) {
17483
17484
17485 if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) {
17486 return -1;
17487 }
17488 }
17489
17490
17491 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17492 if (!tmp->destroy && tmp->span != y) {
17493 tmp->manages_span_alarms = 1;
17494 y = tmp->span;
17495 } else {
17496 tmp->manages_span_alarms = 0;
17497 }
17498 }
17499
17500
17501
17502 if (!found_pseudo && reload != 1) {
17503
17504
17505
17506
17507 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17508
17509 if (conf.chan.cc_params) {
17510 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17511 } else {
17512 tmp = NULL;
17513 }
17514 if (tmp) {
17515 ast_verb(3, "Automatically generated pseudo channel\n");
17516 } else {
17517 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17518 }
17519 ast_cc_config_params_destroy(conf.chan.cc_params);
17520 }
17521 return 0;
17522 }
17523
17524
17525
17526
17527
17528
17529
17530
17531
17532
17533
17534 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17535 {
17536 struct ast_cc_config_params *cc_params;
17537
17538 cc_params = dest->chan.cc_params;
17539 *dest = *src;
17540 dest->chan.cc_params = cc_params;
17541 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17542 }
17543
17544
17545
17546
17547
17548
17549
17550
17551
17552
17553
17554
17555 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17556 {
17557 struct ast_config *cfg;
17558 struct ast_config *ucfg;
17559 struct ast_variable *v;
17560 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17561 const char *cat;
17562 int res;
17563
17564 #ifdef HAVE_PRI
17565 char *c;
17566 int spanno;
17567 int i;
17568 int logicalspan;
17569 int trunkgroup;
17570 int dchannels[SIG_PRI_NUM_DCHANS];
17571 #endif
17572
17573 cfg = ast_config_load(config, config_flags);
17574
17575
17576 if (!cfg) {
17577 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17578 return 0;
17579 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17580 ucfg = ast_config_load("users.conf", config_flags);
17581 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17582 return 0;
17583 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17584 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17585 return 0;
17586 }
17587 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17588 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17589 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17590 ast_config_destroy(ucfg);
17591 return 0;
17592 }
17593 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17594 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17595 return 0;
17596 } else {
17597 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17598 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17599 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17600 ast_config_destroy(cfg);
17601 return 0;
17602 }
17603 }
17604
17605
17606 ast_mutex_lock(&iflock);
17607 #ifdef HAVE_PRI
17608 if (reload != 1) {
17609
17610 v = ast_variable_browse(cfg, "trunkgroups");
17611 while (v) {
17612 if (!strcasecmp(v->name, "trunkgroup")) {
17613 trunkgroup = atoi(v->value);
17614 if (trunkgroup > 0) {
17615 if ((c = strchr(v->value, ','))) {
17616 i = 0;
17617 memset(dchannels, 0, sizeof(dchannels));
17618 while (c && (i < SIG_PRI_NUM_DCHANS)) {
17619 dchannels[i] = atoi(c + 1);
17620 if (dchannels[i] < 0) {
17621 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);
17622 } else
17623 i++;
17624 c = strchr(c + 1, ',');
17625 }
17626 if (i) {
17627 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17628 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);
17629 } else
17630 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");
17631 } else
17632 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17633 } else
17634 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17635 } else
17636 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17637 } else if (!strcasecmp(v->name, "spanmap")) {
17638 spanno = atoi(v->value);
17639 if (spanno > 0) {
17640 if ((c = strchr(v->value, ','))) {
17641 trunkgroup = atoi(c + 1);
17642 if (trunkgroup > 0) {
17643 if ((c = strchr(c + 1, ',')))
17644 logicalspan = atoi(c + 1);
17645 else
17646 logicalspan = 0;
17647 if (logicalspan >= 0) {
17648 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17649 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17650 } else
17651 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17652 } else
17653 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);
17654 } else
17655 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17656 } else
17657 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17658 } else
17659 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17660 } else {
17661 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17662 }
17663 v = v->next;
17664 }
17665 }
17666 #endif
17667
17668
17669 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17670
17671 mwimonitornotify[0] = '\0';
17672
17673 v = ast_variable_browse(cfg, "channels");
17674 if ((res = process_dahdi(base_conf, "", v, reload, 0))) {
17675 ast_mutex_unlock(&iflock);
17676 ast_config_destroy(cfg);
17677 if (ucfg) {
17678 ast_config_destroy(ucfg);
17679 }
17680 return res;
17681 }
17682
17683
17684 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17685
17686
17687
17688 if (!strcasecmp(cat, "general") ||
17689 !strcasecmp(cat, "trunkgroups") ||
17690 !strcasecmp(cat, "globals") ||
17691 !strcasecmp(cat, "channels")) {
17692 continue;
17693 }
17694
17695
17696 deep_copy_dahdi_chan_conf(conf, base_conf);
17697
17698 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17699 ast_mutex_unlock(&iflock);
17700 ast_config_destroy(cfg);
17701 if (ucfg) {
17702 ast_config_destroy(ucfg);
17703 }
17704 return res;
17705 }
17706 }
17707
17708 ast_config_destroy(cfg);
17709
17710 if (ucfg) {
17711 const char *chans;
17712
17713 process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17714
17715 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17716 if (!strcasecmp(cat, "general")) {
17717 continue;
17718 }
17719
17720 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17721
17722 if (ast_strlen_zero(chans)) {
17723 continue;
17724 }
17725
17726
17727 deep_copy_dahdi_chan_conf(conf, base_conf);
17728
17729 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17730 ast_config_destroy(ucfg);
17731 ast_mutex_unlock(&iflock);
17732 return res;
17733 }
17734 }
17735 ast_config_destroy(ucfg);
17736 }
17737 ast_mutex_unlock(&iflock);
17738
17739 #ifdef HAVE_PRI
17740 if (reload != 1) {
17741 int x;
17742 for (x = 0; x < NUM_SPANS; x++) {
17743 if (pris[x].pri.pvts[0]) {
17744 prepare_pri(pris + x);
17745 if (sig_pri_start_pri(&pris[x].pri)) {
17746 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17747 return -1;
17748 } else
17749 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17750 }
17751 }
17752 }
17753 #endif
17754 #if defined(HAVE_SS7)
17755 if (reload != 1) {
17756 int x;
17757 for (x = 0; x < NUM_SPANS; x++) {
17758 if (linksets[x].ss7.ss7) {
17759 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
17760 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
17761 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17762 return -1;
17763 } else
17764 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17765 }
17766 }
17767 }
17768 #endif
17769 #ifdef HAVE_OPENR2
17770 if (reload != 1) {
17771 int x;
17772 for (x = 0; x < r2links_count; x++) {
17773 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17774 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17775 return -1;
17776 } else {
17777 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17778 }
17779 }
17780 }
17781 #endif
17782
17783 restart_monitor();
17784 return 0;
17785 }
17786
17787
17788
17789
17790
17791
17792
17793
17794
17795
17796 static int setup_dahdi(int reload)
17797 {
17798 int res;
17799 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17800 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17801
17802 if (base_conf.chan.cc_params && conf.chan.cc_params) {
17803 res = setup_dahdi_int(reload, &base_conf, &conf);
17804 } else {
17805 res = -1;
17806 }
17807 ast_cc_config_params_destroy(base_conf.chan.cc_params);
17808 ast_cc_config_params_destroy(conf.chan.cc_params);
17809
17810 return res;
17811 }
17812
17813
17814
17815
17816
17817
17818
17819
17820 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
17821 struct ast_data *data_root)
17822 {
17823 int ctl, res, span;
17824 struct ast_data *data_span, *data_alarms;
17825 struct dahdi_spaninfo s;
17826
17827 ctl = open("/dev/dahdi/ctl", O_RDWR);
17828 if (ctl < 0) {
17829 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
17830 return -1;
17831 }
17832 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17833 s.spanno = span;
17834 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
17835 if (res) {
17836 continue;
17837 }
17838
17839 data_span = ast_data_add_node(data_root, "span");
17840 if (!data_span) {
17841 continue;
17842 }
17843 ast_data_add_str(data_span, "description", s.desc);
17844
17845
17846 data_alarms = ast_data_add_node(data_span, "alarms");
17847 if (!data_alarms) {
17848 continue;
17849 }
17850
17851 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
17852 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
17853 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
17854 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
17855 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
17856 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
17857
17858 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
17859 ast_data_add_int(data_span, "bpviol", s.bpvcount);
17860 ast_data_add_int(data_span, "crc4", s.crc4count);
17861 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17862 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17863 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17864 "CAS");
17865 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17866 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17867 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17868 "Unknown");
17869 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
17870 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17871 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
17872 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
17873
17874
17875 if (!ast_data_search_match(search, data_span)) {
17876 ast_data_remove_node(data_root, data_span);
17877 }
17878 }
17879 close(ctl);
17880
17881 return 0;
17882 }
17883
17884
17885
17886
17887
17888
17889
17890
17891 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
17892 struct ast_data *data_root)
17893 {
17894 struct dahdi_pvt *tmp;
17895 struct ast_data *data_channel;
17896
17897 ast_mutex_lock(&iflock);
17898 for (tmp = iflist; tmp; tmp = tmp->next) {
17899 data_channel = ast_data_add_node(data_root, "channel");
17900 if (!data_channel) {
17901 continue;
17902 }
17903
17904 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
17905
17906
17907 if (!ast_data_search_match(search, data_channel)) {
17908 ast_data_remove_node(data_root, data_channel);
17909 }
17910 }
17911 ast_mutex_unlock(&iflock);
17912
17913 return 0;
17914 }
17915
17916
17917
17918
17919
17920
17921
17922
17923 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
17924 struct ast_data *data_root)
17925 {
17926 int pseudo_fd = -1;
17927 struct dahdi_versioninfo vi = {
17928 .version = "Unknown",
17929 .echo_canceller = "Unknown"
17930 };
17931
17932 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
17933 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
17934 return -1;
17935 }
17936
17937 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
17938 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
17939 }
17940
17941 close(pseudo_fd);
17942
17943 ast_data_add_str(data_root, "value", vi.version);
17944 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
17945
17946 return 0;
17947 }
17948
17949 static const struct ast_data_handler dahdi_status_data_provider = {
17950 .version = AST_DATA_HANDLER_VERSION,
17951 .get = dahdi_status_data_provider_get
17952 };
17953
17954 static const struct ast_data_handler dahdi_channels_data_provider = {
17955 .version = AST_DATA_HANDLER_VERSION,
17956 .get = dahdi_channels_data_provider_get
17957 };
17958
17959 static const struct ast_data_handler dahdi_version_data_provider = {
17960 .version = AST_DATA_HANDLER_VERSION,
17961 .get = dahdi_version_data_provider_get
17962 };
17963
17964 static const struct ast_data_entry dahdi_data_providers[] = {
17965 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
17966 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
17967 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
17968 };
17969
17970 static int load_module(void)
17971 {
17972 int res;
17973 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17974 int y;
17975 #endif
17976
17977 #ifdef HAVE_PRI
17978 memset(pris, 0, sizeof(pris));
17979 for (y = 0; y < NUM_SPANS; y++) {
17980 sig_pri_init_pri(&pris[y].pri);
17981 }
17982 pri_set_error(dahdi_pri_error);
17983 pri_set_message(dahdi_pri_message);
17984 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17985 #ifdef HAVE_PRI_PROG_W_CAUSE
17986 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17987 #endif
17988 #if defined(HAVE_PRI_CCSS)
17989 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
17990 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
17991 __unload_module();
17992 return AST_MODULE_LOAD_FAILURE;
17993 }
17994 #endif
17995 if (sig_pri_load(
17996 #if defined(HAVE_PRI_CCSS)
17997 dahdi_pri_cc_type
17998 #else
17999 NULL
18000 #endif
18001 )) {
18002 __unload_module();
18003 return AST_MODULE_LOAD_FAILURE;
18004 }
18005 #endif
18006 #if defined(HAVE_SS7)
18007 memset(linksets, 0, sizeof(linksets));
18008 for (y = 0; y < NUM_SPANS; y++) {
18009 sig_ss7_init_linkset(&linksets[y].ss7);
18010 }
18011 ss7_set_error(dahdi_ss7_error);
18012 ss7_set_message(dahdi_ss7_message);
18013 #endif
18014 res = setup_dahdi(0);
18015
18016 if (res)
18017 return AST_MODULE_LOAD_DECLINE;
18018 if (ast_channel_register(&dahdi_tech)) {
18019 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
18020 __unload_module();
18021 return AST_MODULE_LOAD_FAILURE;
18022 }
18023 #ifdef HAVE_PRI
18024 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
18025 #endif
18026 #if defined(HAVE_SS7)
18027 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
18028 #endif
18029 #ifdef HAVE_OPENR2
18030 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
18031 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
18032 #endif
18033
18034 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
18035
18036 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
18037 memset(round_robin, 0, sizeof(round_robin));
18038 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
18039 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
18040 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
18041 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
18042 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
18043 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
18044 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
18045
18046 ast_cond_init(&ss_thread_complete, NULL);
18047
18048 return res;
18049 }
18050
18051 static int dahdi_sendtext(struct ast_channel *c, const char *text)
18052 {
18053 #define END_SILENCE_LEN 400
18054 #define HEADER_MS 50
18055 #define TRAILER_MS 5
18056 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
18057 #define ASCII_BYTES_PER_CHAR 80
18058
18059 unsigned char *buf,*mybuf;
18060 struct dahdi_pvt *p = c->tech_pvt;
18061 struct pollfd fds[1];
18062 int size,res,fd,len,x;
18063 int bytes=0;
18064
18065 float cr = 1.0;
18066 float ci = 0.0;
18067 float scont = 0.0;
18068 int idx;
18069
18070 idx = dahdi_get_index(c, p, 0);
18071 if (idx < 0) {
18072 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18073 return -1;
18074 }
18075 if (!text[0]) return(0);
18076 if ((!p->tdd) && (!p->mate)) return(0);
18077 if (p->mate)
18078 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18079 else
18080 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18081 if (!buf)
18082 return -1;
18083 mybuf = buf;
18084 if (p->mate) {
18085 int codec = AST_LAW(p);
18086 for (x = 0; x < HEADER_MS; x++) {
18087 PUT_CLID_MARKMS;
18088 }
18089
18090 for (x = 0; text[x]; x++) {
18091 PUT_CLID(text[x]);
18092 }
18093 for (x = 0; x < TRAILER_MS; x++) {
18094 PUT_CLID_MARKMS;
18095 }
18096 len = bytes;
18097 buf = mybuf;
18098 } else {
18099 len = tdd_generate(p->tdd, buf, text);
18100 if (len < 1) {
18101 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18102 ast_free(mybuf);
18103 return -1;
18104 }
18105 }
18106 memset(buf + len, 0x7f, END_SILENCE_LEN);
18107 len += END_SILENCE_LEN;
18108 fd = p->subs[idx].dfd;
18109 while (len) {
18110 if (ast_check_hangup(c)) {
18111 ast_free(mybuf);
18112 return -1;
18113 }
18114 size = len;
18115 if (size > READ_SIZE)
18116 size = READ_SIZE;
18117 fds[0].fd = fd;
18118 fds[0].events = POLLOUT | POLLPRI;
18119 fds[0].revents = 0;
18120 res = poll(fds, 1, -1);
18121 if (!res) {
18122 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18123 continue;
18124 }
18125
18126 if (fds[0].revents & POLLPRI) {
18127 ast_free(mybuf);
18128 return -1;
18129 }
18130 if (!(fds[0].revents & POLLOUT)) {
18131 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18132 continue;
18133 }
18134 res = write(fd, buf, size);
18135 if (res != size) {
18136 if (res == -1) {
18137 ast_free(mybuf);
18138 return -1;
18139 }
18140 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18141 break;
18142 }
18143 len -= size;
18144 buf += size;
18145 }
18146 ast_free(mybuf);
18147 return(0);
18148 }
18149
18150
18151 static int reload(void)
18152 {
18153 int res = 0;
18154
18155 res = setup_dahdi(1);
18156 if (res) {
18157 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18158 return -1;
18159 }
18160 return 0;
18161 }
18162
18163
18164
18165
18166
18167 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18168 .load = load_module,
18169 .unload = unload_module,
18170 .reload = reload,
18171 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18172 .nonoptreq = "res_smdi",
18173 );