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 busy_tonelength;
01110
01111
01112
01113
01114 int busy_quietlength;
01115
01116
01117
01118
01119 int callprogress;
01120
01121
01122
01123
01124 int waitfordialtone;
01125 struct timeval waitingfordt;
01126 struct timeval flashtime;
01127
01128 struct ast_dsp *dsp;
01129
01130 struct dahdi_dialoperation dop;
01131 int whichwink;
01132
01133 char finaldial[64];
01134 char accountcode[AST_MAX_ACCOUNT_CODE];
01135 int amaflags;
01136 struct tdd_state *tdd;
01137
01138 char call_forward[AST_MAX_EXTENSION];
01139
01140
01141
01142
01143 char mailbox[AST_MAX_EXTENSION];
01144
01145 struct ast_event_sub *mwi_event_sub;
01146
01147 char dialdest[256];
01148 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01149 struct dahdi_vmwi_info mwisend_setting;
01150 unsigned int mwisend_fsk: 1;
01151 unsigned int mwisend_rpas:1;
01152 #endif
01153 int distinctivering;
01154 int dtmfrelax;
01155
01156 int fake_event;
01157
01158
01159
01160
01161 int polarityonanswerdelay;
01162
01163 struct timeval polaritydelaytv;
01164
01165
01166
01167
01168 int sendcalleridafter;
01169
01170 int polarity;
01171
01172 int dsp_features;
01173 #if defined(HAVE_SS7)
01174
01175 struct sig_ss7_linkset *ss7;
01176 #endif
01177 #ifdef HAVE_OPENR2
01178 struct dahdi_mfcr2 *mfcr2;
01179 openr2_chan_t *r2chan;
01180 openr2_calling_party_category_t mfcr2_recvd_category;
01181 openr2_calling_party_category_t mfcr2_category;
01182 int mfcr2_dnis_index;
01183 int mfcr2_ani_index;
01184 int mfcr2call:1;
01185 int mfcr2_answer_pending:1;
01186 int mfcr2_charge_calls:1;
01187 int mfcr2_allow_collect_calls:1;
01188 int mfcr2_forced_release:1;
01189 int mfcr2_dnis_matched:1;
01190 int mfcr2_call_accepted:1;
01191 int mfcr2_progress:1;
01192 int mfcr2_accept_on_offer:1;
01193 #endif
01194
01195 char begindigit;
01196
01197 int muting;
01198 void *sig_pvt;
01199 struct ast_cc_config_params *cc_params;
01200
01201
01202
01203
01204
01205
01206 char dialstring[AST_CHANNEL_NAME];
01207 };
01208
01209 #define DATA_EXPORT_DAHDI_PVT(MEMBER) \
01210 MEMBER(dahdi_pvt, cid_rxgain, AST_DATA_DOUBLE) \
01211 MEMBER(dahdi_pvt, rxgain, AST_DATA_DOUBLE) \
01212 MEMBER(dahdi_pvt, txgain, AST_DATA_DOUBLE) \
01213 MEMBER(dahdi_pvt, txdrc, AST_DATA_DOUBLE) \
01214 MEMBER(dahdi_pvt, rxdrc, AST_DATA_DOUBLE) \
01215 MEMBER(dahdi_pvt, adsi, AST_DATA_BOOLEAN) \
01216 MEMBER(dahdi_pvt, answeronpolarityswitch, AST_DATA_BOOLEAN) \
01217 MEMBER(dahdi_pvt, busydetect, AST_DATA_BOOLEAN) \
01218 MEMBER(dahdi_pvt, callreturn, AST_DATA_BOOLEAN) \
01219 MEMBER(dahdi_pvt, callwaiting, AST_DATA_BOOLEAN) \
01220 MEMBER(dahdi_pvt, callwaitingcallerid, AST_DATA_BOOLEAN) \
01221 MEMBER(dahdi_pvt, cancallforward, AST_DATA_BOOLEAN) \
01222 MEMBER(dahdi_pvt, canpark, AST_DATA_BOOLEAN) \
01223 MEMBER(dahdi_pvt, confirmanswer, AST_DATA_BOOLEAN) \
01224 MEMBER(dahdi_pvt, destroy, AST_DATA_BOOLEAN) \
01225 MEMBER(dahdi_pvt, didtdd, AST_DATA_BOOLEAN) \
01226 MEMBER(dahdi_pvt, dialednone, AST_DATA_BOOLEAN) \
01227 MEMBER(dahdi_pvt, dialing, AST_DATA_BOOLEAN) \
01228 MEMBER(dahdi_pvt, digital, AST_DATA_BOOLEAN) \
01229 MEMBER(dahdi_pvt, dnd, AST_DATA_BOOLEAN) \
01230 MEMBER(dahdi_pvt, echobreak, AST_DATA_BOOLEAN) \
01231 MEMBER(dahdi_pvt, echocanbridged, AST_DATA_BOOLEAN) \
01232 MEMBER(dahdi_pvt, echocanon, AST_DATA_BOOLEAN) \
01233 MEMBER(dahdi_pvt, faxhandled, AST_DATA_BOOLEAN) \
01234 MEMBER(dahdi_pvt, usefaxbuffers, AST_DATA_BOOLEAN) \
01235 MEMBER(dahdi_pvt, bufferoverrideinuse, AST_DATA_BOOLEAN) \
01236 MEMBER(dahdi_pvt, firstradio, AST_DATA_BOOLEAN) \
01237 MEMBER(dahdi_pvt, hanguponpolarityswitch, AST_DATA_BOOLEAN) \
01238 MEMBER(dahdi_pvt, hardwaredtmf, AST_DATA_BOOLEAN) \
01239 MEMBER(dahdi_pvt, hidecallerid, AST_DATA_BOOLEAN) \
01240 MEMBER(dahdi_pvt, hidecalleridname, AST_DATA_BOOLEAN) \
01241 MEMBER(dahdi_pvt, ignoredtmf, AST_DATA_BOOLEAN) \
01242 MEMBER(dahdi_pvt, immediate, AST_DATA_BOOLEAN) \
01243 MEMBER(dahdi_pvt, inalarm, AST_DATA_BOOLEAN) \
01244 MEMBER(dahdi_pvt, mate, AST_DATA_BOOLEAN) \
01245 MEMBER(dahdi_pvt, outgoing, AST_DATA_BOOLEAN) \
01246 MEMBER(dahdi_pvt, permcallwaiting, AST_DATA_BOOLEAN) \
01247 MEMBER(dahdi_pvt, priindication_oob, AST_DATA_BOOLEAN) \
01248 MEMBER(dahdi_pvt, priexclusive, AST_DATA_BOOLEAN) \
01249 MEMBER(dahdi_pvt, pulse, AST_DATA_BOOLEAN) \
01250 MEMBER(dahdi_pvt, pulsedial, AST_DATA_BOOLEAN) \
01251 MEMBER(dahdi_pvt, restartpending, AST_DATA_BOOLEAN) \
01252 MEMBER(dahdi_pvt, restrictcid, AST_DATA_BOOLEAN) \
01253 MEMBER(dahdi_pvt, threewaycalling, AST_DATA_BOOLEAN) \
01254 MEMBER(dahdi_pvt, transfer, AST_DATA_BOOLEAN) \
01255 MEMBER(dahdi_pvt, use_callerid, AST_DATA_BOOLEAN) \
01256 MEMBER(dahdi_pvt, use_callingpres, AST_DATA_BOOLEAN) \
01257 MEMBER(dahdi_pvt, usedistinctiveringdetection, AST_DATA_BOOLEAN) \
01258 MEMBER(dahdi_pvt, dahditrcallerid, AST_DATA_BOOLEAN) \
01259 MEMBER(dahdi_pvt, transfertobusy, AST_DATA_BOOLEAN) \
01260 MEMBER(dahdi_pvt, mwimonitor_neon, AST_DATA_BOOLEAN) \
01261 MEMBER(dahdi_pvt, mwimonitor_fsk, AST_DATA_BOOLEAN) \
01262 MEMBER(dahdi_pvt, mwimonitor_rpas, AST_DATA_BOOLEAN) \
01263 MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
01264 MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
01265 MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
01266 MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
01267 MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
01268 MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
01269 MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
01270 MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
01271 MEMBER(dahdi_pvt, defcontext, AST_DATA_STRING) \
01272 MEMBER(dahdi_pvt, exten, AST_DATA_STRING) \
01273 MEMBER(dahdi_pvt, language, AST_DATA_STRING) \
01274 MEMBER(dahdi_pvt, mohinterpret, AST_DATA_STRING) \
01275 MEMBER(dahdi_pvt, mohsuggest, AST_DATA_STRING) \
01276 MEMBER(dahdi_pvt, parkinglot, AST_DATA_STRING)
01277
01278 AST_DATA_STRUCTURE(dahdi_pvt, DATA_EXPORT_DAHDI_PVT);
01279
01280 static struct dahdi_pvt *iflist = NULL;
01281 static struct dahdi_pvt *ifend = NULL;
01282
01283 #if defined(HAVE_PRI)
01284 static struct dahdi_parms_pseudo {
01285 int buf_no;
01286 int buf_policy;
01287 int faxbuf_no;
01288 int faxbuf_policy;
01289 } dahdi_pseudo_parms;
01290 #endif
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 struct dahdi_chan_conf {
01303 struct dahdi_pvt chan;
01304 #ifdef HAVE_PRI
01305 struct dahdi_pri pri;
01306 #endif
01307
01308 #if defined(HAVE_SS7)
01309 struct dahdi_ss7 ss7;
01310 #endif
01311
01312 #ifdef HAVE_OPENR2
01313 struct dahdi_mfcr2_conf mfcr2;
01314 #endif
01315 struct dahdi_params timing;
01316 int is_sig_auto;
01317
01318 int ignore_failed_channels;
01319
01320
01321
01322
01323
01324 char smdi_port[SMDI_MAX_FILENAME_LEN];
01325 };
01326
01327
01328 static struct dahdi_chan_conf dahdi_chan_conf_default(void)
01329 {
01330
01331
01332
01333 struct dahdi_chan_conf conf = {
01334 #ifdef HAVE_PRI
01335 .pri.pri = {
01336 .nsf = PRI_NSF_NONE,
01337 .switchtype = PRI_SWITCH_NI2,
01338 .dialplan = PRI_UNKNOWN + 1,
01339 .localdialplan = PRI_NATIONAL_ISDN + 1,
01340 .nodetype = PRI_CPE,
01341 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01342
01343 #if defined(HAVE_PRI_CCSS)
01344 .cc_ptmp_recall_mode = 1,
01345 .cc_qsig_signaling_link_req = 1,
01346 .cc_qsig_signaling_link_rsp = 1,
01347 #endif
01348
01349 .minunused = 2,
01350 .idleext = "",
01351 .idledial = "",
01352 .internationalprefix = "",
01353 .nationalprefix = "",
01354 .localprefix = "",
01355 .privateprefix = "",
01356 .unknownprefix = "",
01357 .resetinterval = -1,
01358 },
01359 #endif
01360 #if defined(HAVE_SS7)
01361 .ss7.ss7 = {
01362 .called_nai = SS7_NAI_NATIONAL,
01363 .calling_nai = SS7_NAI_NATIONAL,
01364 .internationalprefix = "",
01365 .nationalprefix = "",
01366 .subscriberprefix = "",
01367 .unknownprefix = ""
01368 },
01369 #endif
01370 #ifdef HAVE_OPENR2
01371 .mfcr2 = {
01372 .variant = OR2_VAR_ITU,
01373 .mfback_timeout = -1,
01374 .metering_pulse_timeout = -1,
01375 .max_ani = 10,
01376 .max_dnis = 4,
01377 .get_ani_first = -1,
01378 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01379 .skip_category_request = -1,
01380 #endif
01381 .call_files = 0,
01382 .allow_collect_calls = 0,
01383 .charge_calls = 1,
01384 .accept_on_offer = 1,
01385 .forced_release = 0,
01386 .double_answer = 0,
01387 .immediate_accept = -1,
01388 .logdir = "",
01389 .r2proto_file = "",
01390 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01391 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01392 },
01393 #endif
01394 .chan = {
01395 .context = "default",
01396 .cid_num = "",
01397 .cid_name = "",
01398 .cid_tag = "",
01399 .mohinterpret = "default",
01400 .mohsuggest = "",
01401 .parkinglot = "",
01402 .transfertobusy = 1,
01403
01404 .cid_signalling = CID_SIG_BELL,
01405 .cid_start = CID_START_RING,
01406 .dahditrcallerid = 0,
01407 .use_callerid = 1,
01408 .sig = -1,
01409 .outsigmod = -1,
01410
01411 .cid_rxgain = +5.0,
01412
01413 .tonezone = -1,
01414
01415 .echocancel.head.tap_length = 1,
01416
01417 .busycount = 3,
01418
01419 .accountcode = "",
01420
01421 .mailbox = "",
01422
01423 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01424 .mwisend_fsk = 1,
01425 #endif
01426 .polarityonanswerdelay = 600,
01427
01428 .sendcalleridafter = DEFAULT_CIDRINGS,
01429
01430 .buf_policy = DAHDI_POLICY_IMMEDIATE,
01431 .buf_no = numbufs,
01432 .usefaxbuffers = 0,
01433 .cc_params = ast_cc_config_params_init(),
01434 },
01435 .timing = {
01436 .prewinktime = -1,
01437 .preflashtime = -1,
01438 .winktime = -1,
01439 .flashtime = -1,
01440 .starttime = -1,
01441 .rxwinktime = -1,
01442 .rxflashtime = -1,
01443 .debouncetime = -1
01444 },
01445 .is_sig_auto = 1,
01446 .smdi_port = "/dev/ttyS0",
01447 };
01448
01449 return conf;
01450 }
01451
01452
01453 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
01454 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
01455 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
01456 static int dahdi_sendtext(struct ast_channel *c, const char *text);
01457 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
01458 static int dahdi_hangup(struct ast_channel *ast);
01459 static int dahdi_answer(struct ast_channel *ast);
01460 static struct ast_frame *dahdi_read(struct ast_channel *ast);
01461 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
01462 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
01463 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
01464 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
01465 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
01466 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen);
01467 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
01468 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value);
01469 static int dahdi_devicestate(void *data);
01470 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback);
01471
01472 static const struct ast_channel_tech dahdi_tech = {
01473 .type = "DAHDI",
01474 .description = tdesc,
01475 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
01476 .requester = dahdi_request,
01477 .send_digit_begin = dahdi_digit_begin,
01478 .send_digit_end = dahdi_digit_end,
01479 .send_text = dahdi_sendtext,
01480 .call = dahdi_call,
01481 .hangup = dahdi_hangup,
01482 .answer = dahdi_answer,
01483 .read = dahdi_read,
01484 .write = dahdi_write,
01485 .bridge = dahdi_bridge,
01486 .exception = dahdi_exception,
01487 .indicate = dahdi_indicate,
01488 .fixup = dahdi_fixup,
01489 .setoption = dahdi_setoption,
01490 .queryoption = dahdi_queryoption,
01491 .func_channel_read = dahdi_func_read,
01492 .func_channel_write = dahdi_func_write,
01493 .devicestate = dahdi_devicestate,
01494 .cc_callback = dahdi_cc_callback,
01495 };
01496
01497 #define GET_CHANNEL(p) ((p)->channel)
01498
01499 #define SIG_PRI_LIB_HANDLE_CASES \
01500 SIG_PRI: \
01501 case SIG_BRI: \
01502 case SIG_BRI_PTMP
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 static inline int dahdi_sig_pri_lib_handles(int signaling)
01514 {
01515 int handles;
01516
01517 switch (signaling) {
01518 case SIG_PRI_LIB_HANDLE_CASES:
01519 handles = 1;
01520 break;
01521 default:
01522 handles = 0;
01523 break;
01524 }
01525
01526 return handles;
01527 }
01528
01529 static enum analog_sigtype dahdisig_to_analogsig(int sig)
01530 {
01531 switch (sig) {
01532 case SIG_FXOLS:
01533 return ANALOG_SIG_FXOLS;
01534 case SIG_FXOGS:
01535 return ANALOG_SIG_FXOGS;
01536 case SIG_FXOKS:
01537 return ANALOG_SIG_FXOKS;
01538 case SIG_FXSLS:
01539 return ANALOG_SIG_FXSLS;
01540 case SIG_FXSGS:
01541 return ANALOG_SIG_FXSGS;
01542 case SIG_FXSKS:
01543 return ANALOG_SIG_FXSKS;
01544 case SIG_EMWINK:
01545 return ANALOG_SIG_EMWINK;
01546 case SIG_EM:
01547 return ANALOG_SIG_EM;
01548 case SIG_EM_E1:
01549 return ANALOG_SIG_EM_E1;
01550 case SIG_FEATD:
01551 return ANALOG_SIG_FEATD;
01552 case SIG_FEATDMF:
01553 return ANALOG_SIG_FEATDMF;
01554 case SIG_E911:
01555 return SIG_E911;
01556 case SIG_FGC_CAMA:
01557 return ANALOG_SIG_FGC_CAMA;
01558 case SIG_FGC_CAMAMF:
01559 return ANALOG_SIG_FGC_CAMAMF;
01560 case SIG_FEATB:
01561 return ANALOG_SIG_FEATB;
01562 case SIG_SFWINK:
01563 return ANALOG_SIG_SFWINK;
01564 case SIG_SF:
01565 return ANALOG_SIG_SF;
01566 case SIG_SF_FEATD:
01567 return ANALOG_SIG_SF_FEATD;
01568 case SIG_SF_FEATDMF:
01569 return ANALOG_SIG_SF_FEATDMF;
01570 case SIG_FEATDMF_TA:
01571 return ANALOG_SIG_FEATDMF_TA;
01572 case SIG_SF_FEATB:
01573 return ANALOG_SIG_FEATB;
01574 default:
01575 return -1;
01576 }
01577 }
01578
01579
01580 static int analog_tone_to_dahditone(enum analog_tone tone)
01581 {
01582 switch (tone) {
01583 case ANALOG_TONE_RINGTONE:
01584 return DAHDI_TONE_RINGTONE;
01585 case ANALOG_TONE_STUTTER:
01586 return DAHDI_TONE_STUTTER;
01587 case ANALOG_TONE_CONGESTION:
01588 return DAHDI_TONE_CONGESTION;
01589 case ANALOG_TONE_DIALTONE:
01590 return DAHDI_TONE_DIALTONE;
01591 case ANALOG_TONE_DIALRECALL:
01592 return DAHDI_TONE_DIALRECALL;
01593 case ANALOG_TONE_INFO:
01594 return DAHDI_TONE_INFO;
01595 default:
01596 return -1;
01597 }
01598 }
01599
01600 static int analogsub_to_dahdisub(enum analog_sub analogsub)
01601 {
01602 int index;
01603
01604 switch (analogsub) {
01605 case ANALOG_SUB_REAL:
01606 index = SUB_REAL;
01607 break;
01608 case ANALOG_SUB_CALLWAIT:
01609 index = SUB_CALLWAIT;
01610 break;
01611 case ANALOG_SUB_THREEWAY:
01612 index = SUB_THREEWAY;
01613 break;
01614 default:
01615 ast_log(LOG_ERROR, "Unidentified sub!\n");
01616 index = SUB_REAL;
01617 }
01618
01619 return index;
01620 }
01621
01622 static enum analog_event dahdievent_to_analogevent(int event);
01623 static int bump_gains(struct dahdi_pvt *p);
01624 static int dahdi_setlinear(int dfd, int linear);
01625
01626 static int my_start_cid_detect(void *pvt, int cid_signalling)
01627 {
01628 struct dahdi_pvt *p = pvt;
01629 int index = SUB_REAL;
01630 p->cs = callerid_new(cid_signalling);
01631 if (!p->cs) {
01632 ast_log(LOG_ERROR, "Unable to alloc callerid\n");
01633 return -1;
01634 }
01635 bump_gains(p);
01636 dahdi_setlinear(p->subs[index].dfd, 0);
01637
01638 return 0;
01639 }
01640
01641 static int my_stop_cid_detect(void *pvt)
01642 {
01643 struct dahdi_pvt *p = pvt;
01644 int index = SUB_REAL;
01645 if (p->cs)
01646 callerid_free(p->cs);
01647 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
01648 return 0;
01649 }
01650
01651 static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout)
01652 {
01653 struct dahdi_pvt *p = pvt;
01654 struct analog_pvt *analog_p = p->sig_pvt;
01655 struct pollfd poller;
01656 char *name, *num;
01657 int index = SUB_REAL;
01658 int res;
01659 unsigned char buf[256];
01660 int flags;
01661
01662 poller.fd = p->subs[SUB_REAL].dfd;
01663 poller.events = POLLPRI | POLLIN;
01664 poller.revents = 0;
01665
01666 res = poll(&poller, 1, timeout);
01667
01668 if (poller.revents & POLLPRI) {
01669 *ev = dahdievent_to_analogevent(dahdi_get_event(p->subs[SUB_REAL].dfd));
01670 return 1;
01671 }
01672
01673 if (poller.revents & POLLIN) {
01674
01675
01676
01677
01678
01679 res = read(p->subs[index].dfd, buf, sizeof(buf));
01680 if (res < 0) {
01681 if (errno != ELAST) {
01682 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01683 callerid_free(p->cs);
01684 return -1;
01685 }
01686 }
01687
01688 if (analog_p->ringt > 0) {
01689 if (!(--analog_p->ringt)) {
01690
01691 return -1;
01692 }
01693 }
01694
01695 if (p->cid_signalling == CID_SIG_V23_JP) {
01696 res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p));
01697 } else {
01698 res = callerid_feed(p->cs, buf, res, AST_LAW(p));
01699 }
01700 if (res < 0) {
01701
01702
01703
01704
01705 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
01706 return -1;
01707 }
01708
01709 if (res == 1) {
01710 callerid_get(p->cs, &name, &num, &flags);
01711 if (name)
01712 ast_copy_string(namebuf, name, ANALOG_MAX_CID);
01713 if (num)
01714 ast_copy_string(numbuf, num, ANALOG_MAX_CID);
01715
01716 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", num, name, flags);
01717 return 0;
01718 }
01719 }
01720
01721 *ev = ANALOG_EVENT_NONE;
01722 return 2;
01723 }
01724
01725 static const char *event2str(int event);
01726 static int restore_gains(struct dahdi_pvt *p);
01727
01728 static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata)
01729 {
01730 unsigned char buf[256];
01731 int distMatches;
01732 int curRingData[RING_PATTERNS];
01733 int receivedRingT;
01734 int counter1;
01735 int counter;
01736 int i;
01737 int res;
01738 int checkaftercid = 0;
01739
01740 struct dahdi_pvt *p = pvt;
01741 struct analog_pvt *analog_p = p->sig_pvt;
01742
01743 if (ringdata == NULL) {
01744 ringdata = curRingData;
01745 } else {
01746 checkaftercid = 1;
01747 }
01748
01749
01750
01751 if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) {
01752
01753 for (receivedRingT = 0; receivedRingT < RING_PATTERNS; receivedRingT++)
01754 ringdata[receivedRingT] = 0;
01755 receivedRingT = 0;
01756 if (checkaftercid && distinctiveringaftercid)
01757 ast_verb(3, "Detecting post-CID distinctive ring\n");
01758
01759 else if (strcmp(p->context,p->defcontext) != 0) {
01760 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
01761 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
01762 }
01763
01764 for (;;) {
01765 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
01766 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
01767 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
01768 ast_hangup(chan);
01769 return 1;
01770 }
01771 if (i & DAHDI_IOMUX_SIGEVENT) {
01772 res = dahdi_get_event(p->subs[idx].dfd);
01773 if (res == DAHDI_EVENT_NOALARM) {
01774 p->inalarm = 0;
01775 analog_p->inalarm = 0;
01776 }
01777 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
01778 res = 0;
01779
01780
01781 ringdata[receivedRingT] = analog_p->ringt;
01782
01783 if (analog_p->ringt < analog_p->ringt_base/2)
01784 break;
01785
01786
01787 if (++receivedRingT == RING_PATTERNS)
01788 break;
01789 } else if (i & DAHDI_IOMUX_READ) {
01790 res = read(p->subs[idx].dfd, buf, sizeof(buf));
01791 if (res < 0) {
01792 if (errno != ELAST) {
01793 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
01794 ast_hangup(chan);
01795 return 1;
01796 }
01797 break;
01798 }
01799 if (analog_p->ringt > 0) {
01800 if (!(--analog_p->ringt)) {
01801 res = -1;
01802 break;
01803 }
01804 }
01805 }
01806 }
01807 }
01808 if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) {
01809
01810 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]);
01811 for (counter = 0; counter < 3; counter++) {
01812
01813 distMatches = 0;
01814
01815 ast_verb(3, "Checking %d,%d,%d\n",
01816 p->drings.ringnum[counter].ring[0],
01817 p->drings.ringnum[counter].ring[1],
01818 p->drings.ringnum[counter].ring[2]);
01819 for (counter1 = 0; counter1 < 3; counter1++) {
01820 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
01821 if (p->drings.ringnum[counter].ring[counter1] == -1) {
01822 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
01823 ringdata[counter1]);
01824 distMatches++;
01825 } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
01826 ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
01827 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
01828 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
01829 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
01830 distMatches++;
01831 }
01832 }
01833
01834 if (distMatches == 3) {
01835
01836 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
01837 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
01838 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
01839 break;
01840 }
01841 }
01842 }
01843
01844 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
01845 restore_gains(p);
01846
01847 return 0;
01848 }
01849
01850 static int my_stop_callwait(void *pvt)
01851 {
01852 struct dahdi_pvt *p = pvt;
01853 p->callwaitingrepeat = 0;
01854 p->cidcwexpire = 0;
01855 p->cid_suppress_expire = 0;
01856
01857 return 0;
01858 }
01859
01860 static int send_callerid(struct dahdi_pvt *p);
01861 static int save_conference(struct dahdi_pvt *p);
01862 static int restore_conference(struct dahdi_pvt *p);
01863
01864 static int my_callwait(void *pvt)
01865 {
01866 struct dahdi_pvt *p = pvt;
01867 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
01868 if (p->cidspill) {
01869 ast_log(LOG_WARNING, "Spill already exists?!?\n");
01870 ast_free(p->cidspill);
01871 }
01872
01873
01874
01875
01876
01877 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
01878 return -1;
01879 save_conference(p);
01880
01881 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
01882 if (!p->callwaitrings && p->callwaitingcallerid) {
01883 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
01884 p->callwaitcas = 1;
01885 p->cidlen = 2400 + 680 + READ_SIZE * 4;
01886 } else {
01887 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
01888 p->callwaitcas = 0;
01889 p->cidlen = 2400 + READ_SIZE * 4;
01890 }
01891 p->cidpos = 0;
01892 send_callerid(p);
01893
01894 return 0;
01895 }
01896
01897 static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
01898 {
01899 struct dahdi_pvt *p = pvt;
01900
01901 ast_debug(2, "Starting cid spill\n");
01902
01903 if (p->cidspill) {
01904 ast_log(LOG_WARNING, "cidspill already exists??\n");
01905 ast_free(p->cidspill);
01906 }
01907
01908 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
01909 if (cwcid == 0) {
01910 p->cidlen = ast_callerid_generate(p->cidspill,
01911 caller->id.name.str,
01912 caller->id.number.str,
01913 AST_LAW(p));
01914 } else {
01915 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
01916 caller->id.name.str, caller->id.number.str);
01917 p->callwaitcas = 0;
01918 p->cidcwexpire = 0;
01919 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
01920 caller->id.name.str,
01921 caller->id.number.str,
01922 AST_LAW(p));
01923 p->cidlen += READ_SIZE * 4;
01924 }
01925 p->cidpos = 0;
01926 p->cid_suppress_expire = 0;
01927 send_callerid(p);
01928 }
01929 return 0;
01930 }
01931
01932 static int my_dsp_reset_and_flush_digits(void *pvt)
01933 {
01934 struct dahdi_pvt *p = pvt;
01935 if (p->dsp)
01936 ast_dsp_digitreset(p->dsp);
01937
01938 return 0;
01939 }
01940
01941 static int my_dsp_set_digitmode(void *pvt, enum analog_dsp_digitmode mode)
01942 {
01943 struct dahdi_pvt *p = pvt;
01944
01945 if (p->channel == CHAN_PSEUDO)
01946 ast_log(LOG_ERROR, "You have assumed incorrectly sir!\n");
01947
01948 if (mode == ANALOG_DIGITMODE_DTMF) {
01949
01950 if (p->hardwaredtmf) {
01951 if (p->dsp) {
01952 ast_dsp_free(p->dsp);
01953 p->dsp = NULL;
01954 }
01955 return 0;
01956 }
01957
01958 if (!p->dsp) {
01959 p->dsp = ast_dsp_new();
01960 if (!p->dsp) {
01961 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01962 return -1;
01963 }
01964 }
01965
01966 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
01967 } else if (mode == ANALOG_DIGITMODE_MF) {
01968 if (!p->dsp) {
01969 p->dsp = ast_dsp_new();
01970 if (!p->dsp) {
01971 ast_log(LOG_ERROR, "Unable to allocate DSP\n");
01972 return -1;
01973 }
01974 }
01975 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
01976 }
01977 return 0;
01978 }
01979
01980 static int dahdi_wink(struct dahdi_pvt *p, int index);
01981
01982 static int my_wink(void *pvt, enum analog_sub sub)
01983 {
01984 struct dahdi_pvt *p = pvt;
01985 int index = analogsub_to_dahdisub(sub);
01986 if (index != SUB_REAL) {
01987 ast_log(LOG_ERROR, "We used a sub other than SUB_REAL (incorrect assumption sir)\n");
01988 }
01989 return dahdi_wink(p, index);
01990 }
01991
01992 static void wakeup_sub(struct dahdi_pvt *p, int a);
01993
01994 static int reset_conf(struct dahdi_pvt *p);
01995
01996 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted);
01997
01998 static void my_handle_dtmf(void *pvt, struct ast_channel *ast, enum analog_sub analog_index, struct ast_frame **dest)
01999 {
02000 struct ast_frame *f = *dest;
02001 struct dahdi_pvt *p = pvt;
02002 int idx = analogsub_to_dahdisub(analog_index);
02003
02004 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
02005 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
02006 f->subclass.integer, f->subclass.integer, ast->name);
02007
02008 if (f->subclass.integer == 'f') {
02009 if (f->frametype == AST_FRAME_DTMF_END) {
02010
02011 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
02012
02013 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
02014 struct dahdi_bufferinfo bi = {
02015 .txbufpolicy = p->faxbuf_policy,
02016 .bufsize = p->bufsize,
02017 .numbufs = p->faxbuf_no
02018 };
02019 int res;
02020
02021 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
02022 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
02023 } else {
02024 p->bufferoverrideinuse = 1;
02025 }
02026 }
02027 p->faxhandled = 1;
02028 if (p->dsp) {
02029 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
02030 ast_dsp_set_features(p->dsp, p->dsp_features);
02031 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
02032 }
02033 if (strcmp(ast->exten, "fax")) {
02034 const char *target_context = S_OR(ast->macrocontext, ast->context);
02035
02036
02037
02038
02039
02040 ast_mutex_unlock(&p->lock);
02041 ast_channel_unlock(ast);
02042 if (ast_exists_extension(ast, target_context, "fax", 1,
02043 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
02044 ast_channel_lock(ast);
02045 ast_mutex_lock(&p->lock);
02046 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
02047
02048 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
02049 if (ast_async_goto(ast, target_context, "fax", 1))
02050 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
02051 } else {
02052 ast_channel_lock(ast);
02053 ast_mutex_lock(&p->lock);
02054 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
02055 }
02056 } else {
02057 ast_debug(1, "Already in a fax extension, not redirecting\n");
02058 }
02059 } else {
02060 ast_debug(1, "Fax already handled\n");
02061 }
02062 dahdi_confmute(p, 0);
02063 }
02064 p->subs[idx].f.frametype = AST_FRAME_NULL;
02065 p->subs[idx].f.subclass.integer = 0;
02066 *dest = &p->subs[idx].f;
02067 }
02068 }
02069
02070 static void my_lock_private(void *pvt)
02071 {
02072 struct dahdi_pvt *p = pvt;
02073 ast_mutex_lock(&p->lock);
02074 }
02075
02076 static void my_unlock_private(void *pvt)
02077 {
02078 struct dahdi_pvt *p = pvt;
02079 ast_mutex_unlock(&p->lock);
02080 }
02081
02082 static void my_deadlock_avoidance_private(void *pvt)
02083 {
02084 struct dahdi_pvt *p = pvt;
02085
02086 DEADLOCK_AVOIDANCE(&p->lock);
02087 }
02088
02089
02090
02091
02092 static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode)
02093 {
02094 struct dahdi_pvt *p = pvt;
02095 int oldval;
02096 int idx = analogsub_to_dahdisub(sub);
02097
02098 dahdi_setlinear(p->subs[idx].dfd, linear_mode);
02099 oldval = p->subs[idx].linear;
02100 p->subs[idx].linear = linear_mode ? 1 : 0;
02101 return oldval;
02102 }
02103
02104 static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway)
02105 {
02106 struct dahdi_pvt *p = pvt;
02107 int idx = analogsub_to_dahdisub(sub);
02108
02109 p->subs[idx].inthreeway = inthreeway;
02110 }
02111
02112 static int get_alarms(struct dahdi_pvt *p);
02113 static void handle_alarms(struct dahdi_pvt *p, int alms);
02114 static void my_get_and_handle_alarms(void *pvt)
02115 {
02116 int res;
02117 struct dahdi_pvt *p = pvt;
02118
02119 res = get_alarms(p);
02120 handle_alarms(p, res);
02121 }
02122
02123 static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan)
02124 {
02125 struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt;
02126 if (p)
02127 return p->sig_pvt;
02128 else
02129 return NULL;
02130 }
02131
02132 static int my_get_sub_fd(void *pvt, enum analog_sub sub)
02133 {
02134 struct dahdi_pvt *p = pvt;
02135 int dahdi_sub = analogsub_to_dahdisub(sub);
02136 return p->subs[dahdi_sub].dfd;
02137 }
02138
02139 static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast)
02140 {
02141 struct dahdi_pvt *p = pvt;
02142
02143
02144 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02145 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02146 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02147 *cidrings = cidrings[p->distinctivering - 1];
02148 } else {
02149 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02150 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02151 *cidrings = p->sendcalleridafter;
02152 }
02153 }
02154
02155 static void my_set_alarm(void *pvt, int in_alarm)
02156 {
02157 struct dahdi_pvt *p = pvt;
02158
02159 p->inalarm = in_alarm;
02160 }
02161
02162 static void my_set_dialing(void *pvt, int is_dialing)
02163 {
02164 struct dahdi_pvt *p = pvt;
02165
02166 p->dialing = is_dialing;
02167 }
02168
02169 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02170 static void my_set_digital(void *pvt, int is_digital)
02171 {
02172 struct dahdi_pvt *p = pvt;
02173
02174 p->digital = is_digital;
02175 }
02176 #endif
02177
02178 #if defined(HAVE_SS7)
02179 static void my_set_inservice(void *pvt, int is_inservice)
02180 {
02181 struct dahdi_pvt *p = pvt;
02182
02183 p->inservice = is_inservice;
02184 }
02185 #endif
02186
02187 #if defined(HAVE_SS7)
02188 static void my_set_locallyblocked(void *pvt, int is_blocked)
02189 {
02190 struct dahdi_pvt *p = pvt;
02191
02192 p->locallyblocked = is_blocked;
02193 }
02194 #endif
02195
02196 #if defined(HAVE_SS7)
02197 static void my_set_remotelyblocked(void *pvt, int is_blocked)
02198 {
02199 struct dahdi_pvt *p = pvt;
02200
02201 p->remotelyblocked = is_blocked;
02202 }
02203 #endif
02204
02205 static void my_set_ringtimeout(void *pvt, int ringt)
02206 {
02207 struct dahdi_pvt *p = pvt;
02208 p->ringt = ringt;
02209 }
02210
02211 static void my_set_waitingfordt(void *pvt, struct ast_channel *ast)
02212 {
02213 struct dahdi_pvt *p = pvt;
02214
02215 if (p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp) {
02216 ast_log(LOG_DEBUG, "Defer dialing for %dms or dialtone\n", p->waitfordialtone);
02217 gettimeofday(&p->waitingfordt, NULL);
02218 ast_setstate(ast, AST_STATE_OFFHOOK);
02219 }
02220 }
02221
02222 static int my_check_waitingfordt(void *pvt)
02223 {
02224 struct dahdi_pvt *p = pvt;
02225
02226 if (p->waitingfordt.tv_usec) {
02227 return 1;
02228 }
02229
02230 return 0;
02231 }
02232
02233 static void my_set_confirmanswer(void *pvt, int flag)
02234 {
02235 struct dahdi_pvt *p = pvt;
02236 p->confirmanswer = flag;
02237 }
02238
02239 static int my_check_confirmanswer(void *pvt)
02240 {
02241 struct dahdi_pvt *p = pvt;
02242 if (p->confirmanswer) {
02243 return 1;
02244 }
02245
02246 return 0;
02247 }
02248
02249 static void my_set_callwaiting(void *pvt, int callwaiting_enable)
02250 {
02251 struct dahdi_pvt *p = pvt;
02252
02253 p->callwaiting = callwaiting_enable;
02254 }
02255
02256 static void my_cancel_cidspill(void *pvt)
02257 {
02258 struct dahdi_pvt *p = pvt;
02259
02260 ast_free(p->cidspill);
02261 p->cidspill = NULL;
02262 restore_conference(p);
02263 }
02264
02265 static int my_confmute(void *pvt, int mute)
02266 {
02267 struct dahdi_pvt *p = pvt;
02268 return dahdi_confmute(p, mute);
02269 }
02270
02271 static void my_set_pulsedial(void *pvt, int flag)
02272 {
02273 struct dahdi_pvt *p = pvt;
02274 p->pulsedial = flag;
02275 }
02276
02277 static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
02278 {
02279 struct dahdi_pvt *p = pvt;
02280
02281 p->owner = new_owner;
02282 }
02283
02284 static const char *my_get_orig_dialstring(void *pvt)
02285 {
02286 struct dahdi_pvt *p = pvt;
02287
02288 return p->dialstring;
02289 }
02290
02291 static void my_increase_ss_count(void)
02292 {
02293 ast_mutex_lock(&ss_thread_lock);
02294 ss_thread_count++;
02295 ast_mutex_unlock(&ss_thread_lock);
02296 }
02297
02298 static void my_decrease_ss_count(void)
02299 {
02300 ast_mutex_lock(&ss_thread_lock);
02301 ss_thread_count--;
02302 ast_cond_signal(&ss_thread_complete);
02303 ast_mutex_unlock(&ss_thread_lock);
02304 }
02305
02306 static void my_all_subchannels_hungup(void *pvt)
02307 {
02308 struct dahdi_pvt *p = pvt;
02309 int res, law;
02310
02311 p->faxhandled = 0;
02312 p->didtdd = 0;
02313
02314 if (p->dsp) {
02315 ast_dsp_free(p->dsp);
02316 p->dsp = NULL;
02317 }
02318
02319 p->law = p->law_default;
02320 law = p->law_default;
02321 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02322 if (res < 0)
02323 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02324
02325 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02326
02327 #if 1
02328 {
02329 int i;
02330 p->owner = NULL;
02331
02332 for (i = 0; i < 3; i++) {
02333 p->subs[i].owner = NULL;
02334 }
02335 }
02336 #endif
02337
02338 reset_conf(p);
02339 if (num_restart_pending == 0) {
02340 restart_monitor();
02341 }
02342 }
02343
02344 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index);
02345
02346 static int my_conf_del(void *pvt, enum analog_sub sub)
02347 {
02348 struct dahdi_pvt *p = pvt;
02349 int x = analogsub_to_dahdisub(sub);
02350
02351 return conf_del(p, &p->subs[x], x);
02352 }
02353
02354 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel);
02355
02356 static int my_conf_add(void *pvt, enum analog_sub sub)
02357 {
02358 struct dahdi_pvt *p = pvt;
02359 int x = analogsub_to_dahdisub(sub);
02360
02361 return conf_add(p, &p->subs[x], x, 0);
02362 }
02363
02364 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out);
02365
02366 static int my_complete_conference_update(void *pvt, int needconference)
02367 {
02368 struct dahdi_pvt *p = pvt;
02369 int needconf = needconference;
02370 int x;
02371 int useslavenative;
02372 struct dahdi_pvt *slave = NULL;
02373
02374 useslavenative = isslavenative(p, &slave);
02375
02376
02377
02378 for (x = 0; x < MAX_SLAVES; x++) {
02379 if (p->slaves[x]) {
02380 if (useslavenative)
02381 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02382 else {
02383 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02384 needconf++;
02385 }
02386 }
02387 }
02388
02389 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02390 if (useslavenative)
02391 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02392 else {
02393 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02394 needconf++;
02395 }
02396 }
02397
02398 if (p->master) {
02399 if (isslavenative(p->master, NULL)) {
02400 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02401 } else {
02402 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02403 }
02404 }
02405 if (!needconf) {
02406
02407
02408 p->confno = -1;
02409 }
02410
02411 return 0;
02412 }
02413
02414 static int check_for_conference(struct dahdi_pvt *p);
02415
02416 static int my_check_for_conference(void *pvt)
02417 {
02418 struct dahdi_pvt *p = pvt;
02419 return check_for_conference(p);
02420 }
02421
02422 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)
02423 {
02424 struct dahdi_pvt *p = pvt;
02425 int da, db;
02426 int tchan;
02427 int tinthreeway;
02428
02429 da = analogsub_to_dahdisub(a);
02430 db = analogsub_to_dahdisub(b);
02431
02432 tchan = p->subs[da].chan;
02433 p->subs[da].chan = p->subs[db].chan;
02434 p->subs[db].chan = tchan;
02435
02436 tinthreeway = p->subs[da].inthreeway;
02437 p->subs[da].inthreeway = p->subs[db].inthreeway;
02438 p->subs[db].inthreeway = tinthreeway;
02439
02440 p->subs[da].owner = ast_a;
02441 p->subs[db].owner = ast_b;
02442
02443 if (ast_a)
02444 ast_channel_set_fd(ast_a, 0, p->subs[da].dfd);
02445 if (ast_b)
02446 ast_channel_set_fd(ast_b, 0, p->subs[db].dfd);
02447
02448 wakeup_sub(p, a);
02449 wakeup_sub(p, b);
02450
02451 return;
02452 }
02453
02454 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid);
02455
02456 static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
02457 {
02458 struct dahdi_pvt *p = pvt;
02459 int dsub = analogsub_to_dahdisub(sub);
02460
02461 return dahdi_new(p, state, startpbx, dsub, 0, requestor ? requestor->linkedid : "");
02462 }
02463
02464 #if defined(HAVE_PRI) || defined(HAVE_SS7)
02465 static int dahdi_setlaw(int dfd, int law)
02466 {
02467 int res;
02468 res = ioctl(dfd, DAHDI_SETLAW, &law);
02469 if (res)
02470 return res;
02471 return 0;
02472 }
02473 #endif
02474
02475 #if defined(HAVE_PRI)
02476 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)
02477 {
02478 struct dahdi_pvt *p = pvt;
02479 int audio;
02480 int newlaw = -1;
02481
02482 switch (p->sig) {
02483 case SIG_PRI_LIB_HANDLE_CASES:
02484 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
02485
02486 break;
02487 }
02488
02489 default:
02490
02491 audio = 1;
02492 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1) {
02493 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
02494 p->channel, audio, strerror(errno));
02495 }
02496 break;
02497 }
02498
02499 if (law != SIG_PRI_DEFLAW) {
02500 dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
02501 }
02502
02503 ast_copy_string(p->exten, exten, sizeof(p->exten));
02504
02505 switch (law) {
02506 case SIG_PRI_DEFLAW:
02507 newlaw = 0;
02508 break;
02509 case SIG_PRI_ALAW:
02510 newlaw = DAHDI_LAW_ALAW;
02511 break;
02512 case SIG_PRI_ULAW:
02513 newlaw = DAHDI_LAW_MULAW;
02514 break;
02515 }
02516 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
02517 }
02518 #endif
02519
02520 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law);
02521
02522 #if defined(HAVE_PRI)
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532 static void my_pri_open_media(void *p)
02533 {
02534 struct dahdi_pvt *pvt = p;
02535 int res;
02536 int dfd;
02537 int set_val;
02538
02539 dfd = pvt->subs[SUB_REAL].dfd;
02540
02541
02542 set_val = 1;
02543 res = ioctl(dfd, DAHDI_AUDIOMODE, &set_val);
02544 if (res < 0) {
02545 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n",
02546 pvt->channel, strerror(errno));
02547 }
02548
02549
02550 res = dahdi_setlaw(dfd, pvt->law);
02551 if (res < 0) {
02552 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pvt->channel);
02553 }
02554
02555
02556 if (pvt->digital) {
02557 res = set_actual_gain(dfd, 0, 0, pvt->rxdrc, pvt->txdrc, pvt->law);
02558 } else {
02559 res = set_actual_gain(dfd, pvt->rxgain, pvt->txgain, pvt->rxdrc, pvt->txdrc,
02560 pvt->law);
02561 }
02562 if (res < 0) {
02563 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pvt->channel);
02564 }
02565
02566 if (pvt->dsp_features && pvt->dsp) {
02567 ast_dsp_set_features(pvt->dsp, pvt->dsp_features);
02568 pvt->dsp_features = 0;
02569 }
02570 }
02571 #endif
02572
02573 static int unalloc_sub(struct dahdi_pvt *p, int x);
02574
02575 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
02576 {
02577 struct dahdi_pvt *p = pvt;
02578
02579 return unalloc_sub(p, analogsub_to_dahdisub(analogsub));
02580 }
02581
02582 static int alloc_sub(struct dahdi_pvt *p, int x);
02583
02584 static int my_allocate_sub(void *pvt, enum analog_sub analogsub)
02585 {
02586 struct dahdi_pvt *p = pvt;
02587
02588 return alloc_sub(p, analogsub_to_dahdisub(analogsub));
02589 }
02590
02591 static int has_voicemail(struct dahdi_pvt *p);
02592
02593 static int my_has_voicemail(void *pvt)
02594 {
02595 struct dahdi_pvt *p = pvt;
02596
02597 return has_voicemail(p);
02598 }
02599
02600 static int my_play_tone(void *pvt, enum analog_sub sub, enum analog_tone tone)
02601 {
02602 struct dahdi_pvt *p = pvt;
02603 int index;
02604
02605 index = analogsub_to_dahdisub(sub);
02606
02607 return tone_zone_play_tone(p->subs[index].dfd, analog_tone_to_dahditone(tone));
02608 }
02609
02610 static enum analog_event dahdievent_to_analogevent(int event)
02611 {
02612 enum analog_event res;
02613
02614 switch (event) {
02615 case DAHDI_EVENT_ONHOOK:
02616 res = ANALOG_EVENT_ONHOOK;
02617 break;
02618 case DAHDI_EVENT_RINGOFFHOOK:
02619 res = ANALOG_EVENT_RINGOFFHOOK;
02620 break;
02621 case DAHDI_EVENT_WINKFLASH:
02622 res = ANALOG_EVENT_WINKFLASH;
02623 break;
02624 case DAHDI_EVENT_ALARM:
02625 res = ANALOG_EVENT_ALARM;
02626 break;
02627 case DAHDI_EVENT_NOALARM:
02628 res = ANALOG_EVENT_NOALARM;
02629 break;
02630 case DAHDI_EVENT_DIALCOMPLETE:
02631 res = ANALOG_EVENT_DIALCOMPLETE;
02632 break;
02633 case DAHDI_EVENT_RINGERON:
02634 res = ANALOG_EVENT_RINGERON;
02635 break;
02636 case DAHDI_EVENT_RINGEROFF:
02637 res = ANALOG_EVENT_RINGEROFF;
02638 break;
02639 case DAHDI_EVENT_HOOKCOMPLETE:
02640 res = ANALOG_EVENT_HOOKCOMPLETE;
02641 break;
02642 case DAHDI_EVENT_PULSE_START:
02643 res = ANALOG_EVENT_PULSE_START;
02644 break;
02645 case DAHDI_EVENT_POLARITY:
02646 res = ANALOG_EVENT_POLARITY;
02647 break;
02648 case DAHDI_EVENT_RINGBEGIN:
02649 res = ANALOG_EVENT_RINGBEGIN;
02650 break;
02651 case DAHDI_EVENT_EC_DISABLED:
02652 res = ANALOG_EVENT_EC_DISABLED;
02653 break;
02654 case DAHDI_EVENT_REMOVED:
02655 res = ANALOG_EVENT_REMOVED;
02656 break;
02657 case DAHDI_EVENT_NEONMWI_ACTIVE:
02658 res = ANALOG_EVENT_NEONMWI_ACTIVE;
02659 break;
02660 case DAHDI_EVENT_NEONMWI_INACTIVE:
02661 res = ANALOG_EVENT_NEONMWI_INACTIVE;
02662 break;
02663 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
02664 case DAHDI_EVENT_TX_CED_DETECTED:
02665 res = ANALOG_EVENT_TX_CED_DETECTED;
02666 break;
02667 case DAHDI_EVENT_RX_CED_DETECTED:
02668 res = ANALOG_EVENT_RX_CED_DETECTED;
02669 break;
02670 case DAHDI_EVENT_EC_NLP_DISABLED:
02671 res = ANALOG_EVENT_EC_NLP_DISABLED;
02672 break;
02673 case DAHDI_EVENT_EC_NLP_ENABLED:
02674 res = ANALOG_EVENT_EC_NLP_ENABLED;
02675 break;
02676 #endif
02677 case DAHDI_EVENT_PULSEDIGIT:
02678 res = ANALOG_EVENT_PULSEDIGIT;
02679 break;
02680 case DAHDI_EVENT_DTMFDOWN:
02681 res = ANALOG_EVENT_DTMFDOWN;
02682 break;
02683 case DAHDI_EVENT_DTMFUP:
02684 res = ANALOG_EVENT_DTMFUP;
02685 break;
02686 default:
02687 switch(event & 0xFFFF0000) {
02688 case DAHDI_EVENT_PULSEDIGIT:
02689 case DAHDI_EVENT_DTMFDOWN:
02690 case DAHDI_EVENT_DTMFUP:
02691
02692
02693
02694
02695 return event;
02696 }
02697
02698 res = ANALOG_EVENT_ERROR;
02699 break;
02700 }
02701
02702 return res;
02703 }
02704
02705 static inline int dahdi_wait_event(int fd);
02706
02707 static int my_wait_event(void *pvt)
02708 {
02709 struct dahdi_pvt *p = pvt;
02710
02711 return dahdi_wait_event(p->subs[SUB_REAL].dfd);
02712 }
02713
02714 static int my_get_event(void *pvt)
02715 {
02716 struct dahdi_pvt *p = pvt;
02717 int res;
02718
02719 if (p->fake_event) {
02720 res = p->fake_event;
02721 p->fake_event = 0;
02722 } else
02723 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
02724
02725 return dahdievent_to_analogevent(res);
02726 }
02727
02728 static int my_is_off_hook(void *pvt)
02729 {
02730 struct dahdi_pvt *p = pvt;
02731 int res;
02732 struct dahdi_params par;
02733
02734 memset(&par, 0, sizeof(par));
02735
02736 if (p->subs[SUB_REAL].dfd > -1)
02737 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
02738 else {
02739
02740 res = 0;
02741 par.rxisoffhook = 0;
02742 }
02743 if (res) {
02744 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
02745 }
02746
02747 if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
02748
02749
02750
02751 return (par.rxbits > -1) || par.rxisoffhook;
02752 }
02753
02754 return par.rxisoffhook;
02755 }
02756
02757 static void dahdi_enable_ec(struct dahdi_pvt *p);
02758 static void dahdi_disable_ec(struct dahdi_pvt *p);
02759
02760 static int my_set_echocanceller(void *pvt, int enable)
02761 {
02762 struct dahdi_pvt *p = pvt;
02763
02764 if (enable)
02765 dahdi_enable_ec(p);
02766 else
02767 dahdi_disable_ec(p);
02768
02769 return 0;
02770 }
02771
02772 static int dahdi_ring_phone(struct dahdi_pvt *p);
02773
02774 static int my_ring(void *pvt)
02775 {
02776 struct dahdi_pvt *p = pvt;
02777
02778 return dahdi_ring_phone(p);
02779 }
02780
02781 static int my_flash(void *pvt)
02782 {
02783 struct dahdi_pvt *p = pvt;
02784 int func = DAHDI_FLASH;
02785 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func);
02786 }
02787
02788 static inline int dahdi_set_hook(int fd, int hs);
02789
02790 static int my_off_hook(void *pvt)
02791 {
02792 struct dahdi_pvt *p = pvt;
02793 return dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
02794 }
02795
02796 static void my_set_needringing(void *pvt, int value)
02797 {
02798 struct dahdi_pvt *p = pvt;
02799 p->subs[SUB_REAL].needringing = value;
02800 }
02801
02802 static void my_set_polarity(void *pvt, int value)
02803 {
02804 struct dahdi_pvt *p = pvt;
02805
02806 if (p->channel == CHAN_PSEUDO) {
02807 return;
02808 }
02809 p->polarity = value;
02810 ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETPOLARITY, &value);
02811 }
02812
02813 static void my_start_polarityswitch(void *pvt)
02814 {
02815 struct dahdi_pvt *p = pvt;
02816
02817 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
02818 my_set_polarity(pvt, 0);
02819 }
02820 }
02821
02822 static void my_answer_polarityswitch(void *pvt)
02823 {
02824 struct dahdi_pvt *p = pvt;
02825
02826 if (!p->answeronpolarityswitch) {
02827 return;
02828 }
02829
02830 my_set_polarity(pvt, 1);
02831 }
02832
02833 static void my_hangup_polarityswitch(void *pvt)
02834 {
02835 struct dahdi_pvt *p = pvt;
02836
02837 if (!p->hanguponpolarityswitch) {
02838 return;
02839 }
02840
02841 if (p->answeronpolarityswitch) {
02842 my_set_polarity(pvt, 0);
02843 } else {
02844 my_set_polarity(pvt, 1);
02845 }
02846 }
02847
02848 static int my_start(void *pvt)
02849 {
02850 struct dahdi_pvt *p = pvt;
02851 int x = DAHDI_START;
02852
02853 return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02854 }
02855
02856 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
02857 {
02858 int index = analogsub_to_dahdisub(sub);
02859 int res;
02860 struct dahdi_pvt *p = pvt;
02861 struct dahdi_dialoperation ddop;
02862
02863 if (dop->op != ANALOG_DIAL_OP_REPLACE) {
02864 ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
02865 return -1;
02866 }
02867
02868 if (sub != ANALOG_SUB_REAL)
02869 printf("Trying to dial digits on sub %d\n", sub);
02870
02871 ddop.op = DAHDI_DIAL_OP_REPLACE;
02872 strncpy(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
02873
02874 printf("Dialing %s on %d\n", ddop.dialstr, p->channel);
02875
02876 res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
02877
02878 if (res == -1)
02879 ast_log(LOG_DEBUG, "DAHDI_DIAL ioctl failed on %s: %s\n", p->owner->name, strerror(errno));
02880
02881 return res;
02882 }
02883
02884 static void dahdi_train_ec(struct dahdi_pvt *p);
02885
02886 static int my_train_echocanceller(void *pvt)
02887 {
02888 struct dahdi_pvt *p = pvt;
02889
02890 dahdi_train_ec(p);
02891
02892 return 0;
02893 }
02894
02895 static int my_is_dialing(void *pvt, enum analog_sub sub)
02896 {
02897 struct dahdi_pvt *p = pvt;
02898 int index;
02899 int x;
02900
02901 index = analogsub_to_dahdisub(sub);
02902
02903 if (ioctl(p->subs[index].dfd, DAHDI_DIALING, &x)) {
02904 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed!\n");
02905 return -1;
02906 }
02907
02908 return x;
02909 }
02910
02911 static int my_on_hook(void *pvt)
02912 {
02913 struct dahdi_pvt *p = pvt;
02914 return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK);
02915 }
02916
02917 #if defined(HAVE_PRI)
02918 static void my_pri_fixup_chans(void *chan_old, void *chan_new)
02919 {
02920 struct dahdi_pvt *old_chan = chan_old;
02921 struct dahdi_pvt *new_chan = chan_new;
02922
02923 new_chan->owner = old_chan->owner;
02924 old_chan->owner = NULL;
02925 if (new_chan->owner) {
02926 new_chan->owner->tech_pvt = new_chan;
02927 new_chan->owner->fds[0] = new_chan->subs[SUB_REAL].dfd;
02928 new_chan->subs[SUB_REAL].owner = old_chan->subs[SUB_REAL].owner;
02929 old_chan->subs[SUB_REAL].owner = NULL;
02930 }
02931
02932 new_chan->dsp = old_chan->dsp;
02933 new_chan->dsp_features = old_chan->dsp_features;
02934 old_chan->dsp = NULL;
02935 old_chan->dsp_features = 0;
02936
02937
02938 new_chan->dialing = old_chan->dialing;
02939 new_chan->digital = old_chan->digital;
02940 new_chan->outgoing = old_chan->outgoing;
02941 old_chan->dialing = 0;
02942 old_chan->digital = 0;
02943 old_chan->outgoing = 0;
02944
02945
02946 new_chan->law = old_chan->law;
02947 strcpy(new_chan->dialstring, old_chan->dialstring);
02948 }
02949 #endif
02950
02951 #if defined(HAVE_PRI)
02952 static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
02953 {
02954 switch (tone) {
02955 case SIG_PRI_TONE_RINGTONE:
02956 return DAHDI_TONE_RINGTONE;
02957 case SIG_PRI_TONE_STUTTER:
02958 return DAHDI_TONE_STUTTER;
02959 case SIG_PRI_TONE_CONGESTION:
02960 return DAHDI_TONE_CONGESTION;
02961 case SIG_PRI_TONE_DIALTONE:
02962 return DAHDI_TONE_DIALTONE;
02963 case SIG_PRI_TONE_DIALRECALL:
02964 return DAHDI_TONE_DIALRECALL;
02965 case SIG_PRI_TONE_INFO:
02966 return DAHDI_TONE_INFO;
02967 case SIG_PRI_TONE_BUSY:
02968 return DAHDI_TONE_BUSY;
02969 default:
02970 return -1;
02971 }
02972 }
02973 #endif
02974
02975 #if defined(HAVE_PRI)
02976 static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
02977 {
02978 int x, res;
02979
02980 res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
02981 if (x) {
02982 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
02983 }
02984
02985 switch (x) {
02986 case DAHDI_EVENT_ALARM:
02987 pri_event_alarm(pri, index, 0);
02988 break;
02989 case DAHDI_EVENT_NOALARM:
02990 pri_event_noalarm(pri, index, 0);
02991 break;
02992 default:
02993 break;
02994 }
02995 }
02996 #endif
02997
02998 #if defined(HAVE_PRI)
02999 static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
03000 {
03001 struct dahdi_pvt *p = pvt;
03002
03003 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
03004 }
03005 #endif
03006
03007 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018 static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
03019 {
03020 struct dahdi_pvt *p = pvt;
03021
03022 ast_copy_string(p->cid_num,
03023 S_COR(caller->id.number.valid, caller->id.number.str, ""),
03024 sizeof(p->cid_num));
03025 ast_copy_string(p->cid_name,
03026 S_COR(caller->id.name.valid, caller->id.name.str, ""),
03027 sizeof(p->cid_name));
03028 ast_copy_string(p->cid_subaddr,
03029 S_COR(caller->id.subaddress.valid, caller->id.subaddress.str, ""),
03030 sizeof(p->cid_subaddr));
03031 p->cid_ton = caller->id.number.plan;
03032 p->callingpres = ast_party_id_presentation(&caller->id);
03033 if (caller->id.tag) {
03034 ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
03035 }
03036 ast_copy_string(p->cid_ani,
03037 S_COR(caller->ani.number.valid, caller->ani.number.str, ""),
03038 sizeof(p->cid_ani));
03039 p->cid_ani2 = caller->ani2;
03040 }
03041 #endif
03042
03043 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054 static void my_set_dnid(void *pvt, const char *dnid)
03055 {
03056 struct dahdi_pvt *p = pvt;
03057
03058 ast_copy_string(p->dnid, dnid, sizeof(p->dnid));
03059 }
03060 #endif
03061
03062 #if defined(HAVE_PRI)
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073 static void my_set_rdnis(void *pvt, const char *rdnis)
03074 {
03075 struct dahdi_pvt *p = pvt;
03076
03077 ast_copy_string(p->rdnis, rdnis, sizeof(p->rdnis));
03078 }
03079 #endif
03080
03081 #if defined(HAVE_PRI)
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106 static void my_pri_make_cc_dialstring(void *priv, char *buf, size_t buf_size)
03107 {
03108 char *dial;
03109 struct dahdi_pvt *pvt;
03110 AST_DECLARE_APP_ARGS(args,
03111 AST_APP_ARG(tech);
03112 AST_APP_ARG(group);
03113
03114
03115
03116 );
03117
03118 pvt = priv;
03119 dial = ast_strdupa(pvt->dialstring);
03120 AST_NONSTANDARD_APP_ARGS(args, dial, '/');
03121 if (!args.tech) {
03122 ast_copy_string(buf, pvt->dialstring, buf_size);
03123 return;
03124 }
03125 if (!args.group) {
03126
03127 snprintf(buf, buf_size, "%s/i%d-", args.tech, pvt->pri->span);
03128 return;
03129 }
03130 if (isdigit(args.group[0]) || args.group[0] == 'i' || strchr(args.group, '!')) {
03131
03132
03133 ast_copy_string(buf, pvt->dialstring, buf_size);
03134 return;
03135 }
03136
03137 snprintf(buf, buf_size, "%s/i%d-%s", args.tech, pvt->pri->span, args.group);
03138 }
03139 #endif
03140
03141 #if defined(HAVE_PRI)
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153 static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri)
03154 {
03155 unsigned idx;
03156 unsigned num_b_chans;
03157 unsigned in_use;
03158 unsigned in_alarm;
03159 enum ast_device_state new_state;
03160
03161
03162 num_b_chans = 0;
03163 in_use = 0;
03164 in_alarm = 1;
03165 for (idx = pri->numchans; idx--;) {
03166 if (pri->pvts[idx] && !pri->pvts[idx]->no_b_channel) {
03167
03168 ++num_b_chans;
03169 if (pri->pvts[idx]->owner
03170 #if defined(HAVE_PRI_SERVICE_MESSAGES)
03171
03172 || pri->pvts[idx]->service_status
03173 #endif
03174 ) {
03175 ++in_use;
03176 }
03177 if (!pri->pvts[idx]->inalarm) {
03178
03179 in_alarm = 0;
03180 }
03181 }
03182 }
03183
03184
03185 if (in_alarm) {
03186 new_state = AST_DEVICE_UNAVAILABLE;
03187 } else {
03188 new_state = num_b_chans == in_use ? AST_DEVICE_BUSY : AST_DEVICE_NOT_INUSE;
03189 }
03190 if (pri->congestion_devstate != new_state) {
03191 pri->congestion_devstate = new_state;
03192 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span);
03193 }
03194 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
03195
03196 if (in_alarm) {
03197 new_state = AST_DEVICE_UNAVAILABLE;
03198 } else if (!in_use) {
03199 new_state = AST_DEVICE_NOT_INUSE;
03200 } else if (!pri->user_busy_threshold) {
03201 new_state = in_use < num_b_chans ? AST_DEVICE_INUSE : AST_DEVICE_BUSY;
03202 } else {
03203 new_state = in_use < pri->user_busy_threshold ? AST_DEVICE_INUSE
03204 : AST_DEVICE_BUSY;
03205 }
03206 if (pri->threshold_devstate != new_state) {
03207 pri->threshold_devstate = new_state;
03208 ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span);
03209 }
03210 #endif
03211 }
03212 #endif
03213
03214 #if defined(HAVE_PRI)
03215
03216
03217
03218
03219
03220
03221
03222 static void my_module_ref(void)
03223 {
03224 ast_module_ref(ast_module_info->self);
03225 }
03226 #endif
03227
03228 #if defined(HAVE_PRI)
03229
03230
03231
03232
03233
03234
03235
03236 static void my_module_unref(void)
03237 {
03238 ast_module_unref(ast_module_info->self);
03239 }
03240 #endif
03241
03242 #if defined(HAVE_PRI)
03243 #if defined(HAVE_PRI_CALL_WAITING)
03244 static void my_pri_init_config(void *priv, struct sig_pri_span *pri);
03245 #endif
03246 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri);
03247
03248 static struct sig_pri_callback dahdi_pri_callbacks =
03249 {
03250 .handle_dchan_exception = my_handle_dchan_exception,
03251 .play_tone = my_pri_play_tone,
03252 .set_echocanceller = my_set_echocanceller,
03253 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03254 .lock_private = my_lock_private,
03255 .unlock_private = my_unlock_private,
03256 .new_ast_channel = my_new_pri_ast_channel,
03257 .fixup_chans = my_pri_fixup_chans,
03258 .set_alarm = my_set_alarm,
03259 .set_dialing = my_set_dialing,
03260 .set_digital = my_set_digital,
03261 .set_callerid = my_set_callerid,
03262 .set_dnid = my_set_dnid,
03263 .set_rdnis = my_set_rdnis,
03264 .new_nobch_intf = dahdi_new_pri_nobch_channel,
03265 #if defined(HAVE_PRI_CALL_WAITING)
03266 .init_config = my_pri_init_config,
03267 #endif
03268 .get_orig_dialstring = my_get_orig_dialstring,
03269 .make_cc_dialstring = my_pri_make_cc_dialstring,
03270 .update_span_devstate = dahdi_pri_update_span_devstate,
03271 .module_ref = my_module_ref,
03272 .module_unref = my_module_unref,
03273 .open_media = my_pri_open_media,
03274 };
03275 #endif
03276
03277 #if defined(HAVE_SS7)
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288 static void my_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
03289 {
03290 int event;
03291
03292 if (ioctl(linkset->fds[which], DAHDI_GETEVENT, &event)) {
03293 ast_log(LOG_ERROR, "SS7: Error in exception retrieval on span %d/%d!\n",
03294 linkset->span, which);
03295 return;
03296 }
03297 switch (event) {
03298 case DAHDI_EVENT_NONE:
03299 break;
03300 case DAHDI_EVENT_ALARM:
03301 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03302 event2str(event), event, linkset->span, which);
03303 sig_ss7_link_alarm(linkset, which);
03304 break;
03305 case DAHDI_EVENT_NOALARM:
03306 ast_log(LOG_ERROR, "SS7 got event: %s(%d) on span %d/%d\n",
03307 event2str(event), event, linkset->span, which);
03308 sig_ss7_link_noalarm(linkset, which);
03309 break;
03310 default:
03311 ast_log(LOG_NOTICE, "SS7 got event: %s(%d) on span %d/%d\n",
03312 event2str(event), event, linkset->span, which);
03313 break;
03314 }
03315 }
03316 #endif
03317
03318 #if defined(HAVE_SS7)
03319 static void my_ss7_set_loopback(void *pvt, int enable)
03320 {
03321 struct dahdi_pvt *p = pvt;
03322
03323 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
03324 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel,
03325 strerror(errno));
03326 }
03327 }
03328 #endif
03329
03330 #if defined(HAVE_SS7)
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345 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)
03346 {
03347 struct dahdi_pvt *p = pvt;
03348 int audio;
03349 int newlaw;
03350
03351
03352 audio = 1;
03353 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
03354 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n",
03355 p->channel, audio, strerror(errno));
03356
03357 if (law != SIG_SS7_DEFLAW) {
03358 dahdi_setlaw(p->subs[SUB_REAL].dfd,
03359 (law == SIG_SS7_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
03360 }
03361
03362 ast_copy_string(p->exten, exten, sizeof(p->exten));
03363
03364 newlaw = -1;
03365 switch (law) {
03366 case SIG_SS7_DEFLAW:
03367 newlaw = 0;
03368 break;
03369 case SIG_SS7_ALAW:
03370 newlaw = DAHDI_LAW_ALAW;
03371 break;
03372 case SIG_SS7_ULAW:
03373 newlaw = DAHDI_LAW_MULAW;
03374 break;
03375 }
03376 return dahdi_new(p, state, 0, SUB_REAL, newlaw, requestor ? requestor->linkedid : "");
03377 }
03378 #endif
03379
03380 #if defined(HAVE_SS7)
03381 static int sig_ss7_tone_to_dahditone(enum sig_ss7_tone tone)
03382 {
03383 switch (tone) {
03384 case SIG_SS7_TONE_RINGTONE:
03385 return DAHDI_TONE_RINGTONE;
03386 case SIG_SS7_TONE_STUTTER:
03387 return DAHDI_TONE_STUTTER;
03388 case SIG_SS7_TONE_CONGESTION:
03389 return DAHDI_TONE_CONGESTION;
03390 case SIG_SS7_TONE_DIALTONE:
03391 return DAHDI_TONE_DIALTONE;
03392 case SIG_SS7_TONE_DIALRECALL:
03393 return DAHDI_TONE_DIALRECALL;
03394 case SIG_SS7_TONE_INFO:
03395 return DAHDI_TONE_INFO;
03396 case SIG_SS7_TONE_BUSY:
03397 return DAHDI_TONE_BUSY;
03398 default:
03399 return -1;
03400 }
03401 }
03402 #endif
03403
03404 #if defined(HAVE_SS7)
03405 static int my_ss7_play_tone(void *pvt, enum sig_ss7_tone tone)
03406 {
03407 struct dahdi_pvt *p = pvt;
03408
03409 return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_ss7_tone_to_dahditone(tone));
03410 }
03411 #endif
03412
03413 #if defined(HAVE_SS7)
03414 static struct sig_ss7_callback dahdi_ss7_callbacks =
03415 {
03416 .lock_private = my_lock_private,
03417 .unlock_private = my_unlock_private,
03418
03419 .set_echocanceller = my_set_echocanceller,
03420 .set_loopback = my_ss7_set_loopback,
03421
03422 .new_ast_channel = my_new_ss7_ast_channel,
03423 .play_tone = my_ss7_play_tone,
03424
03425 .handle_link_exception = my_handle_link_exception,
03426 .set_alarm = my_set_alarm,
03427 .set_dialing = my_set_dialing,
03428 .set_digital = my_set_digital,
03429 .set_inservice = my_set_inservice,
03430 .set_locallyblocked = my_set_locallyblocked,
03431 .set_remotelyblocked = my_set_remotelyblocked,
03432 .set_callerid = my_set_callerid,
03433 .set_dnid = my_set_dnid,
03434 };
03435 #endif
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455 static void notify_message(char *mailbox_full, int thereornot)
03456 {
03457 char s[sizeof(mwimonitornotify) + 80];
03458 struct ast_event *event;
03459 char *mailbox, *context;
03460
03461
03462 context = mailbox = ast_strdupa(mailbox_full);
03463 strsep(&context, "@");
03464 if (ast_strlen_zero(context))
03465 context = "default";
03466
03467 if (!(event = ast_event_new(AST_EVENT_MWI,
03468 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03469 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03470 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03471 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
03472 AST_EVENT_IE_END))) {
03473 return;
03474 }
03475
03476 ast_event_queue_and_cache(event);
03477
03478 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
03479 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
03480 ast_safe_system(s);
03481 }
03482 }
03483
03484 static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int cid_flags, int neon_mwievent)
03485 {
03486 struct dahdi_pvt *p = pvt;
03487
03488 if (neon_mwievent > -1 && !p->mwimonitor_neon)
03489 return;
03490
03491 if (neon_mwievent == ANALOG_EVENT_NEONMWI_ACTIVE || cid_flags & CID_MSGWAITING) {
03492 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting, mailbox %s\n", p->channel, p->mailbox);
03493 notify_message(p->mailbox, 1);
03494 } else if (neon_mwievent == ANALOG_EVENT_NEONMWI_INACTIVE || cid_flags & CID_NOMSGWAITING) {
03495 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting, mailbox %s\n", p->channel, p->mailbox);
03496 notify_message(p->mailbox, 0);
03497 }
03498
03499
03500 if (neon_mwievent == -1 && p->mwimonitor_rpas) {
03501 ast_hangup(chan);
03502 return;
03503 }
03504 }
03505
03506
03507
03508 static struct analog_callback dahdi_analog_callbacks =
03509 {
03510 .play_tone = my_play_tone,
03511 .get_event = my_get_event,
03512 .wait_event = my_wait_event,
03513 .is_off_hook = my_is_off_hook,
03514 .set_echocanceller = my_set_echocanceller,
03515 .ring = my_ring,
03516 .flash = my_flash,
03517 .off_hook = my_off_hook,
03518 .dial_digits = my_dial_digits,
03519 .train_echocanceller = my_train_echocanceller,
03520 .on_hook = my_on_hook,
03521 .is_dialing = my_is_dialing,
03522 .allocate_sub = my_allocate_sub,
03523 .unallocate_sub = my_unallocate_sub,
03524 .swap_subs = my_swap_subchannels,
03525 .has_voicemail = my_has_voicemail,
03526 .check_for_conference = my_check_for_conference,
03527 .conf_add = my_conf_add,
03528 .conf_del = my_conf_del,
03529 .complete_conference_update = my_complete_conference_update,
03530 .start = my_start,
03531 .all_subchannels_hungup = my_all_subchannels_hungup,
03532 .lock_private = my_lock_private,
03533 .unlock_private = my_unlock_private,
03534 .deadlock_avoidance_private = my_deadlock_avoidance_private,
03535 .handle_dtmf = my_handle_dtmf,
03536 .wink = my_wink,
03537 .new_ast_channel = my_new_analog_ast_channel,
03538 .dsp_set_digitmode = my_dsp_set_digitmode,
03539 .dsp_reset_and_flush_digits = my_dsp_reset_and_flush_digits,
03540 .send_callerid = my_send_callerid,
03541 .callwait = my_callwait,
03542 .stop_callwait = my_stop_callwait,
03543 .get_callerid = my_get_callerid,
03544 .start_cid_detect = my_start_cid_detect,
03545 .stop_cid_detect = my_stop_cid_detect,
03546 .handle_notify_message = my_handle_notify_message,
03547 .increase_ss_count = my_increase_ss_count,
03548 .decrease_ss_count = my_decrease_ss_count,
03549 .distinctive_ring = my_distinctive_ring,
03550 .set_linear_mode = my_set_linear_mode,
03551 .set_inthreeway = my_set_inthreeway,
03552 .get_and_handle_alarms = my_get_and_handle_alarms,
03553 .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel,
03554 .get_sub_fd = my_get_sub_fd,
03555 .set_cadence = my_set_cadence,
03556 .set_alarm = my_set_alarm,
03557 .set_dialing = my_set_dialing,
03558 .set_ringtimeout = my_set_ringtimeout,
03559 .set_waitingfordt = my_set_waitingfordt,
03560 .check_waitingfordt = my_check_waitingfordt,
03561 .set_confirmanswer = my_set_confirmanswer,
03562 .check_confirmanswer = my_check_confirmanswer,
03563 .set_callwaiting = my_set_callwaiting,
03564 .cancel_cidspill = my_cancel_cidspill,
03565 .confmute = my_confmute,
03566 .set_pulsedial = my_set_pulsedial,
03567 .set_new_owner = my_set_new_owner,
03568 .get_orig_dialstring = my_get_orig_dialstring,
03569 .set_needringing = my_set_needringing,
03570 .set_polarity = my_set_polarity,
03571 .start_polarityswitch = my_start_polarityswitch,
03572 .answer_polarityswitch = my_answer_polarityswitch,
03573 .hangup_polarityswitch = my_hangup_polarityswitch,
03574 };
03575
03576
03577 static struct dahdi_pvt *round_robin[32];
03578
03579 #define dahdi_get_index(ast, p, nullok) _dahdi_get_index(ast, p, nullok, __PRETTY_FUNCTION__, __LINE__)
03580 static int _dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok, const char *fname, unsigned long line)
03581 {
03582 int res;
03583 if (p->subs[SUB_REAL].owner == ast)
03584 res = 0;
03585 else if (p->subs[SUB_CALLWAIT].owner == ast)
03586 res = 1;
03587 else if (p->subs[SUB_THREEWAY].owner == ast)
03588 res = 2;
03589 else {
03590 res = -1;
03591 if (!nullok)
03592 ast_log(LOG_WARNING,
03593 "Unable to get index for '%s' on channel %d (%s(), line %lu)\n",
03594 ast ? ast->name : "", p->channel, fname, line);
03595 }
03596 return res;
03597 }
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614 static void dahdi_lock_sub_owner(struct dahdi_pvt *pvt, int sub_idx)
03615 {
03616 for (;;) {
03617 if (!pvt->subs[sub_idx].owner) {
03618
03619 break;
03620 }
03621 if (!ast_channel_trylock(pvt->subs[sub_idx].owner)) {
03622
03623 break;
03624 }
03625
03626 DEADLOCK_AVOIDANCE(&pvt->lock);
03627 }
03628 }
03629
03630 static void wakeup_sub(struct dahdi_pvt *p, int a)
03631 {
03632 dahdi_lock_sub_owner(p, a);
03633 if (p->subs[a].owner) {
03634 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
03635 ast_channel_unlock(p->subs[a].owner);
03636 }
03637 }
03638
03639 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f)
03640 {
03641 for (;;) {
03642 if (p->owner) {
03643 if (ast_channel_trylock(p->owner)) {
03644 DEADLOCK_AVOIDANCE(&p->lock);
03645 } else {
03646 ast_queue_frame(p->owner, f);
03647 ast_channel_unlock(p->owner);
03648 break;
03649 }
03650 } else
03651 break;
03652 }
03653 }
03654
03655 static void handle_clear_alarms(struct dahdi_pvt *p)
03656 {
03657 if (report_alarms & REPORT_CHANNEL_ALARMS) {
03658 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
03659 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", "Channel: %d\r\n", p->channel);
03660 }
03661 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
03662 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", p->span);
03663 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarmClear", "Span: %d\r\n", p->span);
03664 }
03665 }
03666
03667 #ifdef HAVE_OPENR2
03668
03669 static int dahdi_r2_answer(struct dahdi_pvt *p)
03670 {
03671 int res = 0;
03672
03673
03674
03675 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
03676 const char *double_answer = pbx_builtin_getvar_helper(p->owner, "MFCR2_DOUBLE_ANSWER");
03677 int wants_double_answer = ast_true(double_answer) ? 1 : 0;
03678 if (!double_answer) {
03679
03680
03681 res = openr2_chan_answer_call(p->r2chan);
03682 } else if (wants_double_answer) {
03683 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_DOUBLE);
03684 } else {
03685 res = openr2_chan_answer_call_with_mode(p->r2chan, OR2_ANSWER_SIMPLE);
03686 }
03687 #else
03688 res = openr2_chan_answer_call(p->r2chan);
03689 #endif
03690 return res;
03691 }
03692
03693
03694
03695
03696 static openr2_calling_party_category_t dahdi_r2_get_channel_category(struct ast_channel *c)
03697 {
03698 openr2_calling_party_category_t cat;
03699 const char *catstr = pbx_builtin_getvar_helper(c, "MFCR2_CATEGORY");
03700 struct dahdi_pvt *p = c->tech_pvt;
03701 if (ast_strlen_zero(catstr)) {
03702 ast_debug(1, "No MFC/R2 category specified for chan %s, using default %s\n",
03703 c->name, openr2_proto_get_category_string(p->mfcr2_category));
03704 return p->mfcr2_category;
03705 }
03706 if ((cat = openr2_proto_get_category(catstr)) == OR2_CALLING_PARTY_CATEGORY_UNKNOWN) {
03707 ast_log(LOG_WARNING, "Invalid category specified '%s' for chan %s, using default %s\n",
03708 catstr, c->name, openr2_proto_get_category_string(p->mfcr2_category));
03709 return p->mfcr2_category;
03710 }
03711 ast_debug(1, "Using category %s\n", catstr);
03712 return cat;
03713 }
03714
03715 static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
03716 {
03717 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03718 ast_mutex_lock(&p->lock);
03719 if (p->mfcr2call) {
03720 ast_mutex_unlock(&p->lock);
03721
03722
03723
03724
03725
03726 ast_log(LOG_ERROR, "Collision of calls on chan %d detected!.\n", openr2_chan_get_number(r2chan));
03727 return;
03728 }
03729 p->mfcr2call = 1;
03730
03731 p->cid_name[0] = '\0';
03732 p->cid_num[0] = '\0';
03733 p->cid_subaddr[0] = '\0';
03734 p->rdnis[0] = '\0';
03735 p->exten[0] = '\0';
03736 p->mfcr2_ani_index = '\0';
03737 p->mfcr2_dnis_index = '\0';
03738 p->mfcr2_dnis_matched = 0;
03739 p->mfcr2_answer_pending = 0;
03740 p->mfcr2_call_accepted = 0;
03741 ast_mutex_unlock(&p->lock);
03742 ast_verbose("New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan));
03743 }
03744
03745 static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
03746 {
03747 int res;
03748 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03749 ast_mutex_lock(&p->lock);
03750 p->inalarm = alarm ? 1 : 0;
03751 if (p->inalarm) {
03752 res = get_alarms(p);
03753 handle_alarms(p, res);
03754 } else {
03755 handle_clear_alarms(p);
03756 }
03757 ast_mutex_unlock(&p->lock);
03758 }
03759
03760 static void dahdi_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
03761 {
03762 ast_log(LOG_ERROR, "OS error on chan %d: %s\n", openr2_chan_get_number(r2chan), strerror(errorcode));
03763 }
03764
03765 static void dahdi_r2_on_protocol_error(openr2_chan_t *r2chan, openr2_protocol_error_t reason)
03766 {
03767 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03768 ast_log(LOG_ERROR, "MFC/R2 protocol error on chan %d: %s\n", openr2_chan_get_number(r2chan), openr2_proto_get_error(reason));
03769 if (p->owner) {
03770 p->owner->hangupcause = AST_CAUSE_PROTOCOL_ERROR;
03771 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03772 }
03773 ast_mutex_lock(&p->lock);
03774 p->mfcr2call = 0;
03775 ast_mutex_unlock(&p->lock);
03776 }
03777
03778 static void dahdi_r2_disconnect_call(struct dahdi_pvt *p, openr2_call_disconnect_cause_t cause)
03779 {
03780 if (openr2_chan_disconnect_call(p->r2chan, cause)) {
03781 ast_log(LOG_NOTICE, "Bad! failed to disconnect call on channel %d with reason %s, hope for the best!\n",
03782 p->channel, openr2_proto_get_disconnect_string(cause));
03783
03784 openr2_chan_set_idle(p->r2chan);
03785 ast_mutex_lock(&p->lock);
03786 p->mfcr2call = 0;
03787 ast_mutex_unlock(&p->lock);
03788 }
03789 }
03790
03791 static void dahdi_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, const char *dnis, openr2_calling_party_category_t category)
03792 {
03793 struct dahdi_pvt *p;
03794 struct ast_channel *c;
03795 ast_verbose("MFC/R2 call offered on chan %d. ANI = %s, DNIS = %s, Category = %s\n",
03796 openr2_chan_get_number(r2chan), ani ? ani : "(restricted)", dnis,
03797 openr2_proto_get_category_string(category));
03798 p = openr2_chan_get_client_data(r2chan);
03799
03800 if (!p->mfcr2_allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
03801 ast_log(LOG_NOTICE, "Rejecting MFC/R2 collect call\n");
03802 dahdi_r2_disconnect_call(p, OR2_CAUSE_COLLECT_CALL_REJECTED);
03803 return;
03804 }
03805 ast_mutex_lock(&p->lock);
03806 p->mfcr2_recvd_category = category;
03807
03808 if (!p->use_callerid) {
03809 ast_log(LOG_DEBUG, "No CID allowed in configuration, CID is being cleared!\n");
03810 p->cid_num[0] = 0;
03811 p->cid_name[0] = 0;
03812 }
03813
03814 if (p->immediate || !openr2_context_get_max_dnis(openr2_chan_get_context(r2chan))) {
03815 ast_log(LOG_DEBUG, "Setting exten => s because of immediate or 0 DNIS configured\n");
03816 p->exten[0] = 's';
03817 p->exten[1] = 0;
03818 }
03819 ast_mutex_unlock(&p->lock);
03820 if (!ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
03821 ast_log(LOG_NOTICE, "MFC/R2 call on channel %d requested non-existent extension '%s' in context '%s'. Rejecting call.\n",
03822 p->channel, p->exten, p->context);
03823 dahdi_r2_disconnect_call(p, OR2_CAUSE_UNALLOCATED_NUMBER);
03824 return;
03825 }
03826 if (!p->mfcr2_accept_on_offer) {
03827
03828 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03829 if (c) {
03830
03831
03832
03833 return;
03834 }
03835 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03836 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03837 } else if (p->mfcr2_charge_calls) {
03838 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge on chan %d\n", p->channel);
03839 openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
03840 } else {
03841 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge on chan %d\n", p->channel);
03842 openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
03843 }
03844 }
03845
03846 static void dahdi_r2_on_call_end(openr2_chan_t *r2chan)
03847 {
03848 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03849 ast_verbose("MFC/R2 call end on channel %d\n", p->channel);
03850 ast_mutex_lock(&p->lock);
03851 p->mfcr2call = 0;
03852 ast_mutex_unlock(&p->lock);
03853 }
03854
03855 static void dahdi_enable_ec(struct dahdi_pvt *p);
03856 static void dahdi_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
03857 {
03858 struct dahdi_pvt *p = NULL;
03859 struct ast_channel *c = NULL;
03860 p = openr2_chan_get_client_data(r2chan);
03861 dahdi_enable_ec(p);
03862 p->mfcr2_call_accepted = 1;
03863
03864 if (OR2_DIR_BACKWARD == openr2_chan_get_direction(r2chan)) {
03865 ast_verbose("MFC/R2 call has been accepted on backward channel %d\n", openr2_chan_get_number(r2chan));
03866
03867
03868
03869
03870 if (!p->mfcr2_accept_on_offer) {
03871 openr2_chan_disable_read(r2chan);
03872 if (p->mfcr2_answer_pending) {
03873 ast_log(LOG_DEBUG, "Answering MFC/R2 call after accepting it on chan %d\n", openr2_chan_get_number(r2chan));
03874 dahdi_r2_answer(p);
03875 }
03876 return;
03877 }
03878 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, NULL);
03879 if (c) {
03880
03881
03882 openr2_chan_disable_read(r2chan);
03883 return;
03884 }
03885 ast_log(LOG_WARNING, "Unable to create PBX channel in DAHDI channel %d\n", p->channel);
03886
03887 dahdi_r2_disconnect_call(p, OR2_CAUSE_OUT_OF_ORDER);
03888 return;
03889 }
03890
03891 ast_verbose("MFC/R2 call has been accepted on forward channel %d\n", p->channel);
03892 p->subs[SUB_REAL].needringing = 1;
03893 p->dialing = 0;
03894
03895 openr2_chan_disable_read(r2chan);
03896 }
03897
03898 static void dahdi_r2_on_call_answered(openr2_chan_t *r2chan)
03899 {
03900 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03901 ast_verbose("MFC/R2 call has been answered on channel %d\n", openr2_chan_get_number(r2chan));
03902 p->subs[SUB_REAL].needanswer = 1;
03903 }
03904
03905 static void dahdi_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf, int buflen)
03906 {
03907
03908 }
03909
03910 static int dahdi_r2_cause_to_ast_cause(openr2_call_disconnect_cause_t cause)
03911 {
03912 switch (cause) {
03913 case OR2_CAUSE_BUSY_NUMBER:
03914 return AST_CAUSE_BUSY;
03915 case OR2_CAUSE_NETWORK_CONGESTION:
03916 return AST_CAUSE_CONGESTION;
03917 case OR2_CAUSE_OUT_OF_ORDER:
03918 return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
03919 case OR2_CAUSE_UNALLOCATED_NUMBER:
03920 return AST_CAUSE_UNREGISTERED;
03921 case OR2_CAUSE_NO_ANSWER:
03922 return AST_CAUSE_NO_ANSWER;
03923 case OR2_CAUSE_NORMAL_CLEARING:
03924 return AST_CAUSE_NORMAL_CLEARING;
03925 case OR2_CAUSE_UNSPECIFIED:
03926 default:
03927 return AST_CAUSE_NOTDEFINED;
03928 }
03929 }
03930
03931 static void dahdi_r2_on_call_disconnect(openr2_chan_t *r2chan, openr2_call_disconnect_cause_t cause)
03932 {
03933 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
03934 ast_verbose("MFC/R2 call disconnected on channel %d\n", openr2_chan_get_number(r2chan));
03935 ast_mutex_lock(&p->lock);
03936 if (!p->owner) {
03937 ast_mutex_unlock(&p->lock);
03938
03939 dahdi_r2_disconnect_call(p, OR2_CAUSE_NORMAL_CLEARING);
03940 return;
03941 }
03942
03943
03944 if (p->owner->_state == AST_STATE_UP) {
03945 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03946 ast_mutex_unlock(&p->lock);
03947 } else if (openr2_chan_get_direction(r2chan) == OR2_DIR_FORWARD) {
03948
03949 switch (cause) {
03950 case OR2_CAUSE_BUSY_NUMBER:
03951 p->subs[SUB_REAL].needbusy = 1;
03952 break;
03953 case OR2_CAUSE_NETWORK_CONGESTION:
03954 case OR2_CAUSE_OUT_OF_ORDER:
03955 case OR2_CAUSE_UNALLOCATED_NUMBER:
03956 case OR2_CAUSE_NO_ANSWER:
03957 case OR2_CAUSE_UNSPECIFIED:
03958 case OR2_CAUSE_NORMAL_CLEARING:
03959 p->subs[SUB_REAL].needcongestion = 1;
03960 break;
03961 default:
03962 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
03963 }
03964 ast_mutex_unlock(&p->lock);
03965 } else {
03966 ast_mutex_unlock(&p->lock);
03967
03968
03969 ast_queue_hangup_with_cause(p->owner, dahdi_r2_cause_to_ast_cause(cause));
03970 }
03971 }
03972
03973 static void dahdi_r2_write_log(openr2_log_level_t level, char *logmessage)
03974 {
03975 switch (level) {
03976 case OR2_LOG_NOTICE:
03977 ast_verbose("%s", logmessage);
03978 break;
03979 case OR2_LOG_WARNING:
03980 ast_log(LOG_WARNING, "%s", logmessage);
03981 break;
03982 case OR2_LOG_ERROR:
03983 ast_log(LOG_ERROR, "%s", logmessage);
03984 break;
03985 case OR2_LOG_STACK_TRACE:
03986 case OR2_LOG_MF_TRACE:
03987 case OR2_LOG_CAS_TRACE:
03988 case OR2_LOG_DEBUG:
03989 case OR2_LOG_EX_DEBUG:
03990 ast_log(LOG_DEBUG, "%s", logmessage);
03991 break;
03992 default:
03993 ast_log(LOG_WARNING, "We should handle logging level %d here.\n", level);
03994 ast_log(LOG_DEBUG, "%s", logmessage);
03995 break;
03996 }
03997 }
03998
03999 static void dahdi_r2_on_line_blocked(openr2_chan_t *r2chan)
04000 {
04001 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04002 ast_mutex_lock(&p->lock);
04003 p->remotelyblocked = 1;
04004 ast_mutex_unlock(&p->lock);
04005 ast_log(LOG_NOTICE, "Far end blocked on chan %d\n", openr2_chan_get_number(r2chan));
04006 }
04007
04008 static void dahdi_r2_on_line_idle(openr2_chan_t *r2chan)
04009 {
04010 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04011 ast_mutex_lock(&p->lock);
04012 p->remotelyblocked = 0;
04013 ast_mutex_unlock(&p->lock);
04014 ast_log(LOG_NOTICE, "Far end unblocked on chan %d\n", openr2_chan_get_number(r2chan));
04015 }
04016
04017 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04018 __attribute__((format (printf, 3, 0)));
04019 static void dahdi_r2_on_context_log(openr2_context_t *r2context, openr2_log_level_t level, const char *fmt, va_list ap)
04020 {
04021 #define CONTEXT_TAG "Context - "
04022 char logmsg[256];
04023 char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
04024 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04025 snprintf(completemsg, sizeof(completemsg), CONTEXT_TAG "%s", logmsg);
04026 dahdi_r2_write_log(level, completemsg);
04027 #undef CONTEXT_TAG
04028 }
04029
04030 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04031 __attribute__((format (printf, 3, 0)));
04032 static void dahdi_r2_on_chan_log(openr2_chan_t *r2chan, openr2_log_level_t level, const char *fmt, va_list ap)
04033 {
04034 #define CHAN_TAG "Chan "
04035 char logmsg[256];
04036 char completemsg[sizeof(logmsg) + sizeof(CHAN_TAG) - 1];
04037 vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
04038 snprintf(completemsg, sizeof(completemsg), CHAN_TAG "%d - %s", openr2_chan_get_number(r2chan), logmsg);
04039 dahdi_r2_write_log(level, completemsg);
04040 }
04041
04042 static int dahdi_r2_on_dnis_digit_received(openr2_chan_t *r2chan, char digit)
04043 {
04044 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04045
04046 if (p->immediate) {
04047 return 0;
04048 }
04049 p->exten[p->mfcr2_dnis_index] = digit;
04050 p->rdnis[p->mfcr2_dnis_index] = digit;
04051 p->mfcr2_dnis_index++;
04052 p->exten[p->mfcr2_dnis_index] = 0;
04053 p->rdnis[p->mfcr2_dnis_index] = 0;
04054
04055 if ((p->mfcr2_dnis_matched ||
04056 (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num) && (p->mfcr2_dnis_matched = 1))) &&
04057 !ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
04058 return 0;
04059 }
04060
04061 return 1;
04062 }
04063
04064 static void dahdi_r2_on_ani_digit_received(openr2_chan_t *r2chan, char digit)
04065 {
04066 struct dahdi_pvt *p = openr2_chan_get_client_data(r2chan);
04067 p->cid_num[p->mfcr2_ani_index] = digit;
04068 p->cid_name[p->mfcr2_ani_index] = digit;
04069 p->mfcr2_ani_index++;
04070 p->cid_num[p->mfcr2_ani_index] = 0;
04071 p->cid_name[p->mfcr2_ani_index] = 0;
04072 }
04073
04074 static void dahdi_r2_on_billing_pulse_received(openr2_chan_t *r2chan)
04075 {
04076 ast_verbose("MFC/R2 billing pulse received on channel %d\n", openr2_chan_get_number(r2chan));
04077 }
04078
04079 static openr2_event_interface_t dahdi_r2_event_iface = {
04080 .on_call_init = dahdi_r2_on_call_init,
04081 .on_call_offered = dahdi_r2_on_call_offered,
04082 .on_call_accepted = dahdi_r2_on_call_accepted,
04083 .on_call_answered = dahdi_r2_on_call_answered,
04084 .on_call_disconnect = dahdi_r2_on_call_disconnect,
04085 .on_call_end = dahdi_r2_on_call_end,
04086 .on_call_read = dahdi_r2_on_call_read,
04087 .on_hardware_alarm = dahdi_r2_on_hardware_alarm,
04088 .on_os_error = dahdi_r2_on_os_error,
04089 .on_protocol_error = dahdi_r2_on_protocol_error,
04090 .on_line_blocked = dahdi_r2_on_line_blocked,
04091 .on_line_idle = dahdi_r2_on_line_idle,
04092
04093 .on_context_log = (openr2_handle_context_logging_func)dahdi_r2_on_context_log,
04094 .on_dnis_digit_received = dahdi_r2_on_dnis_digit_received,
04095 .on_ani_digit_received = dahdi_r2_on_ani_digit_received,
04096
04097 .on_billing_pulse_received = dahdi_r2_on_billing_pulse_received
04098 };
04099
04100 static inline int16_t dahdi_r2_alaw_to_linear(uint8_t sample)
04101 {
04102 return AST_ALAW(sample);
04103 }
04104
04105 static inline uint8_t dahdi_r2_linear_to_alaw(int sample)
04106 {
04107 return AST_LIN2A(sample);
04108 }
04109
04110 static openr2_transcoder_interface_t dahdi_r2_transcode_iface = {
04111 dahdi_r2_alaw_to_linear,
04112 dahdi_r2_linear_to_alaw
04113 };
04114
04115 #endif
04116
04117 static void swap_subs(struct dahdi_pvt *p, int a, int b)
04118 {
04119 int tchan;
04120 int tinthreeway;
04121 struct ast_channel *towner;
04122
04123 ast_debug(1, "Swapping %d and %d\n", a, b);
04124
04125 tchan = p->subs[a].chan;
04126 towner = p->subs[a].owner;
04127 tinthreeway = p->subs[a].inthreeway;
04128
04129 p->subs[a].chan = p->subs[b].chan;
04130 p->subs[a].owner = p->subs[b].owner;
04131 p->subs[a].inthreeway = p->subs[b].inthreeway;
04132
04133 p->subs[b].chan = tchan;
04134 p->subs[b].owner = towner;
04135 p->subs[b].inthreeway = tinthreeway;
04136
04137 if (p->subs[a].owner)
04138 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
04139 if (p->subs[b].owner)
04140 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
04141 wakeup_sub(p, a);
04142 wakeup_sub(p, b);
04143 }
04144
04145 static int dahdi_open(char *fn)
04146 {
04147 int fd;
04148 int isnum;
04149 int chan = 0;
04150 int bs;
04151 int x;
04152 isnum = 1;
04153 for (x = 0; x < strlen(fn); x++) {
04154 if (!isdigit(fn[x])) {
04155 isnum = 0;
04156 break;
04157 }
04158 }
04159 if (isnum) {
04160 chan = atoi(fn);
04161 if (chan < 1) {
04162 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
04163 return -1;
04164 }
04165 fn = "/dev/dahdi/channel";
04166 }
04167 fd = open(fn, O_RDWR | O_NONBLOCK);
04168 if (fd < 0) {
04169 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
04170 return -1;
04171 }
04172 if (chan) {
04173 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
04174 x = errno;
04175 close(fd);
04176 errno = x;
04177 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
04178 return -1;
04179 }
04180 }
04181 bs = READ_SIZE;
04182 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
04183 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
04184 x = errno;
04185 close(fd);
04186 errno = x;
04187 return -1;
04188 }
04189 return fd;
04190 }
04191
04192 static void dahdi_close(int fd)
04193 {
04194 if (fd > 0)
04195 close(fd);
04196 }
04197
04198 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
04199 {
04200 dahdi_close(chan_pvt->subs[sub_num].dfd);
04201 chan_pvt->subs[sub_num].dfd = -1;
04202 }
04203
04204 #if defined(HAVE_PRI)
04205 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
04206 {
04207 dahdi_close(pri->pri.fds[fd_num]);
04208 pri->pri.fds[fd_num] = -1;
04209 }
04210 #endif
04211
04212 #if defined(HAVE_SS7)
04213 static void dahdi_close_ss7_fd(struct dahdi_ss7 *ss7, int fd_num)
04214 {
04215 dahdi_close(ss7->ss7.fds[fd_num]);
04216 ss7->ss7.fds[fd_num] = -1;
04217 }
04218 #endif
04219
04220 static int dahdi_setlinear(int dfd, int linear)
04221 {
04222 return ioctl(dfd, DAHDI_SETLINEAR, &linear);
04223 }
04224
04225
04226 static int alloc_sub(struct dahdi_pvt *p, int x)
04227 {
04228 struct dahdi_bufferinfo bi;
04229 int res;
04230 if (p->subs[x].dfd >= 0) {
04231 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
04232 return -1;
04233 }
04234
04235 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
04236 if (p->subs[x].dfd <= -1) {
04237 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
04238 return -1;
04239 }
04240
04241 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
04242 if (!res) {
04243 bi.txbufpolicy = p->buf_policy;
04244 bi.rxbufpolicy = p->buf_policy;
04245 bi.numbufs = p->buf_no;
04246 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
04247 if (res < 0) {
04248 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
04249 }
04250 } else
04251 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
04252
04253 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
04254 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
04255 dahdi_close_sub(p, x);
04256 p->subs[x].dfd = -1;
04257 return -1;
04258 }
04259 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
04260 return 0;
04261 }
04262
04263 static int unalloc_sub(struct dahdi_pvt *p, int x)
04264 {
04265 if (!x) {
04266 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
04267 return -1;
04268 }
04269 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
04270 dahdi_close_sub(p, x);
04271 p->subs[x].linear = 0;
04272 p->subs[x].chan = 0;
04273 p->subs[x].owner = NULL;
04274 p->subs[x].inthreeway = 0;
04275 p->polarity = POLARITY_IDLE;
04276 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
04277 return 0;
04278 }
04279
04280 static int digit_to_dtmfindex(char digit)
04281 {
04282 if (isdigit(digit))
04283 return DAHDI_TONE_DTMF_BASE + (digit - '0');
04284 else if (digit >= 'A' && digit <= 'D')
04285 return DAHDI_TONE_DTMF_A + (digit - 'A');
04286 else if (digit >= 'a' && digit <= 'd')
04287 return DAHDI_TONE_DTMF_A + (digit - 'a');
04288 else if (digit == '*')
04289 return DAHDI_TONE_DTMF_s;
04290 else if (digit == '#')
04291 return DAHDI_TONE_DTMF_p;
04292 else
04293 return -1;
04294 }
04295
04296 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
04297 {
04298 struct dahdi_pvt *pvt;
04299 int idx;
04300 int dtmf = -1;
04301 int res;
04302
04303 pvt = chan->tech_pvt;
04304
04305 ast_mutex_lock(&pvt->lock);
04306
04307 idx = dahdi_get_index(chan, pvt, 0);
04308
04309 if ((idx != SUB_REAL) || !pvt->owner)
04310 goto out;
04311
04312 #ifdef HAVE_PRI
04313 switch (pvt->sig) {
04314 case SIG_PRI_LIB_HANDLE_CASES:
04315 res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
04316 if (!res)
04317 goto out;
04318 break;
04319 default:
04320 break;
04321 }
04322 #endif
04323 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
04324 goto out;
04325
04326 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
04327 struct dahdi_dialoperation zo = {
04328 .op = DAHDI_DIAL_OP_APPEND,
04329 };
04330
04331 zo.dialstr[0] = 'T';
04332 zo.dialstr[1] = digit;
04333 zo.dialstr[2] = '\0';
04334 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
04335 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
04336 else
04337 pvt->dialing = 1;
04338 } else {
04339 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
04340 pvt->dialing = 1;
04341 pvt->begindigit = digit;
04342 }
04343
04344 out:
04345 ast_mutex_unlock(&pvt->lock);
04346
04347 return 0;
04348 }
04349
04350 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
04351 {
04352 struct dahdi_pvt *pvt;
04353 int res = 0;
04354 int idx;
04355 int x;
04356
04357 pvt = chan->tech_pvt;
04358
04359 ast_mutex_lock(&pvt->lock);
04360
04361 idx = dahdi_get_index(chan, pvt, 0);
04362
04363 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
04364 goto out;
04365
04366 #ifdef HAVE_PRI
04367
04368 if (dahdi_sig_pri_lib_handles(pvt->sig) && !pvt->begindigit) {
04369 goto out;
04370 }
04371 #endif
04372
04373 if (pvt->begindigit) {
04374 x = -1;
04375 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
04376 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
04377 pvt->dialing = 0;
04378 pvt->begindigit = 0;
04379 }
04380
04381 out:
04382 ast_mutex_unlock(&pvt->lock);
04383
04384 return res;
04385 }
04386
04387 static const char * const events[] = {
04388 "No event",
04389 "On hook",
04390 "Ring/Answered",
04391 "Wink/Flash",
04392 "Alarm",
04393 "No more alarm",
04394 "HDLC Abort",
04395 "HDLC Overrun",
04396 "HDLC Bad FCS",
04397 "Dial Complete",
04398 "Ringer On",
04399 "Ringer Off",
04400 "Hook Transition Complete",
04401 "Bits Changed",
04402 "Pulse Start",
04403 "Timer Expired",
04404 "Timer Ping",
04405 "Polarity Reversal",
04406 "Ring Begin",
04407 };
04408
04409 static struct {
04410 int alarm;
04411 char *name;
04412 } alarms[] = {
04413 { DAHDI_ALARM_RED, "Red Alarm" },
04414 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
04415 { DAHDI_ALARM_BLUE, "Blue Alarm" },
04416 { DAHDI_ALARM_RECOVER, "Recovering" },
04417 { DAHDI_ALARM_LOOPBACK, "Loopback" },
04418 { DAHDI_ALARM_NOTOPEN, "Not Open" },
04419 { DAHDI_ALARM_NONE, "None" },
04420 };
04421
04422 static char *alarm2str(int alm)
04423 {
04424 int x;
04425 for (x = 0; x < ARRAY_LEN(alarms); x++) {
04426 if (alarms[x].alarm & alm)
04427 return alarms[x].name;
04428 }
04429 return alm ? "Unknown Alarm" : "No Alarm";
04430 }
04431
04432 static const char *event2str(int event)
04433 {
04434 static char buf[256];
04435 if ((event < (ARRAY_LEN(events))) && (event > -1))
04436 return events[event];
04437 sprintf(buf, "Event %d", event);
04438 return buf;
04439 }
04440
04441 static char *dahdi_sig2str(int sig)
04442 {
04443 static char buf[256];
04444 switch (sig) {
04445 case SIG_EM:
04446 return "E & M Immediate";
04447 case SIG_EMWINK:
04448 return "E & M Wink";
04449 case SIG_EM_E1:
04450 return "E & M E1";
04451 case SIG_FEATD:
04452 return "Feature Group D (DTMF)";
04453 case SIG_FEATDMF:
04454 return "Feature Group D (MF)";
04455 case SIG_FEATDMF_TA:
04456 return "Feature Groud D (MF) Tandem Access";
04457 case SIG_FEATB:
04458 return "Feature Group B (MF)";
04459 case SIG_E911:
04460 return "E911 (MF)";
04461 case SIG_FGC_CAMA:
04462 return "FGC/CAMA (Dialpulse)";
04463 case SIG_FGC_CAMAMF:
04464 return "FGC/CAMA (MF)";
04465 case SIG_FXSLS:
04466 return "FXS Loopstart";
04467 case SIG_FXSGS:
04468 return "FXS Groundstart";
04469 case SIG_FXSKS:
04470 return "FXS Kewlstart";
04471 case SIG_FXOLS:
04472 return "FXO Loopstart";
04473 case SIG_FXOGS:
04474 return "FXO Groundstart";
04475 case SIG_FXOKS:
04476 return "FXO Kewlstart";
04477 case SIG_PRI:
04478 return "ISDN PRI";
04479 case SIG_BRI:
04480 return "ISDN BRI Point to Point";
04481 case SIG_BRI_PTMP:
04482 return "ISDN BRI Point to MultiPoint";
04483 case SIG_SS7:
04484 return "SS7";
04485 case SIG_MFCR2:
04486 return "MFC/R2";
04487 case SIG_SF:
04488 return "SF (Tone) Immediate";
04489 case SIG_SFWINK:
04490 return "SF (Tone) Wink";
04491 case SIG_SF_FEATD:
04492 return "SF (Tone) with Feature Group D (DTMF)";
04493 case SIG_SF_FEATDMF:
04494 return "SF (Tone) with Feature Group D (MF)";
04495 case SIG_SF_FEATB:
04496 return "SF (Tone) with Feature Group B (MF)";
04497 case 0:
04498 return "Pseudo";
04499 default:
04500 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
04501 return buf;
04502 }
04503 }
04504
04505 #define sig2str dahdi_sig2str
04506
04507 static int analog_lib_handles(int signalling, int radio, int oprmode)
04508 {
04509 switch (signalling) {
04510 case SIG_FXOLS:
04511 case SIG_FXOGS:
04512 case SIG_FXOKS:
04513 case SIG_FXSLS:
04514 case SIG_FXSGS:
04515 case SIG_FXSKS:
04516 case SIG_EMWINK:
04517 case SIG_EM:
04518 case SIG_EM_E1:
04519 case SIG_FEATD:
04520 case SIG_FEATDMF:
04521 case SIG_E911:
04522 case SIG_FGC_CAMA:
04523 case SIG_FGC_CAMAMF:
04524 case SIG_FEATB:
04525 case SIG_SFWINK:
04526 case SIG_SF:
04527 case SIG_SF_FEATD:
04528 case SIG_SF_FEATDMF:
04529 case SIG_FEATDMF_TA:
04530 case SIG_SF_FEATB:
04531 break;
04532 default:
04533
04534 return 0;
04535 }
04536
04537 if (radio)
04538 return 0;
04539
04540 if (oprmode)
04541 return 0;
04542
04543 return 1;
04544 }
04545
04546 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
04547 {
04548
04549
04550 struct dahdi_confinfo zi;
04551
04552 memset(&zi, 0, sizeof(zi));
04553 zi.chan = 0;
04554
04555 if (slavechannel > 0) {
04556
04557 zi.confmode = DAHDI_CONF_DIGITALMON;
04558 zi.confno = slavechannel;
04559 } else {
04560 if (!idx) {
04561
04562 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
04563 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
04564 } else
04565 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
04566 zi.confno = p->confno;
04567 }
04568 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
04569 return 0;
04570 if (c->dfd < 0)
04571 return 0;
04572 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04573 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
04574 return -1;
04575 }
04576 if (slavechannel < 1) {
04577 p->confno = zi.confno;
04578 }
04579 c->curconf = zi;
04580 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04581 return 0;
04582 }
04583
04584 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
04585 {
04586
04587 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
04588 return 1;
04589
04590 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
04591 return 1;
04592 return 0;
04593 }
04594
04595 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
04596 {
04597 struct dahdi_confinfo zi;
04598 if (
04599 (c->dfd < 0) ||
04600
04601 !isourconf(p, c)
04602
04603 ) return 0;
04604 memset(&zi, 0, sizeof(zi));
04605 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
04606 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
04607 return -1;
04608 }
04609 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
04610 memcpy(&c->curconf, &zi, sizeof(c->curconf));
04611 return 0;
04612 }
04613
04614 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
04615 {
04616 int x;
04617 int useslavenative;
04618 struct dahdi_pvt *slave = NULL;
04619
04620 useslavenative = 1;
04621
04622 for (x = 0; x < 3; x++) {
04623
04624
04625 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
04626 useslavenative = 0;
04627 }
04628
04629
04630 if (useslavenative) {
04631 for (x = 0; x < MAX_SLAVES; x++) {
04632 if (p->slaves[x]) {
04633 if (slave) {
04634
04635
04636 slave = NULL;
04637 useslavenative = 0;
04638 break;
04639 } else {
04640
04641 slave = p->slaves[x];
04642 }
04643 }
04644 }
04645 }
04646
04647 if (!slave)
04648 useslavenative = 0;
04649 else if (slave->law != p->law) {
04650 useslavenative = 0;
04651 slave = NULL;
04652 }
04653 if (out)
04654 *out = slave;
04655 return useslavenative;
04656 }
04657
04658 static int reset_conf(struct dahdi_pvt *p)
04659 {
04660 p->confno = -1;
04661 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
04662 if (p->subs[SUB_REAL].dfd > -1) {
04663 struct dahdi_confinfo zi;
04664
04665 memset(&zi, 0, sizeof(zi));
04666 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
04667 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
04668 }
04669 return 0;
04670 }
04671
04672 static int update_conf(struct dahdi_pvt *p)
04673 {
04674 int needconf = 0;
04675 int x;
04676 int useslavenative;
04677 struct dahdi_pvt *slave = NULL;
04678
04679 useslavenative = isslavenative(p, &slave);
04680
04681 for (x = 0; x < 3; x++) {
04682
04683 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
04684 conf_add(p, &p->subs[x], x, 0);
04685 needconf++;
04686 } else {
04687 conf_del(p, &p->subs[x], x);
04688 }
04689 }
04690
04691
04692 for (x = 0; x < MAX_SLAVES; x++) {
04693 if (p->slaves[x]) {
04694 if (useslavenative)
04695 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
04696 else {
04697 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
04698 needconf++;
04699 }
04700 }
04701 }
04702
04703 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
04704 if (useslavenative)
04705 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
04706 else {
04707 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
04708 needconf++;
04709 }
04710 }
04711
04712 if (p->master) {
04713 if (isslavenative(p->master, NULL)) {
04714 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
04715 } else {
04716 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
04717 }
04718 }
04719 if (!needconf) {
04720
04721
04722 p->confno = -1;
04723 }
04724 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
04725 return 0;
04726 }
04727
04728 static void dahdi_enable_ec(struct dahdi_pvt *p)
04729 {
04730 int res;
04731 if (!p)
04732 return;
04733 if (p->echocanon) {
04734 ast_debug(1, "Echo cancellation already on\n");
04735 return;
04736 }
04737 if (p->digital) {
04738 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
04739 return;
04740 }
04741 if (p->echocancel.head.tap_length) {
04742 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04743 switch (p->sig) {
04744 #if defined(HAVE_PRI)
04745 case SIG_PRI_LIB_HANDLE_CASES:
04746 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
04747
04748
04749
04750
04751 return;
04752 }
04753
04754 #endif
04755 #if defined(HAVE_SS7)
04756 case SIG_SS7:
04757 #endif
04758 {
04759 int x = 1;
04760
04761 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
04762 if (res)
04763 ast_log(LOG_WARNING,
04764 "Unable to enable audio mode on channel %d (%s)\n",
04765 p->channel, strerror(errno));
04766 }
04767 break;
04768 default:
04769 break;
04770 }
04771 #endif
04772 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
04773 if (res) {
04774 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
04775 } else {
04776 p->echocanon = 1;
04777 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
04778 }
04779 } else
04780 ast_debug(1, "No echo cancellation requested\n");
04781 }
04782
04783 static void dahdi_train_ec(struct dahdi_pvt *p)
04784 {
04785 int x;
04786 int res;
04787
04788 if (p && p->echocanon && p->echotraining) {
04789 x = p->echotraining;
04790 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
04791 if (res)
04792 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
04793 else
04794 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
04795 } else {
04796 ast_debug(1, "No echo training requested\n");
04797 }
04798 }
04799
04800 static void dahdi_disable_ec(struct dahdi_pvt *p)
04801 {
04802 int res;
04803
04804 if (p->echocanon) {
04805 struct dahdi_echocanparams ecp = { .tap_length = 0 };
04806
04807 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
04808
04809 if (res)
04810 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
04811 else
04812 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
04813 }
04814
04815 p->echocanon = 0;
04816 }
04817
04818
04819 static int drc_sample(int sample, float drc)
04820 {
04821 float neg;
04822 float shallow, steep;
04823 float max = SHRT_MAX;
04824
04825 neg = (sample < 0 ? -1 : 1);
04826 steep = drc*sample;
04827 shallow = neg*(max-max/drc)+(float)sample/drc;
04828 if (abs(steep) < abs(shallow)) {
04829 sample = steep;
04830 }
04831 else {
04832 sample = shallow;
04833 }
04834
04835 return sample;
04836 }
04837
04838
04839 static void fill_txgain(struct dahdi_gains *g, float gain, float drc, int law)
04840 {
04841 int j;
04842 int k;
04843
04844 float linear_gain = pow(10.0, gain / 20.0);
04845
04846 switch (law) {
04847 case DAHDI_LAW_ALAW:
04848 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04849 if (gain || drc) {
04850 k = AST_ALAW(j);
04851 if (drc) {
04852 k = drc_sample(k, drc);
04853 }
04854 k = (float)k*linear_gain;
04855 if (k > 32767) k = 32767;
04856 if (k < -32767) k = -32767;
04857 g->txgain[j] = AST_LIN2A(k);
04858 } else {
04859 g->txgain[j] = j;
04860 }
04861 }
04862 break;
04863 case DAHDI_LAW_MULAW:
04864 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
04865 if (gain || drc) {
04866 k = AST_MULAW(j);
04867 if (drc) {
04868 k = drc_sample(k, drc);
04869 }
04870 k = (float)k*linear_gain;
04871 if (k > 32767) k = 32767;
04872 if (k < -32767) k = -32767;
04873 g->txgain[j] = AST_LIN2MU(k);
04874
04875 } else {
04876 g->txgain[j] = j;
04877 }
04878 }
04879 break;
04880 }
04881 }
04882
04883 static void fill_rxgain(struct dahdi_gains *g, float gain, float drc, int law)
04884 {
04885 int j;
04886 int k;
04887 float linear_gain = pow(10.0, gain / 20.0);
04888
04889 switch (law) {
04890 case DAHDI_LAW_ALAW:
04891 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04892 if (gain || drc) {
04893 k = AST_ALAW(j);
04894 if (drc) {
04895 k = drc_sample(k, drc);
04896 }
04897 k = (float)k*linear_gain;
04898 if (k > 32767) k = 32767;
04899 if (k < -32767) k = -32767;
04900 g->rxgain[j] = AST_LIN2A(k);
04901 } else {
04902 g->rxgain[j] = j;
04903 }
04904 }
04905 break;
04906 case DAHDI_LAW_MULAW:
04907 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
04908 if (gain || drc) {
04909 k = AST_MULAW(j);
04910 if (drc) {
04911 k = drc_sample(k, drc);
04912 }
04913 k = (float)k*linear_gain;
04914 if (k > 32767) k = 32767;
04915 if (k < -32767) k = -32767;
04916 g->rxgain[j] = AST_LIN2MU(k);
04917 } else {
04918 g->rxgain[j] = j;
04919 }
04920 }
04921 break;
04922 }
04923 }
04924
04925 static int set_actual_txgain(int fd, float gain, float drc, int law)
04926 {
04927 struct dahdi_gains g;
04928 int res;
04929
04930 memset(&g, 0, sizeof(g));
04931 res = ioctl(fd, DAHDI_GETGAINS, &g);
04932 if (res) {
04933 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04934 return res;
04935 }
04936
04937 fill_txgain(&g, gain, drc, law);
04938
04939 return ioctl(fd, DAHDI_SETGAINS, &g);
04940 }
04941
04942 static int set_actual_rxgain(int fd, float gain, float drc, int law)
04943 {
04944 struct dahdi_gains g;
04945 int res;
04946
04947 memset(&g, 0, sizeof(g));
04948 res = ioctl(fd, DAHDI_GETGAINS, &g);
04949 if (res) {
04950 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
04951 return res;
04952 }
04953
04954 fill_rxgain(&g, gain, drc, law);
04955
04956 return ioctl(fd, DAHDI_SETGAINS, &g);
04957 }
04958
04959 static int set_actual_gain(int fd, float rxgain, float txgain, float rxdrc, float txdrc, int law)
04960 {
04961 return set_actual_txgain(fd, txgain, txdrc, law) | set_actual_rxgain(fd, rxgain, rxdrc, law);
04962 }
04963
04964 static int bump_gains(struct dahdi_pvt *p)
04965 {
04966 int res;
04967
04968
04969 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain + p->cid_rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04970 if (res) {
04971 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
04972 return -1;
04973 }
04974
04975 return 0;
04976 }
04977
04978 static int restore_gains(struct dahdi_pvt *p)
04979 {
04980 int res;
04981
04982 res = set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
04983 if (res) {
04984 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
04985 return -1;
04986 }
04987
04988 return 0;
04989 }
04990
04991 static inline int dahdi_set_hook(int fd, int hs)
04992 {
04993 int x, res;
04994
04995 x = hs;
04996 res = ioctl(fd, DAHDI_HOOK, &x);
04997
04998 if (res < 0) {
04999 if (errno == EINPROGRESS)
05000 return 0;
05001 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
05002
05003 }
05004
05005 return res;
05006 }
05007
05008 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
05009 {
05010 int x, res;
05011
05012 x = muted;
05013 #if defined(HAVE_PRI) || defined(HAVE_SS7)
05014 switch (p->sig) {
05015 #if defined(HAVE_PRI)
05016 case SIG_PRI_LIB_HANDLE_CASES:
05017 if (((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
05018
05019 break;
05020 }
05021
05022 #endif
05023 #if defined(HAVE_SS7)
05024 case SIG_SS7:
05025 #endif
05026 {
05027 int y = 1;
05028
05029 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
05030 if (res)
05031 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n",
05032 p->channel, strerror(errno));
05033 }
05034 break;
05035 default:
05036 break;
05037 }
05038 #endif
05039 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
05040 if (res < 0)
05041 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
05042 return res;
05043 }
05044
05045 static int save_conference(struct dahdi_pvt *p)
05046 {
05047 struct dahdi_confinfo c;
05048 int res;
05049 if (p->saveconf.confmode) {
05050 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
05051 return -1;
05052 }
05053 p->saveconf.chan = 0;
05054 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
05055 if (res) {
05056 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
05057 p->saveconf.confmode = 0;
05058 return -1;
05059 }
05060 memset(&c, 0, sizeof(c));
05061 c.confmode = DAHDI_CONF_NORMAL;
05062 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
05063 if (res) {
05064 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
05065 return -1;
05066 }
05067 ast_debug(1, "Disabled conferencing\n");
05068 return 0;
05069 }
05070
05071 static int restore_conference(struct dahdi_pvt *p)
05072 {
05073 int res;
05074 if (p->saveconf.confmode) {
05075 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
05076 p->saveconf.confmode = 0;
05077 if (res) {
05078 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
05079 return -1;
05080 }
05081 ast_debug(1, "Restored conferencing\n");
05082 }
05083 return 0;
05084 }
05085
05086 static int send_cwcidspill(struct dahdi_pvt *p)
05087 {
05088 p->callwaitcas = 0;
05089 p->cidcwexpire = 0;
05090 p->cid_suppress_expire = 0;
05091 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
05092 return -1;
05093 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
05094
05095 p->cidlen += READ_SIZE * 4;
05096 p->cidpos = 0;
05097 send_callerid(p);
05098 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
05099 return 0;
05100 }
05101
05102 static int has_voicemail(struct dahdi_pvt *p)
05103 {
05104 int new_msgs;
05105 struct ast_event *event;
05106 char *mailbox, *context;
05107
05108 mailbox = context = ast_strdupa(p->mailbox);
05109 strsep(&context, "@");
05110 if (ast_strlen_zero(context))
05111 context = "default";
05112
05113 event = ast_event_get_cached(AST_EVENT_MWI,
05114 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05115 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05116 AST_EVENT_IE_END);
05117
05118 if (event) {
05119 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05120 ast_event_destroy(event);
05121 } else
05122 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
05123
05124 return new_msgs;
05125 }
05126
05127
05128
05129 static int send_callerid(struct dahdi_pvt *p)
05130 {
05131
05132 int res;
05133
05134 if (p->subs[SUB_REAL].linear) {
05135 p->subs[SUB_REAL].linear = 0;
05136 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
05137 }
05138 while (p->cidpos < p->cidlen) {
05139 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
05140 ast_debug(4, "writing callerid at pos %d of %d, res = %d\n", p->cidpos, p->cidlen, res);
05141 if (res < 0) {
05142 if (errno == EAGAIN)
05143 return 0;
05144 else {
05145 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05146 return -1;
05147 }
05148 }
05149 if (!res)
05150 return 0;
05151 p->cidpos += res;
05152 }
05153 p->cid_suppress_expire = CALLWAITING_SUPPRESS_SAMPLES;
05154 ast_free(p->cidspill);
05155 p->cidspill = NULL;
05156 if (p->callwaitcas) {
05157
05158 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
05159 p->cid_suppress_expire = p->cidcwexpire;
05160 } else
05161 restore_conference(p);
05162 return 0;
05163 }
05164
05165 static int dahdi_callwait(struct ast_channel *ast)
05166 {
05167 struct dahdi_pvt *p = ast->tech_pvt;
05168 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
05169 if (p->cidspill) {
05170 ast_log(LOG_WARNING, "Spill already exists?!?\n");
05171 ast_free(p->cidspill);
05172 }
05173
05174
05175
05176
05177
05178 if (!(p->cidspill = ast_malloc(2400 + 680 + READ_SIZE * 4)))
05179 return -1;
05180 save_conference(p);
05181
05182 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
05183 if (!p->callwaitrings && p->callwaitingcallerid) {
05184 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
05185 p->callwaitcas = 1;
05186 p->cidlen = 2400 + 680 + READ_SIZE * 4;
05187 } else {
05188 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
05189 p->callwaitcas = 0;
05190 p->cidlen = 2400 + READ_SIZE * 4;
05191 }
05192 p->cidpos = 0;
05193 send_callerid(p);
05194
05195 return 0;
05196 }
05197
05198 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
05199 {
05200 struct dahdi_pvt *p = ast->tech_pvt;
05201 int x, res, mysig;
05202 char dest[256];
05203
05204 ast_mutex_lock(&p->lock);
05205 ast_copy_string(dest, rdest, sizeof(dest));
05206 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
05207 if ((ast->_state == AST_STATE_BUSY)) {
05208 p->subs[SUB_REAL].needbusy = 1;
05209 ast_mutex_unlock(&p->lock);
05210 return 0;
05211 }
05212 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
05213 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
05214 ast_mutex_unlock(&p->lock);
05215 return -1;
05216 }
05217 p->waitingfordt.tv_sec = 0;
05218 p->dialednone = 0;
05219 if ((p->radio || (p->oprmode < 0)))
05220 {
05221
05222 ast_setstate(ast, AST_STATE_UP);
05223 ast_mutex_unlock(&p->lock);
05224 return 0;
05225 }
05226 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
05227 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
05228 if (res)
05229 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
05230 p->outgoing = 1;
05231
05232 if (IS_DIGITAL(ast->transfercapability)){
05233 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, p->rxdrc, p->txdrc, p->law);
05234 } else {
05235 set_actual_gain(p->subs[SUB_REAL].dfd, p->rxgain, p->txgain, p->rxdrc, p->txdrc, p->law);
05236 }
05237
05238 #ifdef HAVE_PRI
05239 if (dahdi_sig_pri_lib_handles(p->sig)) {
05240 res = sig_pri_call(p->sig_pvt, ast, rdest, timeout,
05241 (p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW);
05242 ast_mutex_unlock(&p->lock);
05243 return res;
05244 }
05245 #endif
05246
05247 #if defined(HAVE_SS7)
05248 if (p->sig == SIG_SS7) {
05249 res = sig_ss7_call(p->sig_pvt, ast, rdest);
05250 ast_mutex_unlock(&p->lock);
05251 return res;
05252 }
05253 #endif
05254
05255
05256 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
05257 p->callwaitrings = 0;
05258 res = analog_call(p->sig_pvt, ast, rdest, timeout);
05259 ast_mutex_unlock(&p->lock);
05260 return res;
05261 }
05262
05263 mysig = p->outsigmod > -1 ? p->outsigmod : p->sig;
05264 switch (mysig) {
05265 case 0:
05266
05267 ast_setstate(ast, AST_STATE_UP);
05268 break;
05269 case SIG_MFCR2:
05270 break;
05271 default:
05272 ast_debug(1, "not yet implemented\n");
05273 ast_mutex_unlock(&p->lock);
05274 return -1;
05275 }
05276
05277 #ifdef HAVE_OPENR2
05278 if (p->mfcr2) {
05279 openr2_calling_party_category_t chancat;
05280 int callres = 0;
05281 char *c, *l;
05282
05283
05284 p->dialdest[0] = '\0';
05285
05286 c = strchr(dest, '/');
05287 if (c) {
05288 c++;
05289 } else {
05290 c = "";
05291 }
05292 if (!p->hidecallerid) {
05293 l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
05294 } else {
05295 l = NULL;
05296 }
05297 if (strlen(c) < p->stripmsd) {
05298 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
05299 ast_mutex_unlock(&p->lock);
05300 return -1;
05301 }
05302 p->dialing = 1;
05303 chancat = dahdi_r2_get_channel_category(ast);
05304 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
05305 if (-1 == callres) {
05306 ast_mutex_unlock(&p->lock);
05307 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
05308 return -1;
05309 }
05310 p->mfcr2_call_accepted = 0;
05311 p->mfcr2_progress = 0;
05312 ast_setstate(ast, AST_STATE_DIALING);
05313 }
05314 #endif
05315 ast_mutex_unlock(&p->lock);
05316 return 0;
05317 }
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334 static void dahdi_iflist_insert(struct dahdi_pvt *pvt)
05335 {
05336 struct dahdi_pvt *cur;
05337
05338 pvt->which_iflist = DAHDI_IFLIST_MAIN;
05339
05340
05341 for (cur = iflist; cur; cur = cur->next) {
05342 if (pvt->channel < cur->channel) {
05343
05344 pvt->prev = cur->prev;
05345 pvt->next = cur;
05346 if (cur->prev) {
05347
05348 cur->prev->next = pvt;
05349 } else {
05350
05351 iflist = pvt;
05352 }
05353 cur->prev = pvt;
05354 return;
05355 }
05356 }
05357
05358
05359 pvt->prev = ifend;
05360 pvt->next = NULL;
05361 if (ifend) {
05362 ifend->next = pvt;
05363 }
05364 ifend = pvt;
05365 if (!iflist) {
05366
05367 iflist = pvt;
05368 }
05369 }
05370
05371
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384 static void dahdi_iflist_extract(struct dahdi_pvt *pvt)
05385 {
05386
05387 if (pvt->prev) {
05388 pvt->prev->next = pvt->next;
05389 } else if (iflist == pvt) {
05390
05391 iflist = pvt->next;
05392 }
05393
05394
05395 if (pvt->next) {
05396 pvt->next->prev = pvt->prev;
05397 } else if (ifend == pvt) {
05398
05399 ifend = pvt->prev;
05400 }
05401
05402
05403 pvt->which_iflist = DAHDI_IFLIST_NONE;
05404 pvt->prev = NULL;
05405 pvt->next = NULL;
05406 }
05407
05408 #if defined(HAVE_PRI)
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418
05419
05420
05421
05422
05423
05424
05425 static void dahdi_nobch_insert(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05426 {
05427 struct dahdi_pvt *cur;
05428
05429 pvt->which_iflist = DAHDI_IFLIST_NO_B_CHAN;
05430
05431
05432 for (cur = pri->no_b_chan_iflist; cur; cur = cur->next) {
05433 if (pvt->channel < cur->channel) {
05434
05435 pvt->prev = cur->prev;
05436 pvt->next = cur;
05437 if (cur->prev) {
05438
05439 cur->prev->next = pvt;
05440 } else {
05441
05442 pri->no_b_chan_iflist = pvt;
05443 }
05444 cur->prev = pvt;
05445 return;
05446 }
05447 }
05448
05449
05450 pvt->prev = pri->no_b_chan_end;
05451 pvt->next = NULL;
05452 if (pri->no_b_chan_end) {
05453 ((struct dahdi_pvt *) pri->no_b_chan_end)->next = pvt;
05454 }
05455 pri->no_b_chan_end = pvt;
05456 if (!pri->no_b_chan_iflist) {
05457
05458 pri->no_b_chan_iflist = pvt;
05459 }
05460 }
05461 #endif
05462
05463 #if defined(HAVE_PRI)
05464
05465
05466
05467
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477
05478 static void dahdi_nobch_extract(struct sig_pri_span *pri, struct dahdi_pvt *pvt)
05479 {
05480
05481 if (pvt->prev) {
05482 pvt->prev->next = pvt->next;
05483 } else if (pri->no_b_chan_iflist == pvt) {
05484
05485 pri->no_b_chan_iflist = pvt->next;
05486 }
05487
05488
05489 if (pvt->next) {
05490 pvt->next->prev = pvt->prev;
05491 } else if (pri->no_b_chan_end == pvt) {
05492
05493 pri->no_b_chan_end = pvt->prev;
05494 }
05495
05496
05497 pvt->which_iflist = DAHDI_IFLIST_NONE;
05498 pvt->prev = NULL;
05499 pvt->next = NULL;
05500 }
05501 #endif
05502
05503 #if defined(HAVE_PRI)
05504
05505
05506
05507
05508
05509
05510
05511
05512
05513 static void dahdi_unlink_pri_pvt(struct dahdi_pvt *pvt)
05514 {
05515 unsigned idx;
05516 struct sig_pri_span *pri;
05517
05518 pri = pvt->pri;
05519 if (!pri) {
05520
05521 return;
05522 }
05523 ast_mutex_lock(&pri->lock);
05524 for (idx = 0; idx < pri->numchans; ++idx) {
05525 if (pri->pvts[idx] == pvt->sig_pvt) {
05526 pri->pvts[idx] = NULL;
05527 ast_mutex_unlock(&pri->lock);
05528 return;
05529 }
05530 }
05531 ast_mutex_unlock(&pri->lock);
05532 }
05533 #endif
05534
05535 #if defined(HAVE_SS7)
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545 static void dahdi_unlink_ss7_pvt(struct dahdi_pvt *pvt)
05546 {
05547 unsigned idx;
05548 struct sig_ss7_linkset *ss7;
05549
05550 ss7 = pvt->ss7;
05551 if (!ss7) {
05552
05553 return;
05554 }
05555 ast_mutex_lock(&ss7->lock);
05556 for (idx = 0; idx < ss7->numchans; ++idx) {
05557 if (ss7->pvts[idx] == pvt->sig_pvt) {
05558 ss7->pvts[idx] = NULL;
05559 ast_mutex_unlock(&ss7->lock);
05560 return;
05561 }
05562 }
05563 ast_mutex_unlock(&ss7->lock);
05564 }
05565 #endif
05566
05567 static struct dahdi_pvt *find_next_iface_in_span(struct dahdi_pvt *cur)
05568 {
05569 if (cur->next && cur->next->span == cur->span) {
05570 return cur->next;
05571 } else if (cur->prev && cur->prev->span == cur->span) {
05572 return cur->prev;
05573 }
05574
05575 return NULL;
05576 }
05577
05578 static void destroy_dahdi_pvt(struct dahdi_pvt *pvt)
05579 {
05580 struct dahdi_pvt *p = pvt;
05581
05582 if (p->manages_span_alarms) {
05583 struct dahdi_pvt *next = find_next_iface_in_span(p);
05584 if (next) {
05585 next->manages_span_alarms = 1;
05586 }
05587 }
05588
05589
05590 #if defined(HAVE_PRI)
05591 dahdi_unlink_pri_pvt(p);
05592 #endif
05593 #if defined(HAVE_SS7)
05594 dahdi_unlink_ss7_pvt(p);
05595 #endif
05596 switch (pvt->which_iflist) {
05597 case DAHDI_IFLIST_NONE:
05598 break;
05599 case DAHDI_IFLIST_MAIN:
05600 dahdi_iflist_extract(p);
05601 break;
05602 #if defined(HAVE_PRI)
05603 case DAHDI_IFLIST_NO_B_CHAN:
05604 if (p->pri) {
05605 dahdi_nobch_extract(p->pri, p);
05606 }
05607 break;
05608 #endif
05609 }
05610
05611 if (p->sig_pvt) {
05612 if (analog_lib_handles(p->sig, 0, 0)) {
05613 analog_delete(p->sig_pvt);
05614 }
05615 switch (p->sig) {
05616 #if defined(HAVE_PRI)
05617 case SIG_PRI_LIB_HANDLE_CASES:
05618 sig_pri_chan_delete(p->sig_pvt);
05619 break;
05620 #endif
05621 #if defined(HAVE_SS7)
05622 case SIG_SS7:
05623 sig_ss7_chan_delete(p->sig_pvt);
05624 break;
05625 #endif
05626 default:
05627 break;
05628 }
05629 }
05630 ast_free(p->cidspill);
05631 if (p->use_smdi)
05632 ast_smdi_interface_unref(p->smdi_iface);
05633 if (p->mwi_event_sub)
05634 ast_event_unsubscribe(p->mwi_event_sub);
05635 if (p->vars) {
05636 ast_variables_destroy(p->vars);
05637 }
05638 if (p->cc_params) {
05639 ast_cc_config_params_destroy(p->cc_params);
05640 }
05641 ast_mutex_destroy(&p->lock);
05642 dahdi_close_sub(p, SUB_REAL);
05643 if (p->owner)
05644 p->owner->tech_pvt = NULL;
05645 ast_free(p);
05646 }
05647
05648 static void destroy_channel(struct dahdi_pvt *cur, int now)
05649 {
05650 int i;
05651
05652 if (!now) {
05653
05654 if (cur->owner) {
05655 return;
05656 }
05657 for (i = 0; i < 3; i++) {
05658 if (cur->subs[i].owner) {
05659 return;
05660 }
05661 }
05662 }
05663 destroy_dahdi_pvt(cur);
05664 }
05665
05666 static void destroy_all_channels(void)
05667 {
05668 int chan;
05669 #if defined(HAVE_PRI)
05670 unsigned span;
05671 struct sig_pri_span *pri;
05672 #endif
05673 struct dahdi_pvt *p;
05674
05675 while (num_restart_pending) {
05676 usleep(1);
05677 }
05678
05679 ast_mutex_lock(&iflock);
05680
05681 while (iflist) {
05682 p = iflist;
05683
05684 chan = p->channel;
05685 #if defined(HAVE_PRI_SERVICE_MESSAGES)
05686 {
05687 char db_chan_name[20];
05688 char db_answer[5];
05689 char state;
05690 int why = -1;
05691
05692 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, chan);
05693 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
05694 sscanf(db_answer, "%1c:%30d", &state, &why);
05695 }
05696 if (!why) {
05697
05698 ast_db_del(db_chan_name, SRVST_DBKEY);
05699 }
05700 }
05701 #endif
05702
05703 destroy_dahdi_pvt(p);
05704 ast_verb(3, "Unregistered channel %d\n", chan);
05705 }
05706 ifcount = 0;
05707 ast_mutex_unlock(&iflock);
05708
05709 #if defined(HAVE_PRI)
05710
05711 for (span = 0; span < NUM_SPANS; ++span) {
05712 if (!pris[span].dchannels[0]) {
05713 break;
05714 }
05715 pri = &pris[span].pri;
05716 ast_mutex_lock(&pri->lock);
05717 while (pri->no_b_chan_iflist) {
05718 p = pri->no_b_chan_iflist;
05719
05720
05721 destroy_dahdi_pvt(p);
05722 }
05723 ast_mutex_unlock(&pri->lock);
05724 }
05725 #endif
05726 }
05727
05728 #if defined(HAVE_PRI)
05729 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
05730
05731 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
05732 {
05733
05734 struct dahdi_pvt *p;
05735
05736 if (ast_strlen_zero(digits)) {
05737 ast_debug(1, "No digit string sent to application!\n");
05738 return -1;
05739 }
05740
05741 p = (struct dahdi_pvt *)chan->tech_pvt;
05742
05743 if (!p) {
05744 ast_debug(1, "Unable to find technology private\n");
05745 return -1;
05746 }
05747
05748 pri_send_keypad_facility_exec(p->sig_pvt, digits);
05749
05750 return 0;
05751 }
05752 #endif
05753
05754 #if defined(HAVE_PRI)
05755 #if defined(HAVE_PRI_PROG_W_CAUSE)
05756 static char *dahdi_send_callrerouting_facility_app = "DAHDISendCallreroutingFacility";
05757
05758 static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, const char *data)
05759 {
05760
05761 struct dahdi_pvt *pvt;
05762 char *parse;
05763 int res = -1;
05764 AST_DECLARE_APP_ARGS(args,
05765 AST_APP_ARG(destination);
05766 AST_APP_ARG(original);
05767 AST_APP_ARG(reason);
05768 );
05769
05770 if (ast_strlen_zero(data)) {
05771 ast_log(LOG_DEBUG, "No data sent to application!\n");
05772 return -1;
05773 }
05774 if (chan->tech != &dahdi_tech) {
05775 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05776 return -1;
05777 }
05778 pvt = (struct dahdi_pvt *) chan->tech_pvt;
05779 if (!pvt) {
05780 ast_log(LOG_DEBUG, "Unable to find technology private\n");
05781 return -1;
05782 }
05783 switch (pvt->sig) {
05784 case SIG_PRI_LIB_HANDLE_CASES:
05785 break;
05786 default:
05787 ast_log(LOG_DEBUG, "callrerouting attempted on non-ISDN channel %s\n",
05788 chan->name);
05789 return -1;
05790 }
05791
05792 parse = ast_strdupa(data);
05793 AST_STANDARD_APP_ARGS(args, parse);
05794
05795 if (ast_strlen_zero(args.destination)) {
05796 ast_log(LOG_WARNING, "callrerouting facility requires at least destination number argument\n");
05797 return -1;
05798 }
05799
05800 if (ast_strlen_zero(args.original)) {
05801 ast_log(LOG_WARNING, "Callrerouting Facility without original called number argument\n");
05802 args.original = NULL;
05803 }
05804
05805 if (ast_strlen_zero(args.reason)) {
05806 ast_log(LOG_NOTICE, "Callrerouting Facility without diversion reason argument, defaulting to unknown\n");
05807 args.reason = NULL;
05808 }
05809
05810 pri_send_callrerouting_facility_exec(pvt->sig_pvt, chan->_state, args.destination,
05811 args.original, args.reason);
05812
05813 return res;
05814 }
05815 #endif
05816 #endif
05817
05818 #if defined(HAVE_OPENR2)
05819 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
05820
05821 static int dahdi_accept_r2_call_exec(struct ast_channel *chan, const char *data)
05822 {
05823
05824 openr2_call_mode_t accept_mode;
05825 int res, timeout, maxloops;
05826 struct ast_frame *f;
05827 struct dahdi_pvt *p;
05828 char *parse;
05829 AST_DECLARE_APP_ARGS(args,
05830 AST_APP_ARG(charge);
05831 );
05832
05833 if (ast_strlen_zero(data)) {
05834 ast_log(LOG_DEBUG, "No data sent to application!\n");
05835 return -1;
05836 }
05837
05838 if (chan->tech != &dahdi_tech) {
05839 ast_log(LOG_DEBUG, "Only DAHDI technology accepted!\n");
05840 return -1;
05841 }
05842
05843 p = (struct dahdi_pvt *)chan->tech_pvt;
05844 if (!p) {
05845 ast_log(LOG_DEBUG, "Unable to find technology private!\n");
05846 return -1;
05847 }
05848
05849 parse = ast_strdupa(data);
05850 AST_STANDARD_APP_ARGS(args, parse);
05851
05852 if (ast_strlen_zero(args.charge)) {
05853 ast_log(LOG_WARNING, "DAHDIAcceptR2Call requires 'yes' or 'no' for the charge parameter\n");
05854 return -1;
05855 }
05856
05857 ast_mutex_lock(&p->lock);
05858 if (!p->mfcr2 || !p->mfcr2call) {
05859 ast_mutex_unlock(&p->lock);
05860 ast_log(LOG_DEBUG, "Channel %s does not seems to be an R2 active channel!\n", chan->name);
05861 return -1;
05862 }
05863
05864 if (p->mfcr2_call_accepted) {
05865 ast_mutex_unlock(&p->lock);
05866 ast_log(LOG_DEBUG, "MFC/R2 call already accepted on channel %s!\n", chan->name);
05867 return 0;
05868 }
05869 accept_mode = ast_true(args.charge) ? OR2_CALL_WITH_CHARGE : OR2_CALL_NO_CHARGE;
05870 if (openr2_chan_accept_call(p->r2chan, accept_mode)) {
05871 ast_mutex_unlock(&p->lock);
05872 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05873 return -1;
05874 }
05875 ast_mutex_unlock(&p->lock);
05876
05877 res = 0;
05878 timeout = 100;
05879 maxloops = 50;
05880
05881 while (maxloops > 0) {
05882 maxloops--;
05883 if (ast_check_hangup(chan)) {
05884 break;
05885 }
05886 res = ast_waitfor(chan, timeout);
05887 if (res < 0) {
05888 ast_log(LOG_DEBUG, "ast_waitfor failed on channel %s, going out ...\n", chan->name);
05889 res = -1;
05890 break;
05891 }
05892 if (res == 0) {
05893 continue;
05894 }
05895 f = ast_read(chan);
05896 if (!f) {
05897 ast_log(LOG_DEBUG, "No frame read on channel %s, going out ...\n", chan->name);
05898 res = -1;
05899 break;
05900 }
05901 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_HANGUP) {
05902 ast_log(LOG_DEBUG, "Got HANGUP frame on channel %s, going out ...\n", chan->name);
05903 ast_frfree(f);
05904 res = -1;
05905 break;
05906 }
05907 ast_frfree(f);
05908 ast_mutex_lock(&p->lock);
05909 if (p->mfcr2_call_accepted) {
05910 ast_mutex_unlock(&p->lock);
05911 ast_log(LOG_DEBUG, "Accepted MFC/R2 call!\n");
05912 break;
05913 }
05914 ast_mutex_unlock(&p->lock);
05915 }
05916 if (res == -1) {
05917 ast_log(LOG_WARNING, "Failed to accept MFC/R2 call!\n");
05918 }
05919 return res;
05920 }
05921
05922 static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
05923 {
05924 openr2_call_disconnect_cause_t r2cause = OR2_CAUSE_NORMAL_CLEARING;
05925 switch (cause) {
05926 case AST_CAUSE_USER_BUSY:
05927 case AST_CAUSE_CALL_REJECTED:
05928 case AST_CAUSE_INTERWORKING:
05929 r2cause = OR2_CAUSE_BUSY_NUMBER;
05930 break;
05931
05932 case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05933 case AST_CAUSE_SWITCH_CONGESTION:
05934 r2cause = OR2_CAUSE_NETWORK_CONGESTION;
05935 break;
05936
05937 case AST_CAUSE_UNALLOCATED:
05938 r2cause = OR2_CAUSE_UNALLOCATED_NUMBER;
05939 break;
05940
05941 case AST_CAUSE_NETWORK_OUT_OF_ORDER:
05942 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
05943 r2cause = OR2_CAUSE_OUT_OF_ORDER;
05944 break;
05945
05946 case AST_CAUSE_NO_ANSWER:
05947 case AST_CAUSE_NO_USER_RESPONSE:
05948 r2cause = OR2_CAUSE_NO_ANSWER;
05949 break;
05950
05951 default:
05952 r2cause = OR2_CAUSE_NORMAL_CLEARING;
05953 break;
05954 }
05955 ast_log(LOG_DEBUG, "ast cause %d resulted in openr2 cause %d/%s\n",
05956 cause, r2cause, openr2_proto_get_disconnect_string(r2cause));
05957 return r2cause;
05958 }
05959 #endif
05960
05961 static int revert_fax_buffers(struct dahdi_pvt *p, struct ast_channel *ast)
05962 {
05963 if (p->bufferoverrideinuse) {
05964
05965 struct dahdi_bufferinfo bi = {
05966 .txbufpolicy = p->buf_policy,
05967 .rxbufpolicy = p->buf_policy,
05968 .bufsize = p->bufsize,
05969 .numbufs = p->buf_no
05970 };
05971 int bpres;
05972
05973 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05974 ast_log(LOG_WARNING, "Channel '%s' unable to revert buffer policy: %s\n", ast->name, strerror(errno));
05975 }
05976 p->bufferoverrideinuse = 0;
05977 return bpres;
05978 }
05979
05980 return -1;
05981 }
05982
05983 static int dahdi_hangup(struct ast_channel *ast)
05984 {
05985 int res = 0;
05986 int idx,x;
05987 int law;
05988
05989 struct dahdi_pvt *p = ast->tech_pvt;
05990 struct dahdi_params par;
05991
05992 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
05993 if (!ast->tech_pvt) {
05994 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
05995 return 0;
05996 }
05997
05998 ast_mutex_lock(&p->lock);
05999 p->exten[0] = '\0';
06000 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06001 dahdi_confmute(p, 0);
06002 restore_gains(p);
06003 p->ignoredtmf = 0;
06004 p->waitingfordt.tv_sec = 0;
06005
06006 res = analog_hangup(p->sig_pvt, ast);
06007 revert_fax_buffers(p, ast);
06008
06009 goto hangup_out;
06010 } else {
06011 p->cid_num[0] = '\0';
06012 p->cid_name[0] = '\0';
06013 p->cid_subaddr[0] = '\0';
06014 }
06015
06016 #ifdef HAVE_PRI
06017 if (dahdi_sig_pri_lib_handles(p->sig)) {
06018 x = 1;
06019 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06020 dahdi_confmute(p, 0);
06021 p->muting = 0;
06022 restore_gains(p);
06023 if (p->dsp) {
06024 ast_dsp_free(p->dsp);
06025 p->dsp = NULL;
06026 }
06027 p->ignoredtmf = 0;
06028 revert_fax_buffers(p, ast);
06029 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06030 p->law = p->law_default;
06031 law = p->law_default;
06032 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06033 dahdi_disable_ec(p);
06034 update_conf(p);
06035 reset_conf(p);
06036 sig_pri_hangup(p->sig_pvt, ast);
06037 p->subs[SUB_REAL].owner = NULL;
06038 p->subs[SUB_REAL].needbusy = 0;
06039 p->owner = NULL;
06040 p->cid_tag[0] = '\0';
06041 p->ringt = 0;
06042 p->distinctivering = 0;
06043 p->confirmanswer = 0;
06044 p->outgoing = 0;
06045 p->digital = 0;
06046 p->faxhandled = 0;
06047 p->pulsedial = 0;
06048 goto hangup_out;
06049 }
06050 #endif
06051
06052 #if defined(HAVE_SS7)
06053 if (p->sig == SIG_SS7) {
06054 x = 1;
06055 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06056
06057 dahdi_confmute(p, 0);
06058 p->muting = 0;
06059 restore_gains(p);
06060 if (p->dsp) {
06061 ast_dsp_free(p->dsp);
06062 p->dsp = NULL;
06063 }
06064 p->ignoredtmf = 0;
06065
06066
06067 p->subs[SUB_REAL].owner = NULL;
06068 p->subs[SUB_REAL].needbusy = 0;
06069 p->polarity = POLARITY_IDLE;
06070 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
06071
06072 p->owner = NULL;
06073 p->ringt = 0;
06074 p->distinctivering = 0;
06075 p->confirmanswer = 0;
06076 p->outgoing = 0;
06077 p->digital = 0;
06078 p->faxhandled = 0;
06079 p->pulsedial = 0;
06080
06081 revert_fax_buffers(p, ast);
06082
06083 p->law = p->law_default;
06084 law = p->law_default;
06085 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06086 if (res < 0)
06087 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06088
06089 sig_ss7_hangup(p->sig_pvt, ast);
06090
06091 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06092 dahdi_disable_ec(p);
06093 x = 0;
06094 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06095 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06096 p->didtdd = 0;
06097 update_conf(p);
06098 reset_conf(p);
06099
06100
06101 x = 0;
06102 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06103
06104 if (num_restart_pending == 0)
06105 restart_monitor();
06106
06107 ast->tech_pvt = NULL;
06108 goto hangup_out;
06109 }
06110 #endif
06111
06112 idx = dahdi_get_index(ast, p, 1);
06113
06114 dahdi_confmute(p, 0);
06115 p->muting = 0;
06116 restore_gains(p);
06117 if (p->origcid_num) {
06118 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
06119 ast_free(p->origcid_num);
06120 p->origcid_num = NULL;
06121 }
06122 if (p->origcid_name) {
06123 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
06124 ast_free(p->origcid_name);
06125 p->origcid_name = NULL;
06126 }
06127 if (p->dsp)
06128 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06129
06130 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
06131 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06132 p->ignoredtmf = 0;
06133
06134 if (idx > -1) {
06135
06136 p->subs[idx].owner = NULL;
06137 p->subs[idx].needanswer = 0;
06138 p->subs[idx].needflash = 0;
06139 p->subs[idx].needringing = 0;
06140 p->subs[idx].needbusy = 0;
06141 p->subs[idx].needcongestion = 0;
06142 p->subs[idx].linear = 0;
06143 p->polarity = POLARITY_IDLE;
06144 dahdi_setlinear(p->subs[idx].dfd, 0);
06145 if (idx == SUB_REAL) {
06146 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
06147 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
06148 if (p->subs[SUB_CALLWAIT].inthreeway) {
06149
06150 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
06151
06152 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06153 unalloc_sub(p, SUB_CALLWAIT);
06154 p->owner = NULL;
06155 } else {
06156
06157 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
06158 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06159 unalloc_sub(p, SUB_THREEWAY);
06160 if (p->subs[SUB_REAL].inthreeway) {
06161
06162
06163 ast_debug(1, "Call was complete, setting owner to former third call\n");
06164 p->owner = p->subs[SUB_REAL].owner;
06165 } else {
06166
06167 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06168 p->owner = NULL;
06169 }
06170 p->subs[SUB_REAL].inthreeway = 0;
06171 }
06172 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
06173
06174 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
06175 unalloc_sub(p, SUB_CALLWAIT);
06176 p->owner = p->subs[SUB_REAL].owner;
06177 if (p->owner->_state != AST_STATE_UP)
06178 p->subs[SUB_REAL].needanswer = 1;
06179 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06180 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06181 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
06182 swap_subs(p, SUB_THREEWAY, SUB_REAL);
06183 unalloc_sub(p, SUB_THREEWAY);
06184 if (p->subs[SUB_REAL].inthreeway) {
06185
06186
06187 ast_debug(1, "Call was complete, setting owner to former third call\n");
06188 p->owner = p->subs[SUB_REAL].owner;
06189 } else {
06190
06191 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
06192 p->owner = NULL;
06193 }
06194 p->subs[SUB_REAL].inthreeway = 0;
06195 }
06196 } else if (idx == SUB_CALLWAIT) {
06197
06198 if (p->subs[SUB_CALLWAIT].inthreeway) {
06199
06200
06201 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06202 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06203 S_OR(p->mohsuggest, NULL),
06204 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06205 }
06206 p->subs[SUB_THREEWAY].inthreeway = 0;
06207
06208 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06209 unalloc_sub(p, SUB_THREEWAY);
06210 } else
06211 unalloc_sub(p, SUB_CALLWAIT);
06212 } else if (idx == SUB_THREEWAY) {
06213 if (p->subs[SUB_CALLWAIT].inthreeway) {
06214
06215
06216 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06217 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06218 S_OR(p->mohsuggest, NULL),
06219 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06220 }
06221 p->subs[SUB_CALLWAIT].inthreeway = 0;
06222 }
06223 p->subs[SUB_REAL].inthreeway = 0;
06224
06225
06226 unalloc_sub(p, SUB_THREEWAY);
06227 } else {
06228
06229 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
06230 }
06231 }
06232
06233 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
06234 p->owner = NULL;
06235 p->ringt = 0;
06236 p->distinctivering = 0;
06237 p->confirmanswer = 0;
06238 p->outgoing = 0;
06239 p->digital = 0;
06240 p->faxhandled = 0;
06241 p->pulsedial = 0;
06242 if (p->dsp) {
06243 ast_dsp_free(p->dsp);
06244 p->dsp = NULL;
06245 }
06246
06247 revert_fax_buffers(p, ast);
06248
06249 p->law = p->law_default;
06250 law = p->law_default;
06251 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
06252 if (res < 0)
06253 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
06254
06255 #ifdef HAVE_OPENR2
06256 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
06257 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
06258
06259 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
06260 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
06261 } else {
06262 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
06263 int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
06264 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
06265 : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
06266 dahdi_r2_disconnect_call(p, r2cause);
06267 }
06268 } else if (p->mfcr2call) {
06269 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
06270
06271
06272
06273
06274 p->mfcr2call = 0;
06275 }
06276 #endif
06277 switch (p->sig) {
06278 case SIG_SS7:
06279 case SIG_MFCR2:
06280 case SIG_PRI_LIB_HANDLE_CASES:
06281 case 0:
06282 break;
06283 default:
06284 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06285 break;
06286 }
06287 if (res < 0) {
06288 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
06289 }
06290 switch (p->sig) {
06291 case SIG_FXOGS:
06292 case SIG_FXOLS:
06293 case SIG_FXOKS:
06294 memset(&par, 0, sizeof(par));
06295 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
06296 if (!res) {
06297 struct analog_pvt *analog_p = p->sig_pvt;
06298 #if 0
06299 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
06300 #endif
06301
06302 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
06303 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06304 else
06305 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06306 analog_p->fxsoffhookstate = par.rxisoffhook;
06307 }
06308 break;
06309 case SIG_FXSGS:
06310 case SIG_FXSLS:
06311 case SIG_FXSKS:
06312
06313
06314 if (ast->_state != AST_STATE_RESERVED) {
06315 time(&p->guardtime);
06316 p->guardtime += 2;
06317 }
06318 break;
06319 default:
06320 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06321 }
06322 if (p->sig)
06323 dahdi_disable_ec(p);
06324 x = 0;
06325 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
06326 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
06327 p->didtdd = 0;
06328 p->callwaitcas = 0;
06329 p->callwaiting = p->permcallwaiting;
06330 p->hidecallerid = p->permhidecallerid;
06331 p->waitingfordt.tv_sec = 0;
06332 p->dialing = 0;
06333 p->rdnis[0] = '\0';
06334 update_conf(p);
06335 reset_conf(p);
06336
06337 switch (p->sig) {
06338 case SIG_PRI_LIB_HANDLE_CASES:
06339 case SIG_SS7:
06340 x = 0;
06341 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
06342 break;
06343 default:
06344 break;
06345 }
06346 if (num_restart_pending == 0)
06347 restart_monitor();
06348 }
06349
06350 p->callwaitingrepeat = 0;
06351 p->cidcwexpire = 0;
06352 p->cid_suppress_expire = 0;
06353 p->oprmode = 0;
06354 ast->tech_pvt = NULL;
06355 hangup_out:
06356 ast_free(p->cidspill);
06357 p->cidspill = NULL;
06358
06359 ast_mutex_unlock(&p->lock);
06360 ast_module_unref(ast_module_info->self);
06361 ast_verb(3, "Hungup '%s'\n", ast->name);
06362
06363 ast_mutex_lock(&iflock);
06364
06365 if (p->restartpending) {
06366 num_restart_pending--;
06367 }
06368
06369 if (p->destroy) {
06370 destroy_channel(p, 0);
06371 }
06372 ast_mutex_unlock(&iflock);
06373 return 0;
06374 }
06375
06376 static int dahdi_answer(struct ast_channel *ast)
06377 {
06378 struct dahdi_pvt *p = ast->tech_pvt;
06379 int res = 0;
06380 int idx;
06381 ast_setstate(ast, AST_STATE_UP);
06382 ast_mutex_lock(&p->lock);
06383 idx = dahdi_get_index(ast, p, 0);
06384 if (idx < 0)
06385 idx = SUB_REAL;
06386
06387 if ((p->radio || (p->oprmode < 0))) {
06388 ast_mutex_unlock(&p->lock);
06389 return 0;
06390 }
06391
06392 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
06393 res = analog_answer(p->sig_pvt, ast);
06394 ast_mutex_unlock(&p->lock);
06395 return res;
06396 }
06397
06398 switch (p->sig) {
06399 #if defined(HAVE_PRI)
06400 case SIG_PRI_LIB_HANDLE_CASES:
06401 res = sig_pri_answer(p->sig_pvt, ast);
06402 break;
06403 #endif
06404 #if defined(HAVE_SS7)
06405 case SIG_SS7:
06406 res = sig_ss7_answer(p->sig_pvt, ast);
06407 break;
06408 #endif
06409 #ifdef HAVE_OPENR2
06410 case SIG_MFCR2:
06411 if (!p->mfcr2_call_accepted) {
06412
06413
06414 p->mfcr2_answer_pending = 1;
06415 if (p->mfcr2_charge_calls) {
06416 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
06417 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
06418 } else {
06419 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
06420 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
06421 }
06422 } else {
06423 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
06424 dahdi_r2_answer(p);
06425 }
06426 break;
06427 #endif
06428 case 0:
06429 ast_mutex_unlock(&p->lock);
06430 return 0;
06431 default:
06432 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
06433 res = -1;
06434 break;
06435 }
06436 ast_mutex_unlock(&p->lock);
06437 return res;
06438 }
06439
06440 static void disable_dtmf_detect(struct dahdi_pvt *p)
06441 {
06442 int val = 0;
06443
06444 p->ignoredtmf = 1;
06445
06446 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06447
06448 if (!p->hardwaredtmf && p->dsp) {
06449 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
06450 ast_dsp_set_features(p->dsp, p->dsp_features);
06451 }
06452 }
06453
06454 static void enable_dtmf_detect(struct dahdi_pvt *p)
06455 {
06456 int val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06457
06458 if (p->channel == CHAN_PSEUDO)
06459 return;
06460
06461 p->ignoredtmf = 0;
06462
06463 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
06464
06465 if (!p->hardwaredtmf && p->dsp) {
06466 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
06467 ast_dsp_set_features(p->dsp, p->dsp_features);
06468 }
06469 }
06470
06471 static int dahdi_queryoption(struct ast_channel *chan, int option, void *data, int *datalen)
06472 {
06473 char *cp;
06474 struct dahdi_pvt *p = chan->tech_pvt;
06475
06476
06477 if (!data || (*datalen < 1)) {
06478 errno = EINVAL;
06479 return -1;
06480 }
06481
06482 switch (option) {
06483 case AST_OPTION_DIGIT_DETECT:
06484 cp = (char *) data;
06485 *cp = p->ignoredtmf ? 0 : 1;
06486 ast_debug(1, "Reporting digit detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06487 break;
06488 case AST_OPTION_FAX_DETECT:
06489 cp = (char *) data;
06490 *cp = (p->dsp_features & DSP_FEATURE_FAX_DETECT) ? 0 : 1;
06491 ast_debug(1, "Reporting fax tone detection %sabled on %s\n", *cp ? "en" : "dis", chan->name);
06492 break;
06493 case AST_OPTION_CC_AGENT_TYPE:
06494 #if defined(HAVE_PRI)
06495 #if defined(HAVE_PRI_CCSS)
06496 if (dahdi_sig_pri_lib_handles(p->sig)) {
06497 ast_copy_string((char *) data, dahdi_pri_cc_type, *datalen);
06498 break;
06499 }
06500 #endif
06501 #endif
06502 return -1;
06503 default:
06504 return -1;
06505 }
06506
06507 errno = 0;
06508
06509 return 0;
06510 }
06511
06512 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
06513 {
06514 char *cp;
06515 signed char *scp;
06516 int x;
06517 int idx;
06518 struct dahdi_pvt *p = chan->tech_pvt, *pp;
06519 struct oprmode *oprmode;
06520
06521
06522
06523 if (!data || (datalen < 1)) {
06524 errno = EINVAL;
06525 return -1;
06526 }
06527
06528 switch (option) {
06529 case AST_OPTION_TXGAIN:
06530 scp = (signed char *) data;
06531 idx = dahdi_get_index(chan, p, 0);
06532 if (idx < 0) {
06533 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
06534 return -1;
06535 }
06536 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
06537 return set_actual_txgain(p->subs[idx].dfd, p->txgain + (float) *scp, p->txdrc, p->law);
06538 case AST_OPTION_RXGAIN:
06539 scp = (signed char *) data;
06540 idx = dahdi_get_index(chan, p, 0);
06541 if (idx < 0) {
06542 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
06543 return -1;
06544 }
06545 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
06546 return set_actual_rxgain(p->subs[idx].dfd, p->rxgain + (float) *scp, p->rxdrc, p->law);
06547 case AST_OPTION_TONE_VERIFY:
06548 if (!p->dsp)
06549 break;
06550 cp = (char *) data;
06551 switch (*cp) {
06552 case 1:
06553 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
06554 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);
06555 break;
06556 case 2:
06557 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
06558 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);
06559 break;
06560 default:
06561 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
06562 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06563 break;
06564 }
06565 break;
06566 case AST_OPTION_TDD:
06567
06568 cp = (char *) data;
06569 p->mate = 0;
06570 if (!*cp) {
06571 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
06572 if (p->tdd)
06573 tdd_free(p->tdd);
06574 p->tdd = 0;
06575 break;
06576 }
06577 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
06578 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
06579 dahdi_disable_ec(p);
06580
06581 if (!p->didtdd) {
06582 unsigned char mybuf[41000];
06583 unsigned char *buf;
06584 int size, res, fd, len;
06585 struct pollfd fds[1];
06586
06587 buf = mybuf;
06588 memset(buf, 0x7f, sizeof(mybuf));
06589 ast_tdd_gen_ecdisa(buf + 16000, 16000);
06590 len = 40000;
06591 idx = dahdi_get_index(chan, p, 0);
06592 if (idx < 0) {
06593 ast_log(LOG_WARNING, "No index in TDD?\n");
06594 return -1;
06595 }
06596 fd = p->subs[idx].dfd;
06597 while (len) {
06598 if (ast_check_hangup(chan))
06599 return -1;
06600 size = len;
06601 if (size > READ_SIZE)
06602 size = READ_SIZE;
06603 fds[0].fd = fd;
06604 fds[0].events = POLLPRI | POLLOUT;
06605 fds[0].revents = 0;
06606 res = poll(fds, 1, -1);
06607 if (!res) {
06608 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
06609 continue;
06610 }
06611
06612 if (fds[0].revents & POLLPRI)
06613 return -1;
06614 if (!(fds[0].revents & POLLOUT)) {
06615 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
06616 continue;
06617 }
06618 res = write(fd, buf, size);
06619 if (res != size) {
06620 if (res == -1) return -1;
06621 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
06622 break;
06623 }
06624 len -= size;
06625 buf += size;
06626 }
06627 p->didtdd = 1;
06628 }
06629 if (*cp == 2) {
06630 if (p->tdd)
06631 tdd_free(p->tdd);
06632 p->tdd = 0;
06633 p->mate = 1;
06634 break;
06635 }
06636 if (!p->tdd) {
06637 p->tdd = tdd_new();
06638 }
06639 break;
06640 case AST_OPTION_RELAXDTMF:
06641 if (!p->dsp)
06642 break;
06643 cp = (char *) data;
06644 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
06645 *cp ? "ON" : "OFF", (int) *cp, chan->name);
06646 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
06647 break;
06648 case AST_OPTION_AUDIO_MODE:
06649 #if defined(HAVE_PRI)
06650 if (dahdi_sig_pri_lib_handles(p->sig)
06651 && ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel) {
06652
06653 break;
06654 }
06655 #endif
06656
06657 cp = (char *) data;
06658 if (!*cp) {
06659 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
06660 x = 0;
06661 dahdi_disable_ec(p);
06662 } else {
06663 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
06664 x = 1;
06665 }
06666 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
06667 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
06668 break;
06669 case AST_OPTION_OPRMODE:
06670 oprmode = (struct oprmode *) data;
06671
06672 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
06673 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
06674 chan->tech->type, oprmode->peer->tech->type);
06675 errno = EINVAL;
06676 return -1;
06677 }
06678 pp = oprmode->peer->tech_pvt;
06679 p->oprmode = pp->oprmode = 0;
06680
06681 p->oprpeer = pp;
06682 pp->oprpeer = p;
06683
06684 if (oprmode->mode)
06685 {
06686 pp->oprmode = oprmode->mode;
06687 p->oprmode = -oprmode->mode;
06688 }
06689 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
06690 oprmode->mode, chan->name,oprmode->peer->name);
06691 break;
06692 case AST_OPTION_ECHOCAN:
06693 cp = (char *) data;
06694 if (*cp) {
06695 ast_debug(1, "Enabling echo cancellation on %s\n", chan->name);
06696 dahdi_enable_ec(p);
06697 } else {
06698 ast_debug(1, "Disabling echo cancellation on %s\n", chan->name);
06699 dahdi_disable_ec(p);
06700 }
06701 break;
06702 case AST_OPTION_DIGIT_DETECT:
06703 cp = (char *) data;
06704 ast_debug(1, "%sabling digit detection on %s\n", *cp ? "En" : "Dis", chan->name);
06705 if (*cp) {
06706 enable_dtmf_detect(p);
06707 } else {
06708 disable_dtmf_detect(p);
06709 }
06710 break;
06711 case AST_OPTION_FAX_DETECT:
06712 cp = (char *) data;
06713 if (p->dsp) {
06714 ast_debug(1, "%sabling fax tone detection on %s\n", *cp ? "En" : "Dis", chan->name);
06715 if (*cp) {
06716 p->dsp_features |= DSP_FEATURE_FAX_DETECT;
06717 } else {
06718 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
06719 }
06720 ast_dsp_set_features(p->dsp, p->dsp_features);
06721 }
06722 break;
06723 default:
06724 return -1;
06725 }
06726 errno = 0;
06727
06728 return 0;
06729 }
06730
06731 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
06732 {
06733 struct dahdi_pvt *p = chan->tech_pvt;
06734 int res = 0;
06735
06736 if (!strcasecmp(data, "rxgain")) {
06737 ast_mutex_lock(&p->lock);
06738 snprintf(buf, len, "%f", p->rxgain);
06739 ast_mutex_unlock(&p->lock);
06740 } else if (!strcasecmp(data, "txgain")) {
06741 ast_mutex_lock(&p->lock);
06742 snprintf(buf, len, "%f", p->txgain);
06743 ast_mutex_unlock(&p->lock);
06744 #if defined(HAVE_PRI)
06745 #if defined(HAVE_PRI_REVERSE_CHARGE)
06746 } else if (!strcasecmp(data, "reversecharge")) {
06747 ast_mutex_lock(&p->lock);
06748 switch (p->sig) {
06749 case SIG_PRI_LIB_HANDLE_CASES:
06750 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->reverse_charging_indication);
06751 break;
06752 default:
06753 *buf = '\0';
06754 res = -1;
06755 break;
06756 }
06757 ast_mutex_unlock(&p->lock);
06758 #endif
06759 #if defined(HAVE_PRI_SETUP_KEYPAD)
06760 } else if (!strcasecmp(data, "keypad_digits")) {
06761 ast_mutex_lock(&p->lock);
06762 switch (p->sig) {
06763 case SIG_PRI_LIB_HANDLE_CASES:
06764 ast_copy_string(buf, ((struct sig_pri_chan *) p->sig_pvt)->keypad_digits,
06765 len);
06766 break;
06767 default:
06768 *buf = '\0';
06769 res = -1;
06770 break;
06771 }
06772 ast_mutex_unlock(&p->lock);
06773 #endif
06774 } else if (!strcasecmp(data, "no_media_path")) {
06775 ast_mutex_lock(&p->lock);
06776 switch (p->sig) {
06777 case SIG_PRI_LIB_HANDLE_CASES:
06778
06779
06780
06781
06782 snprintf(buf, len, "%d", ((struct sig_pri_chan *) p->sig_pvt)->no_b_channel);
06783 break;
06784 default:
06785 *buf = '\0';
06786 res = -1;
06787 break;
06788 }
06789 ast_mutex_unlock(&p->lock);
06790 #endif
06791 } else {
06792 *buf = '\0';
06793 res = -1;
06794 }
06795
06796 return res;
06797 }
06798
06799
06800 static int parse_buffers_policy(const char *parse, int *num_buffers, int *policy)
06801 {
06802 int res;
06803 char policy_str[21] = "";
06804
06805 if ((res = sscanf(parse, "%30d,%20s", num_buffers, policy_str)) != 2) {
06806 ast_log(LOG_WARNING, "Parsing buffer string '%s' failed.\n", parse);
06807 return 1;
06808 }
06809 if (*num_buffers < 0) {
06810 ast_log(LOG_WARNING, "Invalid buffer count given '%d'.\n", *num_buffers);
06811 return -1;
06812 }
06813 if (!strcasecmp(policy_str, "full")) {
06814 *policy = DAHDI_POLICY_WHEN_FULL;
06815 } else if (!strcasecmp(policy_str, "immediate")) {
06816 *policy = DAHDI_POLICY_IMMEDIATE;
06817 #if defined(HAVE_DAHDI_HALF_FULL)
06818 } else if (!strcasecmp(policy_str, "half")) {
06819 *policy = DAHDI_POLICY_HALF_FULL;
06820 #endif
06821 } else {
06822 ast_log(LOG_WARNING, "Invalid policy name given '%s'.\n", policy_str);
06823 return -1;
06824 }
06825
06826 return 0;
06827 }
06828
06829 static int dahdi_func_write(struct ast_channel *chan, const char *function, char *data, const char *value)
06830 {
06831 struct dahdi_pvt *p = chan->tech_pvt;
06832 int res = 0;
06833
06834 if (!strcasecmp(data, "buffers")) {
06835 int num_bufs, policy;
06836
06837 if (!(parse_buffers_policy(value, &num_bufs, &policy))) {
06838 struct dahdi_bufferinfo bi = {
06839 .txbufpolicy = policy,
06840 .rxbufpolicy = policy,
06841 .bufsize = p->bufsize,
06842 .numbufs = num_bufs,
06843 };
06844 int bpres;
06845
06846 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
06847 ast_log(LOG_WARNING, "Channel '%d' unable to override buffer policy: %s\n", p->channel, strerror(errno));
06848 } else {
06849 p->bufferoverrideinuse = 1;
06850 }
06851 } else {
06852 res = -1;
06853 }
06854 } else if (!strcasecmp(data, "echocan_mode")) {
06855 if (!strcasecmp(value, "on")) {
06856 ast_mutex_lock(&p->lock);
06857 dahdi_enable_ec(p);
06858 ast_mutex_unlock(&p->lock);
06859 } else if (!strcasecmp(value, "off")) {
06860 ast_mutex_lock(&p->lock);
06861 dahdi_disable_ec(p);
06862 ast_mutex_unlock(&p->lock);
06863 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
06864 } else if (!strcasecmp(value, "fax")) {
06865 int blah = 1;
06866
06867 ast_mutex_lock(&p->lock);
06868 if (!p->echocanon) {
06869 dahdi_enable_ec(p);
06870 }
06871 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06872 ast_log(LOG_WARNING, "Unable to place echocan into fax mode on channel %d: %s\n", p->channel, strerror(errno));
06873 }
06874 ast_mutex_unlock(&p->lock);
06875 } else if (!strcasecmp(value, "voice")) {
06876 int blah = 0;
06877
06878 ast_mutex_lock(&p->lock);
06879 if (!p->echocanon) {
06880 dahdi_enable_ec(p);
06881 }
06882 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_FAX_MODE, &blah)) {
06883 ast_log(LOG_WARNING, "Unable to place echocan into voice mode on channel %d: %s\n", p->channel, strerror(errno));
06884 }
06885 ast_mutex_unlock(&p->lock);
06886 #endif
06887 } else {
06888 ast_log(LOG_WARNING, "Unsupported value '%s' provided for '%s' item.\n", value, data);
06889 res = -1;
06890 }
06891 } else {
06892 res = -1;
06893 }
06894
06895 return res;
06896 }
06897
06898 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
06899 {
06900
06901 int x;
06902 int hasslaves;
06903 if (!master)
06904 return;
06905 if (needlock) {
06906 ast_mutex_lock(&master->lock);
06907 if (slave) {
06908 while (ast_mutex_trylock(&slave->lock)) {
06909 DEADLOCK_AVOIDANCE(&master->lock);
06910 }
06911 }
06912 }
06913 hasslaves = 0;
06914 for (x = 0; x < MAX_SLAVES; x++) {
06915 if (master->slaves[x]) {
06916 if (!slave || (master->slaves[x] == slave)) {
06917
06918 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
06919 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
06920 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
06921 master->slaves[x]->master = NULL;
06922 master->slaves[x] = NULL;
06923 } else
06924 hasslaves = 1;
06925 }
06926 if (!hasslaves)
06927 master->inconference = 0;
06928 }
06929 if (!slave) {
06930 if (master->master) {
06931
06932 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
06933 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
06934 hasslaves = 0;
06935 for (x = 0; x < MAX_SLAVES; x++) {
06936 if (master->master->slaves[x] == master)
06937 master->master->slaves[x] = NULL;
06938 else if (master->master->slaves[x])
06939 hasslaves = 1;
06940 }
06941 if (!hasslaves)
06942 master->master->inconference = 0;
06943 }
06944 master->master = NULL;
06945 }
06946 update_conf(master);
06947 if (needlock) {
06948 if (slave)
06949 ast_mutex_unlock(&slave->lock);
06950 ast_mutex_unlock(&master->lock);
06951 }
06952 }
06953
06954 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
06955 int x;
06956 if (!slave || !master) {
06957 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
06958 return;
06959 }
06960 for (x = 0; x < MAX_SLAVES; x++) {
06961 if (!master->slaves[x]) {
06962 master->slaves[x] = slave;
06963 break;
06964 }
06965 }
06966 if (x >= MAX_SLAVES) {
06967 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
06968 master->slaves[MAX_SLAVES - 1] = slave;
06969 }
06970 if (slave->master)
06971 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
06972 slave->master = master;
06973
06974 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
06975 }
06976
06977 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)
06978 {
06979 struct ast_channel *who;
06980 struct dahdi_pvt *p0, *p1, *op0, *op1;
06981 struct dahdi_pvt *master = NULL, *slave = NULL;
06982 struct ast_frame *f;
06983 int inconf = 0;
06984 int nothingok = 1;
06985 int ofd0, ofd1;
06986 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
06987 int os0 = -1, os1 = -1;
06988 int priority = 0;
06989 struct ast_channel *oc0, *oc1;
06990 enum ast_bridge_result res;
06991 #ifdef PRI_2BCT
06992 int triedtopribridge = 0;
06993 q931_call *q931c0;
06994 q931_call *q931c1;
06995 #endif
06996
06997
06998
06999
07000
07001
07002 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
07003 return AST_BRIDGE_FAILED_NOWARN;
07004
07005 ast_channel_lock(c0);
07006 while (ast_channel_trylock(c1)) {
07007 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07008 }
07009
07010 p0 = c0->tech_pvt;
07011 p1 = c1->tech_pvt;
07012
07013 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
07014 ast_channel_unlock(c0);
07015 ast_channel_unlock(c1);
07016 return AST_BRIDGE_FAILED_NOWARN;
07017 }
07018
07019 oi0 = dahdi_get_index(c0, p0, 0);
07020 oi1 = dahdi_get_index(c1, p1, 0);
07021 if ((oi0 < 0) || (oi1 < 0)) {
07022 ast_channel_unlock(c0);
07023 ast_channel_unlock(c1);
07024 return AST_BRIDGE_FAILED;
07025 }
07026
07027 op0 = p0 = c0->tech_pvt;
07028 op1 = p1 = c1->tech_pvt;
07029 ofd0 = c0->fds[0];
07030 ofd1 = c1->fds[0];
07031 oc0 = p0->owner;
07032 oc1 = p1->owner;
07033
07034 if (ast_mutex_trylock(&p0->lock)) {
07035
07036 ast_channel_unlock(c0);
07037 ast_channel_unlock(c1);
07038 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07039 return AST_BRIDGE_RETRY;
07040 }
07041 if (ast_mutex_trylock(&p1->lock)) {
07042
07043 ast_mutex_unlock(&p0->lock);
07044 ast_channel_unlock(c0);
07045 ast_channel_unlock(c1);
07046 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
07047 return AST_BRIDGE_RETRY;
07048 }
07049
07050 if ((p0->callwaiting && p0->callwaitingcallerid)
07051 || (p1->callwaiting && p1->callwaitingcallerid)) {
07052
07053
07054
07055
07056
07057
07058
07059
07060
07061 ast_mutex_unlock(&p0->lock);
07062 ast_mutex_unlock(&p1->lock);
07063 ast_channel_unlock(c0);
07064 ast_channel_unlock(c1);
07065 return AST_BRIDGE_FAILED_NOWARN;
07066 }
07067
07068 #if defined(HAVE_PRI)
07069 if ((dahdi_sig_pri_lib_handles(p0->sig)
07070 && ((struct sig_pri_chan *) p0->sig_pvt)->no_b_channel)
07071 || (dahdi_sig_pri_lib_handles(p1->sig)
07072 && ((struct sig_pri_chan *) p1->sig_pvt)->no_b_channel)) {
07073
07074
07075
07076
07077 ast_mutex_unlock(&p0->lock);
07078 ast_mutex_unlock(&p1->lock);
07079 ast_channel_unlock(c0);
07080 ast_channel_unlock(c1);
07081 return AST_BRIDGE_FAILED_NOWARN;
07082 }
07083 #endif
07084
07085 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07086 if (p0->owner && p1->owner) {
07087
07088 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
07089 master = p0;
07090 slave = p1;
07091 inconf = 1;
07092 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
07093 master = p1;
07094 slave = p0;
07095 inconf = 1;
07096 } else {
07097 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
07098 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
07099 p0->channel,
07100 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07101 p0->subs[SUB_REAL].inthreeway, p0->channel,
07102 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
07103 p1->subs[SUB_REAL].inthreeway);
07104 }
07105 nothingok = 0;
07106 }
07107 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
07108 if (p1->subs[SUB_THREEWAY].inthreeway) {
07109 master = p1;
07110 slave = p0;
07111 nothingok = 0;
07112 }
07113 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
07114 if (p0->subs[SUB_THREEWAY].inthreeway) {
07115 master = p0;
07116 slave = p1;
07117 nothingok = 0;
07118 }
07119 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
07120
07121
07122 if (p1->subs[SUB_CALLWAIT].inthreeway) {
07123 master = p1;
07124 slave = p0;
07125 nothingok = 0;
07126 }
07127 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
07128
07129 if (p0->subs[SUB_CALLWAIT].inthreeway) {
07130 master = p0;
07131 slave = p1;
07132 nothingok = 0;
07133 }
07134 }
07135 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
07136 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
07137 if (master && slave) {
07138
07139
07140
07141 if ((oi1 == SUB_THREEWAY) &&
07142 p1->subs[SUB_THREEWAY].inthreeway &&
07143 p1->subs[SUB_REAL].owner &&
07144 p1->subs[SUB_REAL].inthreeway &&
07145 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07146 ast_debug(1,
07147 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07148 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07149 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
07150 os1 = p1->subs[SUB_REAL].owner->_state;
07151 } else {
07152 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07153 p0->channel, oi0, c0->name, p1->channel, oi1, c1->name);
07154 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
07155 }
07156 if ((oi0 == SUB_THREEWAY) &&
07157 p0->subs[SUB_THREEWAY].inthreeway &&
07158 p0->subs[SUB_REAL].owner &&
07159 p0->subs[SUB_REAL].inthreeway &&
07160 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
07161 ast_debug(1,
07162 "Playing ringback on %d/%d(%s) since %d/%d(%s) is in a ringing three-way\n",
07163 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07164 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
07165 os0 = p0->subs[SUB_REAL].owner->_state;
07166 } else {
07167 ast_debug(1, "Stopping tones on %d/%d(%s) talking to %d/%d(%s)\n",
07168 p1->channel, oi1, c1->name, p0->channel, oi0, c0->name);
07169 tone_zone_play_tone(p1->subs[oi1].dfd, -1);
07170 }
07171 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
07172 if (!p0->echocanbridged || !p1->echocanbridged) {
07173
07174 dahdi_disable_ec(p0);
07175 dahdi_disable_ec(p1);
07176 }
07177 }
07178 dahdi_link(slave, master);
07179 master->inconference = inconf;
07180 } else if (!nothingok)
07181 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
07182
07183 update_conf(p0);
07184 update_conf(p1);
07185 t0 = p0->subs[SUB_REAL].inthreeway;
07186 t1 = p1->subs[SUB_REAL].inthreeway;
07187
07188 ast_mutex_unlock(&p0->lock);
07189 ast_mutex_unlock(&p1->lock);
07190
07191 ast_channel_unlock(c0);
07192 ast_channel_unlock(c1);
07193
07194
07195 if ((!master || !slave) && !nothingok) {
07196 dahdi_enable_ec(p0);
07197 dahdi_enable_ec(p1);
07198 return AST_BRIDGE_FAILED;
07199 }
07200
07201 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07202
07203 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07204 disable_dtmf_detect(op0);
07205
07206 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07207 disable_dtmf_detect(op1);
07208
07209 for (;;) {
07210 struct ast_channel *c0_priority[2] = {c0, c1};
07211 struct ast_channel *c1_priority[2] = {c1, c0};
07212
07213
07214
07215
07216 ast_channel_lock(c0);
07217 while (ast_channel_trylock(c1)) {
07218 CHANNEL_DEADLOCK_AVOIDANCE(c0);
07219 }
07220
07221 p0 = c0->tech_pvt;
07222 p1 = c1->tech_pvt;
07223
07224 if (op0 == p0)
07225 i0 = dahdi_get_index(c0, p0, 1);
07226 if (op1 == p1)
07227 i1 = dahdi_get_index(c1, p1, 1);
07228
07229 ast_channel_unlock(c0);
07230 ast_channel_unlock(c1);
07231
07232 if (!timeoutms ||
07233 (op0 != p0) ||
07234 (op1 != p1) ||
07235 (ofd0 != c0->fds[0]) ||
07236 (ofd1 != c1->fds[0]) ||
07237 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
07238 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
07239 (oc0 != p0->owner) ||
07240 (oc1 != p1->owner) ||
07241 (t0 != p0->subs[SUB_REAL].inthreeway) ||
07242 (t1 != p1->subs[SUB_REAL].inthreeway) ||
07243 (oi0 != i0) ||
07244 (oi1 != i1)) {
07245 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
07246 op0->channel, oi0, op1->channel, oi1);
07247 res = AST_BRIDGE_RETRY;
07248 goto return_from_bridge;
07249 }
07250
07251 #ifdef PRI_2BCT
07252 if (!triedtopribridge) {
07253 triedtopribridge = 1;
07254 if (p0->pri && p0->pri == p1->pri && p0->pri->transfer) {
07255 ast_mutex_lock(&p0->pri->lock);
07256 switch (p0->sig) {
07257 case SIG_PRI_LIB_HANDLE_CASES:
07258 q931c0 = ((struct sig_pri_chan *) (p0->sig_pvt))->call;
07259 break;
07260 default:
07261 q931c0 = NULL;
07262 break;
07263 }
07264 switch (p1->sig) {
07265 case SIG_PRI_LIB_HANDLE_CASES:
07266 q931c1 = ((struct sig_pri_chan *) (p1->sig_pvt))->call;
07267 break;
07268 default:
07269 q931c1 = NULL;
07270 break;
07271 }
07272 if (q931c0 && q931c1) {
07273 pri_channel_bridge(q931c0, q931c1);
07274 }
07275 ast_mutex_unlock(&p0->pri->lock);
07276 }
07277 }
07278 #endif
07279
07280 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
07281 if (!who) {
07282 ast_debug(1, "Ooh, empty read...\n");
07283 continue;
07284 }
07285 f = ast_read(who);
07286 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
07287 *fo = f;
07288 *rc = who;
07289 res = AST_BRIDGE_COMPLETE;
07290 goto return_from_bridge;
07291 }
07292 if (f->frametype == AST_FRAME_DTMF) {
07293 if ((who == c0) && p0->pulsedial) {
07294 ast_write(c1, f);
07295 } else if ((who == c1) && p1->pulsedial) {
07296 ast_write(c0, f);
07297 } else {
07298 *fo = f;
07299 *rc = who;
07300 res = AST_BRIDGE_COMPLETE;
07301 goto return_from_bridge;
07302 }
07303 }
07304 ast_frfree(f);
07305
07306
07307 priority = !priority;
07308 }
07309
07310 return_from_bridge:
07311 if (op0 == p0)
07312 dahdi_enable_ec(p0);
07313
07314 if (op1 == p1)
07315 dahdi_enable_ec(p1);
07316
07317 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
07318 enable_dtmf_detect(op0);
07319
07320 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
07321 enable_dtmf_detect(op1);
07322
07323 dahdi_unlink(slave, master, 1);
07324
07325 return res;
07326 }
07327
07328 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
07329 {
07330 struct dahdi_pvt *p = newchan->tech_pvt;
07331 int x;
07332
07333 ast_mutex_lock(&p->lock);
07334
07335 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
07336 if (p->owner == oldchan) {
07337 p->owner = newchan;
07338 }
07339 for (x = 0; x < 3; x++) {
07340 if (p->subs[x].owner == oldchan) {
07341 if (!x) {
07342 dahdi_unlink(NULL, p, 0);
07343 }
07344 p->subs[x].owner = newchan;
07345 }
07346 }
07347 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
07348 analog_fixup(oldchan, newchan, p->sig_pvt);
07349 #if defined(HAVE_PRI)
07350 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
07351 sig_pri_fixup(oldchan, newchan, p->sig_pvt);
07352 #endif
07353 #if defined(HAVE_SS7)
07354 } else if (p->sig == SIG_SS7) {
07355 sig_ss7_fixup(oldchan, newchan, p->sig_pvt);
07356 #endif
07357 }
07358 update_conf(p);
07359
07360 ast_mutex_unlock(&p->lock);
07361
07362 if (newchan->_state == AST_STATE_RINGING) {
07363 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
07364 }
07365 return 0;
07366 }
07367
07368 static int dahdi_ring_phone(struct dahdi_pvt *p)
07369 {
07370 int x;
07371 int res;
07372
07373 x = 0;
07374 x = DAHDI_ONHOOK;
07375 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07376 do {
07377 x = DAHDI_RING;
07378 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07379 if (res) {
07380 switch (errno) {
07381 case EBUSY:
07382 case EINTR:
07383
07384 usleep(10000);
07385 continue;
07386 case EINPROGRESS:
07387 res = 0;
07388 break;
07389 default:
07390 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
07391 res = 0;
07392 }
07393 }
07394 } while (res);
07395 return res;
07396 }
07397
07398 static void *analog_ss_thread(void *data);
07399
07400 static int attempt_transfer(struct dahdi_pvt *p)
07401 {
07402
07403
07404
07405 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
07406
07407
07408 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
07409 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
07410 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
07411 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
07412 }
07413 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
07414 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
07415 }
07416 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
07417 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07418 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
07419 return -1;
07420 }
07421
07422 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07423 unalloc_sub(p, SUB_THREEWAY);
07424 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07425 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07426 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
07427 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
07428 }
07429 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
07430 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07431 }
07432 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
07433 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
07434 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
07435 return -1;
07436 }
07437
07438 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07439 ast_channel_unlock(p->subs[SUB_REAL].owner);
07440 unalloc_sub(p, SUB_THREEWAY);
07441
07442 return 1;
07443 } else {
07444 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
07445 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
07446 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07447 return -1;
07448 }
07449 return 0;
07450 }
07451
07452 static int check_for_conference(struct dahdi_pvt *p)
07453 {
07454 struct dahdi_confinfo ci;
07455
07456 if (p->master || (p->confno > -1))
07457 return 0;
07458 memset(&ci, 0, sizeof(ci));
07459 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
07460 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
07461 return 0;
07462 }
07463
07464
07465
07466 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
07467 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
07468 return 1;
07469 }
07470 return 0;
07471 }
07472
07473
07474
07475
07476
07477
07478 static int get_alarms(struct dahdi_pvt *p)
07479 {
07480 int res;
07481 struct dahdi_spaninfo zi;
07482 struct dahdi_params params;
07483
07484 memset(&zi, 0, sizeof(zi));
07485 zi.spanno = p->span;
07486
07487 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
07488 if (zi.alarms != DAHDI_ALARM_NONE)
07489 return zi.alarms;
07490 } else {
07491 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
07492 return 0;
07493 }
07494
07495
07496 memset(¶ms, 0, sizeof(params));
07497 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0)
07498 return params.chan_alarms;
07499
07500 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
07501
07502 return DAHDI_ALARM_NONE;
07503 }
07504
07505 static void dahdi_handle_dtmf(struct ast_channel *ast, int idx, struct ast_frame **dest)
07506 {
07507 struct dahdi_pvt *p = ast->tech_pvt;
07508 struct ast_frame *f = *dest;
07509
07510 ast_debug(1, "%s DTMF digit: 0x%02X '%c' on %s\n",
07511 f->frametype == AST_FRAME_DTMF_BEGIN ? "Begin" : "End",
07512 f->subclass.integer, f->subclass.integer, ast->name);
07513
07514 if (p->confirmanswer) {
07515 if (f->frametype == AST_FRAME_DTMF_END) {
07516 ast_debug(1, "Confirm answer on %s!\n", ast->name);
07517
07518
07519 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07520 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07521
07522 p->confirmanswer = 0;
07523 } else {
07524 p->subs[idx].f.frametype = AST_FRAME_NULL;
07525 p->subs[idx].f.subclass.integer = 0;
07526 }
07527 *dest = &p->subs[idx].f;
07528 } else if (p->callwaitcas) {
07529 if (f->frametype == AST_FRAME_DTMF_END) {
07530 if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
07531 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
07532 ast_free(p->cidspill);
07533 p->cidspill = NULL;
07534 send_cwcidspill(p);
07535 }
07536 p->callwaitcas = 0;
07537 }
07538 p->subs[idx].f.frametype = AST_FRAME_NULL;
07539 p->subs[idx].f.subclass.integer = 0;
07540 *dest = &p->subs[idx].f;
07541 } else if (f->subclass.integer == 'f') {
07542 if (f->frametype == AST_FRAME_DTMF_END) {
07543
07544 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
07545
07546 if (p->usefaxbuffers && !p->bufferoverrideinuse) {
07547 struct dahdi_bufferinfo bi = {
07548 .txbufpolicy = p->faxbuf_policy,
07549 .bufsize = p->bufsize,
07550 .numbufs = p->faxbuf_no
07551 };
07552 int res;
07553
07554 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
07555 ast_log(LOG_WARNING, "Channel '%s' unable to set buffer policy, reason: %s\n", ast->name, strerror(errno));
07556 } else {
07557 p->bufferoverrideinuse = 1;
07558 }
07559 }
07560 p->faxhandled = 1;
07561 if (p->dsp) {
07562 p->dsp_features &= ~DSP_FEATURE_FAX_DETECT;
07563 ast_dsp_set_features(p->dsp, p->dsp_features);
07564 ast_debug(1, "Disabling FAX tone detection on %s after tone received\n", ast->name);
07565 }
07566 if (strcmp(ast->exten, "fax")) {
07567 const char *target_context = S_OR(ast->macrocontext, ast->context);
07568
07569
07570
07571
07572
07573 ast_mutex_unlock(&p->lock);
07574 ast_channel_unlock(ast);
07575 if (ast_exists_extension(ast, target_context, "fax", 1,
07576 S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07577 ast_channel_lock(ast);
07578 ast_mutex_lock(&p->lock);
07579 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
07580
07581 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
07582 if (ast_async_goto(ast, target_context, "fax", 1))
07583 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
07584 } else {
07585 ast_channel_lock(ast);
07586 ast_mutex_lock(&p->lock);
07587 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
07588 }
07589 } else {
07590 ast_debug(1, "Already in a fax extension, not redirecting\n");
07591 }
07592 } else {
07593 ast_debug(1, "Fax already handled\n");
07594 }
07595 dahdi_confmute(p, 0);
07596 }
07597 p->subs[idx].f.frametype = AST_FRAME_NULL;
07598 p->subs[idx].f.subclass.integer = 0;
07599 *dest = &p->subs[idx].f;
07600 }
07601 }
07602
07603 static void handle_alarms(struct dahdi_pvt *p, int alms)
07604 {
07605 const char *alarm_str = alarm2str(alms);
07606
07607 if (report_alarms & REPORT_CHANNEL_ALARMS) {
07608 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
07609 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
07610 "Alarm: %s\r\n"
07611 "Channel: %d\r\n",
07612 alarm_str, p->channel);
07613 }
07614
07615 if (report_alarms & REPORT_SPAN_ALARMS && p->manages_span_alarms) {
07616 ast_log(LOG_WARNING, "Detected alarm on span %d: %s\n", p->span, alarm_str);
07617 manager_event(EVENT_FLAG_SYSTEM, "SpanAlarm",
07618 "Alarm: %s\r\n"
07619 "Span: %d\r\n",
07620 alarm_str, p->span);
07621 }
07622 }
07623
07624 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
07625 {
07626 int res, x;
07627 int idx, mysig;
07628 char *c;
07629 struct dahdi_pvt *p = ast->tech_pvt;
07630 pthread_t threadid;
07631 struct ast_channel *chan;
07632 struct ast_frame *f;
07633
07634 idx = dahdi_get_index(ast, p, 0);
07635 mysig = p->sig;
07636 if (p->outsigmod > -1)
07637 mysig = p->outsigmod;
07638 p->subs[idx].f.frametype = AST_FRAME_NULL;
07639 p->subs[idx].f.subclass.integer = 0;
07640 p->subs[idx].f.datalen = 0;
07641 p->subs[idx].f.samples = 0;
07642 p->subs[idx].f.mallocd = 0;
07643 p->subs[idx].f.offset = 0;
07644 p->subs[idx].f.src = "dahdi_handle_event";
07645 p->subs[idx].f.data.ptr = NULL;
07646 f = &p->subs[idx].f;
07647
07648 if (idx < 0)
07649 return &p->subs[idx].f;
07650 if (p->fake_event) {
07651 res = p->fake_event;
07652 p->fake_event = 0;
07653 } else
07654 res = dahdi_get_event(p->subs[idx].dfd);
07655
07656 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
07657
07658 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
07659 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
07660 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
07661 #if defined(HAVE_PRI)
07662 if (dahdi_sig_pri_lib_handles(p->sig)
07663 && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
07664 && p->pri
07665 && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07666
07667 } else
07668 #endif
07669 {
07670
07671 dahdi_confmute(p, 0);
07672 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
07673 p->subs[idx].f.subclass.integer = res & 0xff;
07674 dahdi_handle_dtmf(ast, idx, &f);
07675 }
07676 return f;
07677 }
07678
07679 if (res & DAHDI_EVENT_DTMFDOWN) {
07680 ast_debug(1, "DTMF Down '%c'\n", 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, 1);
07692 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
07693 p->subs[idx].f.subclass.integer = res & 0xff;
07694 dahdi_handle_dtmf(ast, idx, &f);
07695 }
07696 return &p->subs[idx].f;
07697 }
07698
07699 switch (res) {
07700 case DAHDI_EVENT_EC_DISABLED:
07701 ast_verb(3, "Channel %d echo canceler disabled.\n", p->channel);
07702 p->echocanon = 0;
07703 break;
07704 #ifdef HAVE_DAHDI_ECHOCANCEL_FAX_MODE
07705 case DAHDI_EVENT_TX_CED_DETECTED:
07706 ast_verb(3, "Channel %d detected a CED tone towards the network.\n", p->channel);
07707 break;
07708 case DAHDI_EVENT_RX_CED_DETECTED:
07709 ast_verb(3, "Channel %d detected a CED tone from the network.\n", p->channel);
07710 break;
07711 case DAHDI_EVENT_EC_NLP_DISABLED:
07712 ast_verb(3, "Channel %d echo canceler disabled its NLP.\n", p->channel);
07713 break;
07714 case DAHDI_EVENT_EC_NLP_ENABLED:
07715 ast_verb(3, "Channel %d echo canceler enabled its NLP.\n", p->channel);
07716 break;
07717 #endif
07718 case DAHDI_EVENT_BITSCHANGED:
07719 #ifdef HAVE_OPENR2
07720 if (p->sig != SIG_MFCR2) {
07721 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07722 } else {
07723 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
07724 openr2_chan_handle_cas(p->r2chan);
07725 }
07726 #else
07727 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
07728 #endif
07729 case DAHDI_EVENT_PULSE_START:
07730
07731 if (!ast->pbx)
07732 tone_zone_play_tone(p->subs[idx].dfd, -1);
07733 break;
07734 case DAHDI_EVENT_DIALCOMPLETE:
07735 #ifdef HAVE_OPENR2
07736 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
07737
07738
07739 break;
07740 }
07741 #endif
07742 if (p->inalarm) break;
07743 if ((p->radio || (p->oprmode < 0))) break;
07744 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
07745 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
07746 return NULL;
07747 }
07748 if (!x) {
07749 dahdi_enable_ec(p);
07750 if (p->echobreak) {
07751 dahdi_train_ec(p);
07752 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
07753 p->dop.op = DAHDI_DIAL_OP_REPLACE;
07754 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07755 p->echobreak = 0;
07756 } else {
07757 p->dialing = 0;
07758 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
07759
07760 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
07761 ast_setstate(ast, AST_STATE_UP);
07762 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07763 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07764 break;
07765 } else {
07766
07767 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
07768 }
07769 }
07770 if (ast->_state == AST_STATE_DIALING) {
07771 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
07772 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
07773 } else if (p->confirmanswer || (!p->dialednone
07774 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
07775 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
07776 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
07777 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
07778 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
07779 || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
07780 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
07781 || (mysig == SIG_SF_FEATB)))) {
07782 ast_setstate(ast, AST_STATE_RINGING);
07783 } else if (!p->answeronpolarityswitch) {
07784 ast_setstate(ast, AST_STATE_UP);
07785 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07786 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
07787
07788 p->polarity = POLARITY_REV;
07789 } else {
07790
07791 p->polarity = POLARITY_IDLE;
07792 }
07793 }
07794 }
07795 }
07796 break;
07797 case DAHDI_EVENT_ALARM:
07798 switch (p->sig) {
07799 #if defined(HAVE_PRI)
07800 case SIG_PRI_LIB_HANDLE_CASES:
07801 sig_pri_chan_alarm_notify(p->sig_pvt, 0);
07802 break;
07803 #endif
07804 #if defined(HAVE_SS7)
07805 case SIG_SS7:
07806 sig_ss7_set_alarm(p->sig_pvt, 1);
07807 break;
07808 #endif
07809 default:
07810 p->inalarm = 1;
07811 break;
07812 }
07813 res = get_alarms(p);
07814 handle_alarms(p, res);
07815 #ifdef HAVE_PRI
07816 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07817
07818 } else {
07819 break;
07820 }
07821 #endif
07822 #if defined(HAVE_SS7)
07823 if (p->sig == SIG_SS7)
07824 break;
07825 #endif
07826 #ifdef HAVE_OPENR2
07827 if (p->sig == SIG_MFCR2)
07828 break;
07829 #endif
07830 case DAHDI_EVENT_ONHOOK:
07831 if (p->radio) {
07832 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07833 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
07834 break;
07835 }
07836 if (p->oprmode < 0)
07837 {
07838 if (p->oprmode != -1) break;
07839 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07840 {
07841
07842 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07843 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
07844 save_conference(p->oprpeer);
07845 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07846 }
07847 break;
07848 }
07849 switch (p->sig) {
07850 case SIG_FXOLS:
07851 case SIG_FXOGS:
07852 case SIG_FXOKS:
07853
07854 if (idx == SUB_REAL) {
07855
07856 if (p->subs[SUB_CALLWAIT].owner) {
07857
07858 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
07859 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
07860 unalloc_sub(p, SUB_CALLWAIT);
07861 #if 0
07862 p->subs[idx].needanswer = 0;
07863 p->subs[idx].needringing = 0;
07864 #endif
07865 p->callwaitingrepeat = 0;
07866 p->cidcwexpire = 0;
07867 p->cid_suppress_expire = 0;
07868 p->owner = NULL;
07869
07870 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
07871 p->dialing = 1;
07872 dahdi_ring_phone(p);
07873 } else if (p->subs[SUB_THREEWAY].owner) {
07874 unsigned int mssinceflash;
07875
07876
07877 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
07878
07879 DLA_UNLOCK(&p->lock);
07880 CHANNEL_DEADLOCK_AVOIDANCE(ast);
07881
07882
07883
07884 DLA_LOCK(&p->lock);
07885 if (p->owner != ast) {
07886 ast_log(LOG_WARNING, "This isn't good...\n");
07887 return NULL;
07888 }
07889 }
07890 if (!p->subs[SUB_THREEWAY].owner) {
07891 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
07892 return NULL;
07893 }
07894 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
07895 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
07896 if (mssinceflash < MIN_MS_SINCE_FLASH) {
07897
07898
07899 if (p->subs[SUB_THREEWAY].owner)
07900 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
07901 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07902 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
07903 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07904 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
07905 if (p->transfer) {
07906
07907 p->subs[SUB_REAL].inthreeway = 0;
07908 p->subs[SUB_THREEWAY].inthreeway = 0;
07909
07910 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
07911 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07912
07913 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07914 p->owner = NULL;
07915
07916 dahdi_ring_phone(p);
07917 } else {
07918 if ((res = attempt_transfer(p)) < 0) {
07919 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07920 if (p->subs[SUB_THREEWAY].owner)
07921 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07922 } else if (res) {
07923
07924 if (p->subs[SUB_THREEWAY].owner)
07925 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07926 break;
07927 }
07928 }
07929 } else {
07930 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
07931 if (p->subs[SUB_THREEWAY].owner)
07932 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07933 }
07934 } else {
07935 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
07936
07937 swap_subs(p, SUB_THREEWAY, SUB_REAL);
07938 p->owner = NULL;
07939
07940 dahdi_ring_phone(p);
07941 }
07942 }
07943 } else {
07944 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
07945 }
07946
07947 default:
07948 dahdi_disable_ec(p);
07949 return NULL;
07950 }
07951 break;
07952 case DAHDI_EVENT_RINGOFFHOOK:
07953 if (p->inalarm) break;
07954 if (p->oprmode < 0)
07955 {
07956 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
07957 {
07958
07959 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
07960 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
07961 restore_conference(p->oprpeer);
07962 }
07963 break;
07964 }
07965 if (p->radio)
07966 {
07967 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
07968 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
07969 break;
07970 }
07971
07972
07973 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
07974 c = strchr(p->dialdest, '/');
07975 if (c)
07976 c++;
07977 else
07978 c = p->dialdest;
07979 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
07980 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
07981 if (strlen(p->dop.dialstr) > 4) {
07982 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
07983 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
07984 p->echorest[sizeof(p->echorest) - 1] = '\0';
07985 p->echobreak = 1;
07986 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
07987 } else
07988 p->echobreak = 0;
07989 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
07990 int saveerr = errno;
07991
07992 x = DAHDI_ONHOOK;
07993 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
07994 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
07995 return NULL;
07996 }
07997 p->dialing = 1;
07998 return &p->subs[idx].f;
07999 }
08000 switch (p->sig) {
08001 case SIG_FXOLS:
08002 case SIG_FXOGS:
08003 case SIG_FXOKS:
08004 switch (ast->_state) {
08005 case AST_STATE_RINGING:
08006 dahdi_enable_ec(p);
08007 dahdi_train_ec(p);
08008 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08009 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08010
08011 p->subs[SUB_REAL].needringing = 0;
08012 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08013 ast_debug(1, "channel %d answered\n", p->channel);
08014
08015
08016 ast_free(p->cidspill);
08017 p->cidspill = NULL;
08018 restore_conference(p);
08019
08020 p->dialing = 0;
08021 p->callwaitcas = 0;
08022 if (p->confirmanswer) {
08023
08024 p->subs[idx].f.frametype = AST_FRAME_NULL;
08025 p->subs[idx].f.subclass.integer = 0;
08026 } else if (!ast_strlen_zero(p->dop.dialstr)) {
08027
08028 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08029 if (res < 0) {
08030 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08031 p->dop.dialstr[0] = '\0';
08032 return NULL;
08033 } else {
08034 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
08035 p->subs[idx].f.frametype = AST_FRAME_NULL;
08036 p->subs[idx].f.subclass.integer = 0;
08037 p->dialing = 1;
08038 }
08039 p->dop.dialstr[0] = '\0';
08040 ast_setstate(ast, AST_STATE_DIALING);
08041 } else
08042 ast_setstate(ast, AST_STATE_UP);
08043 return &p->subs[idx].f;
08044 case AST_STATE_DOWN:
08045 ast_setstate(ast, AST_STATE_RING);
08046 ast->rings = 1;
08047 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08048 p->subs[idx].f.subclass.integer = AST_CONTROL_OFFHOOK;
08049 ast_debug(1, "channel %d picked up\n", p->channel);
08050 return &p->subs[idx].f;
08051 case AST_STATE_UP:
08052
08053 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
08054
08055 if (ast_bridged_channel(p->owner))
08056 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08057 p->subs[idx].needunhold = 1;
08058 break;
08059 case AST_STATE_RESERVED:
08060
08061 if (has_voicemail(p))
08062 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08063 else
08064 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08065 break;
08066 default:
08067 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
08068 }
08069 break;
08070 case SIG_FXSLS:
08071 case SIG_FXSGS:
08072 case SIG_FXSKS:
08073 if (ast->_state == AST_STATE_RING) {
08074 p->ringt = p->ringt_base;
08075 }
08076
08077
08078
08079 ast_debug(1, "Setting IDLE polarity due "
08080 "to ring. Old polarity was %d\n",
08081 p->polarity);
08082 p->polarity = POLARITY_IDLE;
08083
08084
08085 case SIG_EM:
08086 case SIG_EM_E1:
08087 case SIG_EMWINK:
08088 case SIG_FEATD:
08089 case SIG_FEATDMF:
08090 case SIG_FEATDMF_TA:
08091 case SIG_E911:
08092 case SIG_FGC_CAMA:
08093 case SIG_FGC_CAMAMF:
08094 case SIG_FEATB:
08095 case SIG_SF:
08096 case SIG_SFWINK:
08097 case SIG_SF_FEATD:
08098 case SIG_SF_FEATDMF:
08099 case SIG_SF_FEATB:
08100 if (ast->_state == AST_STATE_PRERING)
08101 ast_setstate(ast, AST_STATE_RING);
08102 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
08103 ast_debug(1, "Ring detected\n");
08104 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08105 p->subs[idx].f.subclass.integer = AST_CONTROL_RING;
08106 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
08107 ast_debug(1, "Line answered\n");
08108 if (p->confirmanswer) {
08109 p->subs[idx].f.frametype = AST_FRAME_NULL;
08110 p->subs[idx].f.subclass.integer = 0;
08111 } else {
08112 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08113 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08114 ast_setstate(ast, AST_STATE_UP);
08115 }
08116 } else if (ast->_state != AST_STATE_RING)
08117 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
08118 break;
08119 default:
08120 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08121 }
08122 break;
08123 case DAHDI_EVENT_RINGBEGIN:
08124 switch (p->sig) {
08125 case SIG_FXSLS:
08126 case SIG_FXSGS:
08127 case SIG_FXSKS:
08128 if (ast->_state == AST_STATE_RING) {
08129 p->ringt = p->ringt_base;
08130 }
08131 break;
08132 }
08133 break;
08134 case DAHDI_EVENT_RINGERON:
08135 break;
08136 case DAHDI_EVENT_NOALARM:
08137 switch (p->sig) {
08138 #if defined(HAVE_PRI)
08139 case SIG_PRI_LIB_HANDLE_CASES:
08140 sig_pri_chan_alarm_notify(p->sig_pvt, 1);
08141 break;
08142 #endif
08143 #if defined(HAVE_SS7)
08144 case SIG_SS7:
08145 sig_ss7_set_alarm(p->sig_pvt, 0);
08146 break;
08147 #endif
08148 default:
08149 p->inalarm = 0;
08150 break;
08151 }
08152 handle_clear_alarms(p);
08153 break;
08154 case DAHDI_EVENT_WINKFLASH:
08155 if (p->inalarm) break;
08156 if (p->radio) break;
08157 if (p->oprmode < 0) break;
08158 if (p->oprmode > 1)
08159 {
08160 struct dahdi_params par;
08161
08162 memset(&par, 0, sizeof(par));
08163 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
08164 {
08165 if (!par.rxisoffhook)
08166 {
08167
08168 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
08169 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
08170 save_conference(p);
08171 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08172 }
08173 }
08174 break;
08175 }
08176
08177 p->flashtime = ast_tvnow();
08178 switch (mysig) {
08179 case SIG_FXOLS:
08180 case SIG_FXOGS:
08181 case SIG_FXOKS:
08182 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
08183 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
08184
08185
08186 ast_free(p->cidspill);
08187 p->cidspill = NULL;
08188 restore_conference(p);
08189 p->callwaitcas = 0;
08190
08191 if (idx != SUB_REAL) {
08192 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
08193 goto winkflashdone;
08194 }
08195
08196 if (p->subs[SUB_CALLWAIT].owner) {
08197
08198 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
08199 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
08200 p->owner = p->subs[SUB_REAL].owner;
08201 ast_debug(1, "Making %s the new owner\n", p->owner->name);
08202 if (p->owner->_state == AST_STATE_RINGING) {
08203 ast_setstate(p->owner, AST_STATE_UP);
08204 p->subs[SUB_REAL].needanswer = 1;
08205 }
08206 p->callwaitingrepeat = 0;
08207 p->cidcwexpire = 0;
08208 p->cid_suppress_expire = 0;
08209
08210 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
08211 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
08212 S_OR(p->mohsuggest, NULL),
08213 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08214 }
08215 p->subs[SUB_CALLWAIT].needhold = 1;
08216 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
08217 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
08218 S_OR(p->mohsuggest, NULL),
08219 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08220 }
08221 p->subs[SUB_REAL].needunhold = 1;
08222 } else if (!p->subs[SUB_THREEWAY].owner) {
08223 if (!p->threewaycalling) {
08224
08225 p->subs[SUB_REAL].needflash = 1;
08226 goto winkflashdone;
08227 } else if (!check_for_conference(p)) {
08228 char cid_num[256];
08229 char cid_name[256];
08230
08231 cid_num[0] = 0;
08232 cid_name[0] = 0;
08233 if (p->dahditrcallerid && p->owner) {
08234 if (p->owner->caller.id.number.valid
08235 && p->owner->caller.id.number.str) {
08236 ast_copy_string(cid_num, p->owner->caller.id.number.str,
08237 sizeof(cid_num));
08238 }
08239 if (p->owner->caller.id.name.valid
08240 && p->owner->caller.id.name.str) {
08241 ast_copy_string(cid_name, p->owner->caller.id.name.str,
08242 sizeof(cid_name));
08243 }
08244 }
08245
08246
08247 if (!((ast->pbx) ||
08248 (ast->_state == AST_STATE_UP) ||
08249 (ast->_state == AST_STATE_RING))) {
08250 ast_debug(1, "Flash when call not up or ringing\n");
08251 goto winkflashdone;
08252 }
08253 if (alloc_sub(p, SUB_THREEWAY)) {
08254 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
08255 goto winkflashdone;
08256 }
08257
08258 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, NULL);
08259 if (p->dahditrcallerid) {
08260 if (!p->origcid_num)
08261 p->origcid_num = ast_strdup(p->cid_num);
08262 if (!p->origcid_name)
08263 p->origcid_name = ast_strdup(p->cid_name);
08264 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
08265 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
08266 }
08267
08268 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08269
08270 dahdi_disable_ec(p);
08271 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
08272 if (res)
08273 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
08274 p->owner = chan;
08275 if (!chan) {
08276 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
08277 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
08278 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
08279 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08280 dahdi_enable_ec(p);
08281 ast_hangup(chan);
08282 } else {
08283 ast_verb(3, "Started three way call on channel %d\n", p->channel);
08284
08285
08286 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08287 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
08288 S_OR(p->mohsuggest, NULL),
08289 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
08290 }
08291 p->subs[SUB_THREEWAY].needhold = 1;
08292 }
08293 }
08294 } else {
08295
08296 if (p->subs[SUB_THREEWAY].inthreeway) {
08297
08298 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
08299
08300 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
08301
08302 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08303 p->owner = p->subs[SUB_REAL].owner;
08304 }
08305
08306 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
08307 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08308 p->subs[SUB_REAL].inthreeway = 0;
08309 p->subs[SUB_THREEWAY].inthreeway = 0;
08310 } else {
08311
08312 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
08313 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
08314 int otherindex = SUB_THREEWAY;
08315
08316 ast_verb(3, "Building conference call with %s and %s\n",
08317 p->subs[SUB_THREEWAY].owner->name,
08318 p->subs[SUB_REAL].owner->name);
08319
08320 p->subs[SUB_THREEWAY].inthreeway = 1;
08321 p->subs[SUB_REAL].inthreeway = 1;
08322 if (ast->_state == AST_STATE_UP) {
08323 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08324 otherindex = SUB_REAL;
08325 }
08326 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
08327 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
08328 p->subs[otherindex].needunhold = 1;
08329 p->owner = p->subs[SUB_REAL].owner;
08330 } else {
08331 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
08332 swap_subs(p, SUB_THREEWAY, SUB_REAL);
08333 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
08334 p->owner = p->subs[SUB_REAL].owner;
08335 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
08336 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08337 p->subs[SUB_REAL].needunhold = 1;
08338 dahdi_enable_ec(p);
08339 }
08340 }
08341 }
08342 winkflashdone:
08343 update_conf(p);
08344 break;
08345 case SIG_EM:
08346 case SIG_EM_E1:
08347 case SIG_FEATD:
08348 case SIG_SF:
08349 case SIG_SFWINK:
08350 case SIG_SF_FEATD:
08351 case SIG_FXSLS:
08352 case SIG_FXSGS:
08353 if (p->dialing)
08354 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
08355 else
08356 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
08357 break;
08358 case SIG_FEATDMF_TA:
08359 switch (p->whichwink) {
08360 case 0:
08361 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
08362 S_COR(p->owner->caller.ani.number.valid,
08363 p->owner->caller.ani.number.str, ""));
08364 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
08365 p->owner->caller.ani2,
08366 S_COR(p->owner->caller.ani.number.valid,
08367 p->owner->caller.ani.number.str, ""));
08368 break;
08369 case 1:
08370 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
08371 break;
08372 case 2:
08373 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
08374 return NULL;
08375 }
08376 p->whichwink++;
08377
08378 case SIG_FEATDMF:
08379 case SIG_E911:
08380 case SIG_FGC_CAMAMF:
08381 case SIG_FGC_CAMA:
08382 case SIG_FEATB:
08383 case SIG_SF_FEATDMF:
08384 case SIG_SF_FEATB:
08385 case SIG_EMWINK:
08386
08387 if (!ast_strlen_zero(p->dop.dialstr)) {
08388 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08389 if (res < 0) {
08390 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08391 p->dop.dialstr[0] = '\0';
08392 return NULL;
08393 } else
08394 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08395 }
08396 p->dop.dialstr[0] = '\0';
08397 break;
08398 default:
08399 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
08400 }
08401 break;
08402 case DAHDI_EVENT_HOOKCOMPLETE:
08403 if (p->inalarm) break;
08404 if ((p->radio || (p->oprmode < 0))) break;
08405 if (p->waitingfordt.tv_sec) break;
08406 switch (mysig) {
08407 case SIG_FXSLS:
08408 case SIG_FXSGS:
08409 case SIG_FXSKS:
08410 case SIG_EM:
08411 case SIG_EM_E1:
08412 case SIG_EMWINK:
08413 case SIG_FEATD:
08414 case SIG_SF:
08415 case SIG_SFWINK:
08416 case SIG_SF_FEATD:
08417 if (!ast_strlen_zero(p->dop.dialstr)) {
08418 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08419 if (res < 0) {
08420 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
08421 p->dop.dialstr[0] = '\0';
08422 return NULL;
08423 } else
08424 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
08425 }
08426 p->dop.dialstr[0] = '\0';
08427 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08428 break;
08429 case SIG_FEATDMF:
08430 case SIG_FEATDMF_TA:
08431 case SIG_E911:
08432 case SIG_FGC_CAMA:
08433 case SIG_FGC_CAMAMF:
08434 case SIG_FEATB:
08435 case SIG_SF_FEATDMF:
08436 case SIG_SF_FEATB:
08437 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
08438 break;
08439 default:
08440 break;
08441 }
08442 break;
08443 case DAHDI_EVENT_POLARITY:
08444
08445
08446
08447
08448
08449
08450 if (p->polarity == POLARITY_IDLE) {
08451 p->polarity = POLARITY_REV;
08452 if (p->answeronpolarityswitch &&
08453 ((ast->_state == AST_STATE_DIALING) ||
08454 (ast->_state == AST_STATE_RINGING))) {
08455 ast_debug(1, "Answering on polarity switch!\n");
08456 ast_setstate(p->owner, AST_STATE_UP);
08457 if (p->hanguponpolarityswitch) {
08458 p->polaritydelaytv = ast_tvnow();
08459 }
08460 } else
08461 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
08462 }
08463
08464
08465 if (p->hanguponpolarityswitch &&
08466 (p->polarityonanswerdelay > 0) &&
08467 (p->polarity == POLARITY_REV) &&
08468 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
08469
08470 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) );
08471
08472 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
08473 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
08474 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
08475 p->polarity = POLARITY_IDLE;
08476 } else
08477 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);
08478
08479 } else {
08480 p->polarity = POLARITY_IDLE;
08481 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
08482 }
08483
08484 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) );
08485 break;
08486 default:
08487 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
08488 }
08489 return &p->subs[idx].f;
08490 }
08491
08492 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
08493 {
08494 int res;
08495 int idx;
08496 struct ast_frame *f;
08497 int usedindex = -1;
08498 struct dahdi_pvt *p = ast->tech_pvt;
08499
08500 idx = dahdi_get_index(ast, p, 1);
08501
08502 p->subs[idx].f.frametype = AST_FRAME_NULL;
08503 p->subs[idx].f.datalen = 0;
08504 p->subs[idx].f.samples = 0;
08505 p->subs[idx].f.mallocd = 0;
08506 p->subs[idx].f.offset = 0;
08507 p->subs[idx].f.subclass.integer = 0;
08508 p->subs[idx].f.delivery = ast_tv(0,0);
08509 p->subs[idx].f.src = "dahdi_exception";
08510 p->subs[idx].f.data.ptr = NULL;
08511
08512
08513 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
08514
08515
08516
08517
08518
08519 if (p->fake_event) {
08520 res = p->fake_event;
08521 p->fake_event = 0;
08522 } else
08523 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
08524
08525 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
08526 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
08527 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
08528 p->owner = p->subs[SUB_REAL].owner;
08529 if (p->owner && ast_bridged_channel(p->owner))
08530 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08531 p->subs[SUB_REAL].needunhold = 1;
08532 }
08533 switch (res) {
08534 case DAHDI_EVENT_ONHOOK:
08535 dahdi_disable_ec(p);
08536 if (p->owner) {
08537 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
08538 dahdi_ring_phone(p);
08539 p->callwaitingrepeat = 0;
08540 p->cidcwexpire = 0;
08541 p->cid_suppress_expire = 0;
08542 } else
08543 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08544 update_conf(p);
08545 break;
08546 case DAHDI_EVENT_RINGOFFHOOK:
08547 dahdi_enable_ec(p);
08548 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08549 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
08550 p->subs[SUB_REAL].needanswer = 1;
08551 p->dialing = 0;
08552 }
08553 break;
08554 case DAHDI_EVENT_HOOKCOMPLETE:
08555 case DAHDI_EVENT_RINGERON:
08556 case DAHDI_EVENT_RINGEROFF:
08557
08558 break;
08559 case DAHDI_EVENT_WINKFLASH:
08560 p->flashtime = ast_tvnow();
08561 if (p->owner) {
08562 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
08563 if (p->owner->_state != AST_STATE_UP) {
08564
08565 usedindex = dahdi_get_index(p->owner, p, 0);
08566 if (usedindex > -1) {
08567 p->subs[usedindex].needanswer = 1;
08568 }
08569 ast_setstate(p->owner, AST_STATE_UP);
08570 }
08571 p->callwaitingrepeat = 0;
08572 p->cidcwexpire = 0;
08573 p->cid_suppress_expire = 0;
08574 if (ast_bridged_channel(p->owner))
08575 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
08576 p->subs[SUB_REAL].needunhold = 1;
08577 } else
08578 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
08579 update_conf(p);
08580 break;
08581 default:
08582 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
08583 }
08584 f = &p->subs[idx].f;
08585 return f;
08586 }
08587 if (!(p->radio || (p->oprmode < 0)))
08588 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
08589
08590 if (ast != p->owner) {
08591 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
08592 f = &p->subs[idx].f;
08593 return f;
08594 }
08595 f = dahdi_handle_event(ast);
08596
08597
08598 if (f == NULL) {
08599 ast_set_hangupsource(ast, ast->name, 0);
08600 }
08601
08602 return f;
08603 }
08604
08605 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
08606 {
08607 struct dahdi_pvt *p = ast->tech_pvt;
08608 struct ast_frame *f;
08609 ast_mutex_lock(&p->lock);
08610 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08611 struct analog_pvt *analog_p = p->sig_pvt;
08612 f = analog_exception(analog_p, ast);
08613 } else {
08614 f = __dahdi_exception(ast);
08615 }
08616 ast_mutex_unlock(&p->lock);
08617 return f;
08618 }
08619
08620 static struct ast_frame *dahdi_read(struct ast_channel *ast)
08621 {
08622 struct dahdi_pvt *p = ast->tech_pvt;
08623 int res;
08624 int idx;
08625 void *readbuf;
08626 struct ast_frame *f;
08627
08628 while (ast_mutex_trylock(&p->lock)) {
08629 CHANNEL_DEADLOCK_AVOIDANCE(ast);
08630 }
08631
08632 idx = dahdi_get_index(ast, p, 0);
08633
08634
08635 if (idx < 0) {
08636 ast_log(LOG_WARNING, "We don't exist?\n");
08637 ast_mutex_unlock(&p->lock);
08638 return NULL;
08639 }
08640
08641 if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
08642 ast_mutex_unlock(&p->lock);
08643 return NULL;
08644 }
08645
08646 p->subs[idx].f.frametype = AST_FRAME_NULL;
08647 p->subs[idx].f.datalen = 0;
08648 p->subs[idx].f.samples = 0;
08649 p->subs[idx].f.mallocd = 0;
08650 p->subs[idx].f.offset = 0;
08651 p->subs[idx].f.subclass.integer = 0;
08652 p->subs[idx].f.delivery = ast_tv(0,0);
08653 p->subs[idx].f.src = "dahdi_read";
08654 p->subs[idx].f.data.ptr = NULL;
08655
08656
08657 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
08658 {
08659 struct dahdi_params ps;
08660
08661 memset(&ps, 0, sizeof(ps));
08662 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
08663 ast_mutex_unlock(&p->lock);
08664 return NULL;
08665 }
08666 p->firstradio = 1;
08667 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08668 if (ps.rxisoffhook)
08669 {
08670 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_KEY;
08671 }
08672 else
08673 {
08674 p->subs[idx].f.subclass.integer = AST_CONTROL_RADIO_UNKEY;
08675 }
08676 ast_mutex_unlock(&p->lock);
08677 return &p->subs[idx].f;
08678 }
08679 if (p->ringt > 0) {
08680 if (!(--p->ringt)) {
08681 ast_mutex_unlock(&p->lock);
08682 return NULL;
08683 }
08684 }
08685
08686 #ifdef HAVE_OPENR2
08687 if (p->mfcr2) {
08688 openr2_chan_process_event(p->r2chan);
08689 if (OR2_DIR_FORWARD == openr2_chan_get_direction(p->r2chan)) {
08690 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_PROGRESS }, };
08691
08692
08693 if (p->mfcr2_call_accepted &&
08694 !p->mfcr2_progress &&
08695 ast->_state == AST_STATE_RINGING) {
08696 ast_log(LOG_DEBUG, "Enqueuing progress frame after R2 accept in chan %d\n", p->channel);
08697 ast_queue_frame(p->owner, &f);
08698 p->mfcr2_progress = 1;
08699 }
08700 }
08701 }
08702 #endif
08703
08704 if (p->subs[idx].needringing) {
08705
08706 p->subs[idx].needringing = 0;
08707 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08708 p->subs[idx].f.subclass.integer = AST_CONTROL_RINGING;
08709 ast_setstate(ast, AST_STATE_RINGING);
08710 ast_mutex_unlock(&p->lock);
08711 return &p->subs[idx].f;
08712 }
08713
08714 if (p->subs[idx].needbusy) {
08715
08716 p->subs[idx].needbusy = 0;
08717 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08718 p->subs[idx].f.subclass.integer = AST_CONTROL_BUSY;
08719 ast_mutex_unlock(&p->lock);
08720 return &p->subs[idx].f;
08721 }
08722
08723 if (p->subs[idx].needcongestion) {
08724
08725 p->subs[idx].needcongestion = 0;
08726 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08727 p->subs[idx].f.subclass.integer = AST_CONTROL_CONGESTION;
08728 ast_mutex_unlock(&p->lock);
08729 return &p->subs[idx].f;
08730 }
08731
08732 if (p->subs[idx].needanswer) {
08733
08734 p->subs[idx].needanswer = 0;
08735 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08736 p->subs[idx].f.subclass.integer = AST_CONTROL_ANSWER;
08737 ast_mutex_unlock(&p->lock);
08738 return &p->subs[idx].f;
08739 }
08740 #ifdef HAVE_OPENR2
08741 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
08742
08743
08744
08745
08746 ast_mutex_unlock(&p->lock);
08747 return &ast_null_frame;
08748 }
08749 #endif
08750
08751 if (p->subs[idx].needflash) {
08752
08753 p->subs[idx].needflash = 0;
08754 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08755 p->subs[idx].f.subclass.integer = AST_CONTROL_FLASH;
08756 ast_mutex_unlock(&p->lock);
08757 return &p->subs[idx].f;
08758 }
08759
08760 if (p->subs[idx].needhold) {
08761
08762 p->subs[idx].needhold = 0;
08763 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08764 p->subs[idx].f.subclass.integer = AST_CONTROL_HOLD;
08765 ast_mutex_unlock(&p->lock);
08766 ast_debug(1, "Sending hold on '%s'\n", ast->name);
08767 return &p->subs[idx].f;
08768 }
08769
08770 if (p->subs[idx].needunhold) {
08771
08772 p->subs[idx].needunhold = 0;
08773 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
08774 p->subs[idx].f.subclass.integer = AST_CONTROL_UNHOLD;
08775 ast_mutex_unlock(&p->lock);
08776 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
08777 return &p->subs[idx].f;
08778 }
08779
08780 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
08781 if (!p->subs[idx].linear) {
08782 p->subs[idx].linear = 1;
08783 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08784 if (res)
08785 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
08786 }
08787 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
08788 (ast->rawreadformat == AST_FORMAT_ALAW)) {
08789 if (p->subs[idx].linear) {
08790 p->subs[idx].linear = 0;
08791 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08792 if (res)
08793 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
08794 }
08795 } else {
08796 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
08797 ast_mutex_unlock(&p->lock);
08798 return NULL;
08799 }
08800 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
08801 CHECK_BLOCKING(ast);
08802 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08803 ast_clear_flag(ast, AST_FLAG_BLOCKING);
08804
08805 if (res < 0) {
08806 f = NULL;
08807 if (res == -1) {
08808 if (errno == EAGAIN) {
08809
08810 ast_mutex_unlock(&p->lock);
08811 return &p->subs[idx].f;
08812 } else if (errno == ELAST) {
08813 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08814 struct analog_pvt *analog_p = p->sig_pvt;
08815 f = analog_exception(analog_p, ast);
08816 } else {
08817 f = __dahdi_exception(ast);
08818 }
08819 } else
08820 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
08821 }
08822 ast_mutex_unlock(&p->lock);
08823 return f;
08824 }
08825 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
08826 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
08827 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08828 struct analog_pvt *analog_p = p->sig_pvt;
08829 f = analog_exception(analog_p, ast);
08830 } else {
08831 f = __dahdi_exception(ast);
08832 }
08833 ast_mutex_unlock(&p->lock);
08834 return f;
08835 }
08836 if (p->tdd) {
08837 int c;
08838
08839 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
08840 if (c < 0) {
08841 ast_debug(1,"tdd_feed failed\n");
08842 ast_mutex_unlock(&p->lock);
08843 return NULL;
08844 }
08845 if (c) {
08846 p->subs[idx].f.subclass.integer = 0;
08847 p->subs[idx].f.frametype = AST_FRAME_TEXT;
08848 p->subs[idx].f.mallocd = 0;
08849 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08850 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
08851 p->subs[idx].f.datalen = 1;
08852 *((char *) p->subs[idx].f.data.ptr) = c;
08853 ast_mutex_unlock(&p->lock);
08854 return &p->subs[idx].f;
08855 }
08856 }
08857 if (idx == SUB_REAL) {
08858
08859 if (p->cidcwexpire) {
08860 if (!--p->cidcwexpire) {
08861
08862 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
08863 restore_conference(p);
08864 }
08865 }
08866 if (p->cid_suppress_expire) {
08867 --p->cid_suppress_expire;
08868 }
08869 if (p->callwaitingrepeat) {
08870 if (!--p->callwaitingrepeat) {
08871
08872 ++p->callwaitrings;
08873 dahdi_callwait(ast);
08874 }
08875 }
08876 }
08877 if (p->subs[idx].linear) {
08878 p->subs[idx].f.datalen = READ_SIZE * 2;
08879 } else
08880 p->subs[idx].f.datalen = READ_SIZE;
08881
08882
08883 if ((p->owner == ast) && p->cidspill) {
08884 send_callerid(p);
08885 }
08886
08887 p->subs[idx].f.frametype = AST_FRAME_VOICE;
08888 p->subs[idx].f.subclass.codec = ast->rawreadformat;
08889 p->subs[idx].f.samples = READ_SIZE;
08890 p->subs[idx].f.mallocd = 0;
08891 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
08892 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
08893 #if 0
08894 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
08895 #endif
08896 if (p->dialing || p->radio ||
08897 (idx && (ast->_state != AST_STATE_UP)) ||
08898 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway)
08899 ) {
08900
08901
08902 p->subs[idx].f.frametype = AST_FRAME_NULL;
08903 p->subs[idx].f.subclass.integer = 0;
08904 p->subs[idx].f.samples = 0;
08905 p->subs[idx].f.mallocd = 0;
08906 p->subs[idx].f.offset = 0;
08907 p->subs[idx].f.data.ptr = NULL;
08908 p->subs[idx].f.datalen= 0;
08909 }
08910 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
08911
08912 int mute;
08913
08914 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
08915
08916
08917 mute = ast_dsp_was_muted(p->dsp);
08918 if (p->muting != mute) {
08919 p->muting = mute;
08920 dahdi_confmute(p, mute);
08921 }
08922
08923 if (f) {
08924 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
08925 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
08926
08927
08928 f = NULL;
08929 }
08930 } else if (f->frametype == AST_FRAME_DTMF_BEGIN
08931 || f->frametype == AST_FRAME_DTMF_END) {
08932 #ifdef HAVE_PRI
08933 if (dahdi_sig_pri_lib_handles(p->sig)
08934 && !((struct sig_pri_chan *) p->sig_pvt)->proceeding
08935 && p->pri
08936 && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
08937 || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
08938
08939 ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
08940 f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
08941 f->subclass.integer, f->subclass.integer, ast->name);
08942
08943 f->frametype = AST_FRAME_NULL;
08944 f->subclass.integer = 0;
08945 }
08946 #endif
08947
08948 p->pulsedial = 0;
08949 } else if (p->waitingfordt.tv_sec) {
08950 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
08951 p->waitingfordt.tv_sec = 0;
08952 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
08953 f=NULL;
08954 } else if (f->frametype == AST_FRAME_VOICE) {
08955 f->frametype = AST_FRAME_NULL;
08956 f->subclass.integer = 0;
08957 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) {
08958 p->waitingfordt.tv_sec = 0;
08959 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
08960 ast_dsp_set_features(p->dsp, p->dsp_features);
08961 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
08962 if (!ast_strlen_zero(p->dop.dialstr)) {
08963 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
08964 if (res < 0) {
08965 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
08966 p->dop.dialstr[0] = '\0';
08967 ast_mutex_unlock(&p->lock);
08968 return NULL;
08969 } else {
08970 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
08971 p->dialing = 1;
08972 p->dop.dialstr[0] = '\0';
08973 p->dop.op = DAHDI_DIAL_OP_REPLACE;
08974 ast_setstate(ast, AST_STATE_DIALING);
08975 }
08976 }
08977 }
08978 }
08979 }
08980 }
08981 } else
08982 f = &p->subs[idx].f;
08983
08984 if (f) {
08985 switch (f->frametype) {
08986 case AST_FRAME_DTMF_BEGIN:
08987 case AST_FRAME_DTMF_END:
08988 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
08989 analog_handle_dtmf(p->sig_pvt, ast, idx, &f);
08990 } else {
08991 dahdi_handle_dtmf(ast, idx, &f);
08992 }
08993 break;
08994 case AST_FRAME_VOICE:
08995 if (p->cidspill || p->cid_suppress_expire) {
08996
08997 p->subs[idx].f.frametype = AST_FRAME_NULL;
08998 p->subs[idx].f.subclass.integer = 0;
08999 p->subs[idx].f.samples = 0;
09000 p->subs[idx].f.mallocd = 0;
09001 p->subs[idx].f.offset = 0;
09002 p->subs[idx].f.data.ptr = NULL;
09003 p->subs[idx].f.datalen= 0;
09004 }
09005 break;
09006 default:
09007 break;
09008 }
09009 }
09010
09011
09012 if (p->fake_event)
09013 ast_set_flag(ast, AST_FLAG_EXCEPTION);
09014
09015 ast_mutex_unlock(&p->lock);
09016 return f;
09017 }
09018
09019 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
09020 {
09021 int sent=0;
09022 int size;
09023 int res;
09024 int fd;
09025 fd = p->subs[idx].dfd;
09026 while (len) {
09027 size = len;
09028 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
09029 size = (linear ? READ_SIZE * 2 : READ_SIZE);
09030 res = write(fd, buf, size);
09031 if (res != size) {
09032 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
09033 return sent;
09034 }
09035 len -= size;
09036 buf += size;
09037 }
09038 return sent;
09039 }
09040
09041 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
09042 {
09043 struct dahdi_pvt *p = ast->tech_pvt;
09044 int res;
09045 int idx;
09046 idx = dahdi_get_index(ast, p, 0);
09047 if (idx < 0) {
09048 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
09049 return -1;
09050 }
09051
09052
09053 if (frame->frametype != AST_FRAME_VOICE) {
09054 if (frame->frametype != AST_FRAME_IMAGE)
09055 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
09056 return 0;
09057 }
09058 if ((frame->subclass.codec != AST_FORMAT_SLINEAR) &&
09059 (frame->subclass.codec != AST_FORMAT_ULAW) &&
09060 (frame->subclass.codec != AST_FORMAT_ALAW)) {
09061 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
09062 return -1;
09063 }
09064 if (p->dialing) {
09065 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
09066 return 0;
09067 }
09068 if (!p->owner) {
09069 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
09070 return 0;
09071 }
09072 if (p->cidspill) {
09073 ast_debug(1, "Dropping frame since I've still got a callerid spill on %s...\n",
09074 ast->name);
09075 return 0;
09076 }
09077
09078 if (!frame->data.ptr || !frame->datalen)
09079 return 0;
09080
09081 if (frame->subclass.codec == AST_FORMAT_SLINEAR) {
09082 if (!p->subs[idx].linear) {
09083 p->subs[idx].linear = 1;
09084 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09085 if (res)
09086 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
09087 }
09088 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
09089 } else {
09090
09091 if (p->subs[idx].linear) {
09092 p->subs[idx].linear = 0;
09093 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
09094 if (res)
09095 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
09096 }
09097 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
09098 }
09099 if (res < 0) {
09100 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
09101 return -1;
09102 }
09103 return 0;
09104 }
09105
09106 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
09107 {
09108 struct dahdi_pvt *p = chan->tech_pvt;
09109 int res=-1;
09110 int idx;
09111 int func = DAHDI_FLASH;
09112
09113 ast_mutex_lock(&p->lock);
09114 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
09115 switch (p->sig) {
09116 #if defined(HAVE_PRI)
09117 case SIG_PRI_LIB_HANDLE_CASES:
09118 res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
09119 ast_mutex_unlock(&p->lock);
09120 return res;
09121 #endif
09122 #if defined(HAVE_SS7)
09123 case SIG_SS7:
09124 res = sig_ss7_indicate(p->sig_pvt, chan, condition, data, datalen);
09125 ast_mutex_unlock(&p->lock);
09126 return res;
09127 #endif
09128 default:
09129 break;
09130 }
09131 #ifdef HAVE_OPENR2
09132 if (p->mfcr2 && !p->mfcr2_call_accepted) {
09133 ast_mutex_unlock(&p->lock);
09134
09135
09136 return 0;
09137 }
09138 #endif
09139 idx = dahdi_get_index(chan, p, 0);
09140 if (idx == SUB_REAL) {
09141 switch (condition) {
09142 case AST_CONTROL_BUSY:
09143 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
09144 break;
09145 case AST_CONTROL_RINGING:
09146 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
09147
09148 if (chan->_state != AST_STATE_UP) {
09149 if ((chan->_state != AST_STATE_RING) ||
09150 ((p->sig != SIG_FXSKS) &&
09151 (p->sig != SIG_FXSLS) &&
09152 (p->sig != SIG_FXSGS)))
09153 ast_setstate(chan, AST_STATE_RINGING);
09154 }
09155 break;
09156 case AST_CONTROL_PROCEEDING:
09157 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
09158
09159 res = 0;
09160 break;
09161 case AST_CONTROL_PROGRESS:
09162 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
09163
09164 res = 0;
09165 break;
09166 case AST_CONTROL_CONGESTION:
09167 chan->hangupcause = AST_CAUSE_CONGESTION;
09168 break;
09169 case AST_CONTROL_HOLD:
09170 ast_moh_start(chan, data, p->mohinterpret);
09171 break;
09172 case AST_CONTROL_UNHOLD:
09173 ast_moh_stop(chan);
09174 break;
09175 case AST_CONTROL_RADIO_KEY:
09176 if (p->radio)
09177 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
09178 res = 0;
09179 break;
09180 case AST_CONTROL_RADIO_UNKEY:
09181 if (p->radio)
09182 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
09183 res = 0;
09184 break;
09185 case AST_CONTROL_FLASH:
09186
09187 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
09188
09189 p->dop.dialstr[0] = '\0';
09190 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
09191 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
09192 chan->name, strerror(errno));
09193 } else
09194 res = 0;
09195 } else
09196 res = 0;
09197 break;
09198 case AST_CONTROL_SRCUPDATE:
09199 res = 0;
09200 break;
09201 case -1:
09202 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09203 break;
09204 }
09205 } else {
09206 res = 0;
09207 }
09208 ast_mutex_unlock(&p->lock);
09209 return res;
09210 }
09211
09212 #if defined(HAVE_PRI)
09213 static struct ast_str *create_channel_name(struct dahdi_pvt *i, int is_outgoing, char *address)
09214 #else
09215 static struct ast_str *create_channel_name(struct dahdi_pvt *i)
09216 #endif
09217 {
09218 struct ast_str *chan_name;
09219 int x, y;
09220
09221
09222 if (!(chan_name = ast_str_create(32))) {
09223 return NULL;
09224 }
09225 if (i->channel == CHAN_PSEUDO) {
09226 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
09227 #if defined(HAVE_PRI)
09228 } else if (i->pri) {
09229 ast_mutex_lock(&i->pri->lock);
09230 y = ++i->pri->new_chan_seq;
09231 if (is_outgoing) {
09232 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, address, y);
09233 address[0] = '\0';
09234 } else if (ast_strlen_zero(i->cid_subaddr)) {
09235
09236 ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
09237 } else {
09238
09239 ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
09240 i->cid_subaddr, y);
09241 }
09242 ast_mutex_unlock(&i->pri->lock);
09243 #endif
09244 } else {
09245 y = 1;
09246 do {
09247 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
09248 for (x = 0; x < 3; ++x) {
09249 if (i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name),
09250 i->subs[x].owner->name + 6)) {
09251 break;
09252 }
09253 }
09254 ++y;
09255 } while (x < 3);
09256 }
09257 return chan_name;
09258 }
09259
09260 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int idx, int law, const char *linkedid)
09261 {
09262 struct ast_channel *tmp;
09263 format_t deflaw;
09264 int x;
09265 int features;
09266 struct ast_str *chan_name;
09267 struct ast_variable *v;
09268
09269 if (i->subs[idx].owner) {
09270 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
09271 return NULL;
09272 }
09273
09274 #if defined(HAVE_PRI)
09275
09276
09277
09278
09279 chan_name = create_channel_name(i, i->outgoing, i->dnid);
09280 #else
09281 chan_name = create_channel_name(i);
09282 #endif
09283 if (!chan_name) {
09284 return NULL;
09285 }
09286
09287 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));
09288 ast_free(chan_name);
09289 if (!tmp)
09290 return NULL;
09291 tmp->tech = &dahdi_tech;
09292 #if defined(HAVE_PRI)
09293 if (i->pri) {
09294 ast_cc_copy_config_params(i->cc_params, i->pri->cc_params);
09295 }
09296 #endif
09297 ast_channel_cc_params_init(tmp, i->cc_params);
09298 if (law) {
09299 i->law = law;
09300 if (law == DAHDI_LAW_ALAW) {
09301 deflaw = AST_FORMAT_ALAW;
09302 } else {
09303 deflaw = AST_FORMAT_ULAW;
09304 }
09305 } else {
09306 switch (i->sig) {
09307 case SIG_PRI_LIB_HANDLE_CASES:
09308
09309 i->law = (i->law_default == DAHDI_LAW_ALAW)
09310 ? DAHDI_LAW_ALAW : DAHDI_LAW_MULAW;
09311 break;
09312 default:
09313 i->law = i->law_default;
09314 break;
09315 }
09316 if (i->law_default == DAHDI_LAW_ALAW) {
09317 deflaw = AST_FORMAT_ALAW;
09318 } else {
09319 deflaw = AST_FORMAT_ULAW;
09320 }
09321 }
09322 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
09323 tmp->nativeformats = deflaw;
09324
09325 tmp->rawreadformat = deflaw;
09326 tmp->readformat = deflaw;
09327 tmp->rawwriteformat = deflaw;
09328 tmp->writeformat = deflaw;
09329 i->subs[idx].linear = 0;
09330 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
09331 features = 0;
09332 if (idx == SUB_REAL) {
09333 if (i->busydetect && CANBUSYDETECT(i))
09334 features |= DSP_FEATURE_BUSY_DETECT;
09335 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
09336 features |= DSP_FEATURE_CALL_PROGRESS;
09337 if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
09338 features |= DSP_FEATURE_WAITDIALTONE;
09339 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
09340 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
09341 features |= DSP_FEATURE_FAX_DETECT;
09342 }
09343 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
09344 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
09345 i->hardwaredtmf = 0;
09346 features |= DSP_FEATURE_DIGIT_DETECT;
09347 } else if (NEED_MFDETECT(i)) {
09348 i->hardwaredtmf = 1;
09349 features |= DSP_FEATURE_DIGIT_DETECT;
09350 }
09351 }
09352 if (features) {
09353 if (i->dsp) {
09354 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
09355 } else {
09356 if (i->channel != CHAN_PSEUDO)
09357 i->dsp = ast_dsp_new();
09358 else
09359 i->dsp = NULL;
09360 if (i->dsp) {
09361 i->dsp_features = features;
09362 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09363
09364 if (i->outgoing && (dahdi_sig_pri_lib_handles(i->sig) || (i->sig == SIG_SS7))) {
09365
09366
09367 i->dsp_features = features & ~DSP_PROGRESS_TALK;
09368 features = 0;
09369 }
09370 #endif
09371 ast_dsp_set_features(i->dsp, features);
09372 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
09373 if (!ast_strlen_zero(progzone))
09374 ast_dsp_set_call_progress_zone(i->dsp, progzone);
09375 if (i->busydetect && CANBUSYDETECT(i)) {
09376 ast_dsp_set_busy_count(i->dsp, i->busycount);
09377 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
09378 }
09379 }
09380 }
09381 }
09382
09383 if (state == AST_STATE_RING)
09384 tmp->rings = 1;
09385 tmp->tech_pvt = i;
09386 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
09387
09388 tmp->callgroup = i->callgroup;
09389 tmp->pickupgroup = i->pickupgroup;
09390 }
09391 if (!ast_strlen_zero(i->parkinglot))
09392 ast_string_field_set(tmp, parkinglot, i->parkinglot);
09393 if (!ast_strlen_zero(i->language))
09394 ast_string_field_set(tmp, language, i->language);
09395 if (!i->owner)
09396 i->owner = tmp;
09397 if (!ast_strlen_zero(i->accountcode))
09398 ast_string_field_set(tmp, accountcode, i->accountcode);
09399 if (i->amaflags)
09400 tmp->amaflags = i->amaflags;
09401 i->subs[idx].owner = tmp;
09402 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
09403 if (!analog_lib_handles(i->sig, i->radio, i->oprmode)) {
09404 ast_string_field_set(tmp, call_forward, i->call_forward);
09405 }
09406
09407 if (!i->adsi)
09408 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
09409 if (!ast_strlen_zero(i->exten))
09410 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
09411 if (!ast_strlen_zero(i->rdnis)) {
09412 tmp->redirecting.from.number.valid = 1;
09413 tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
09414 }
09415 if (!ast_strlen_zero(i->dnid)) {
09416 tmp->dialed.number.str = ast_strdup(i->dnid);
09417 }
09418
09419
09420
09421 #if defined(HAVE_PRI) || defined(HAVE_SS7)
09422 if (!ast_strlen_zero(i->cid_ani)) {
09423 tmp->caller.ani.number.valid = 1;
09424 tmp->caller.ani.number.str = ast_strdup(i->cid_ani);
09425 } else if (!ast_strlen_zero(i->cid_num)) {
09426 tmp->caller.ani.number.valid = 1;
09427 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09428 }
09429 #else
09430 if (!ast_strlen_zero(i->cid_num)) {
09431 tmp->caller.ani.number.valid = 1;
09432 tmp->caller.ani.number.str = ast_strdup(i->cid_num);
09433 }
09434 #endif
09435 tmp->caller.id.name.presentation = i->callingpres;
09436 tmp->caller.id.number.presentation = i->callingpres;
09437 tmp->caller.id.number.plan = i->cid_ton;
09438 tmp->caller.ani2 = i->cid_ani2;
09439 tmp->caller.id.tag = ast_strdup(i->cid_tag);
09440
09441 i->fake_event = 0;
09442
09443 dahdi_confmute(i, 0);
09444 i->muting = 0;
09445
09446 ast_jb_configure(tmp, &global_jbconf);
09447
09448 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
09449
09450 for (v = i->vars ; v ; v = v->next)
09451 pbx_builtin_setvar_helper(tmp, v->name, v->value);
09452
09453 ast_module_ref(ast_module_info->self);
09454
09455 if (startpbx) {
09456 #ifdef HAVE_OPENR2
09457 if (i->mfcr2call) {
09458 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
09459 }
09460 #endif
09461 if (ast_pbx_start(tmp)) {
09462 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
09463 ast_hangup(tmp);
09464 return NULL;
09465 }
09466 }
09467 return tmp;
09468 }
09469
09470
09471 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
09472 {
09473 char c;
09474
09475 *str = 0;
09476 for (;;)
09477 {
09478
09479 c = ast_waitfordigit(chan, ms);
09480
09481 if (c < 1)
09482 return c;
09483 *str++ = c;
09484 *str = 0;
09485 if (strchr(term, c))
09486 return 1;
09487 }
09488 }
09489
09490 static int dahdi_wink(struct dahdi_pvt *p, int idx)
09491 {
09492 int j;
09493 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
09494 for (;;)
09495 {
09496
09497 j = DAHDI_IOMUX_SIGEVENT;
09498
09499 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
09500
09501 if (j & DAHDI_IOMUX_SIGEVENT) break;
09502 }
09503
09504 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
09505 return 0;
09506 }
09507
09508
09509
09510
09511
09512
09513
09514
09515
09516
09517 static int dahdi_dnd(struct dahdi_pvt *dahdichan, int flag)
09518 {
09519 if (analog_lib_handles(dahdichan->sig, dahdichan->radio, dahdichan->oprmode)) {
09520 return analog_dnd(dahdichan->sig_pvt, flag);
09521 }
09522
09523 if (flag == -1) {
09524 return dahdichan->dnd;
09525 }
09526
09527
09528 dahdichan->dnd = flag;
09529 ast_verb(3, "%s DND on channel %d\n",
09530 flag? "Enabled" : "Disabled",
09531 dahdichan->channel);
09532 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
09533 "Channel: DAHDI/%d\r\n"
09534 "Status: %s\r\n", dahdichan->channel,
09535 flag? "enabled" : "disabled");
09536
09537 return 0;
09538 }
09539
09540 static void *analog_ss_thread(void *data)
09541 {
09542 struct ast_channel *chan = data;
09543 struct dahdi_pvt *p = chan->tech_pvt;
09544 char exten[AST_MAX_EXTENSION] = "";
09545 char exten2[AST_MAX_EXTENSION] = "";
09546 unsigned char buf[256];
09547 char dtmfcid[300];
09548 char dtmfbuf[300];
09549 struct callerid_state *cs = NULL;
09550 char *name = NULL, *number = NULL;
09551 int distMatches;
09552 int curRingData[3];
09553 int receivedRingT;
09554 int counter1;
09555 int counter;
09556 int samples = 0;
09557 struct ast_smdi_md_message *smdi_msg = NULL;
09558 int flags = 0;
09559 int i;
09560 int timeout;
09561 int getforward = 0;
09562 char *s1, *s2;
09563 int len = 0;
09564 int res;
09565 int idx;
09566
09567 ast_mutex_lock(&ss_thread_lock);
09568 ss_thread_count++;
09569 ast_mutex_unlock(&ss_thread_lock);
09570
09571
09572
09573 if (!p) {
09574 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
09575 ast_hangup(chan);
09576 goto quit;
09577 }
09578 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
09579 idx = dahdi_get_index(chan, p, 1);
09580 if (idx < 0) {
09581 ast_log(LOG_WARNING, "Huh?\n");
09582 ast_hangup(chan);
09583 goto quit;
09584 }
09585 if (p->dsp)
09586 ast_dsp_digitreset(p->dsp);
09587 switch (p->sig) {
09588 case SIG_FEATD:
09589 case SIG_FEATDMF:
09590 case SIG_FEATDMF_TA:
09591 case SIG_E911:
09592 case SIG_FGC_CAMAMF:
09593 case SIG_FEATB:
09594 case SIG_EMWINK:
09595 case SIG_SF_FEATD:
09596 case SIG_SF_FEATDMF:
09597 case SIG_SF_FEATB:
09598 case SIG_SFWINK:
09599 if (dahdi_wink(p, idx))
09600 goto quit;
09601
09602 case SIG_EM:
09603 case SIG_EM_E1:
09604 case SIG_SF:
09605 case SIG_FGC_CAMA:
09606 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09607 if (p->dsp)
09608 ast_dsp_digitreset(p->dsp);
09609
09610 if (p->dsp) {
09611 if (NEED_MFDETECT(p))
09612 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09613 else
09614 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09615 }
09616 memset(dtmfbuf, 0, sizeof(dtmfbuf));
09617
09618 if (!p->immediate)
09619
09620 res = ast_waitfordigit(chan, 5000);
09621 else
09622 res = 0;
09623 if (res > 0) {
09624
09625 dtmfbuf[0] = res;
09626 switch (p->sig) {
09627 case SIG_FEATD:
09628 case SIG_SF_FEATD:
09629 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09630 if (res > 0)
09631 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09632 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09633 break;
09634 case SIG_FEATDMF_TA:
09635 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09636 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09637 if (dahdi_wink(p, idx)) goto quit;
09638 dtmfbuf[0] = 0;
09639
09640 res = ast_waitfordigit(chan, 5000);
09641 if (res <= 0) break;
09642 dtmfbuf[0] = res;
09643
09644 case SIG_FEATDMF:
09645 case SIG_E911:
09646 case SIG_FGC_CAMAMF:
09647 case SIG_SF_FEATDMF:
09648 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09649
09650 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
09651 {
09652 if (dahdi_wink(p, idx)) goto quit;
09653 dtmfbuf[0] = 0;
09654
09655 res = ast_waitfordigit(chan, 5000);
09656 if (res <= 0) break;
09657 dtmfbuf[0] = res;
09658 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09659 }
09660 if (res > 0) {
09661
09662 if (p->sig == SIG_E911)
09663 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09664 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
09665 }
09666 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09667 break;
09668 case SIG_FEATB:
09669 case SIG_SF_FEATB:
09670 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
09671 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09672 break;
09673 case SIG_EMWINK:
09674
09675
09676
09677
09678 if (res == '*') {
09679 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
09680 if (res > 0)
09681 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
09682 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
09683 break;
09684 }
09685 default:
09686
09687 len = 1;
09688 dtmfbuf[len] = '\0';
09689 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09690 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
09691 timeout = matchdigittimeout;
09692 } else {
09693 timeout = gendigittimeout;
09694 }
09695 res = ast_waitfordigit(chan, timeout);
09696 if (res < 0) {
09697 ast_debug(1, "waitfordigit returned < 0...\n");
09698 ast_hangup(chan);
09699 goto quit;
09700 } else if (res) {
09701 dtmfbuf[len++] = res;
09702 dtmfbuf[len] = '\0';
09703 } else {
09704 break;
09705 }
09706 }
09707 break;
09708 }
09709 }
09710 if (res == -1) {
09711 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
09712 ast_hangup(chan);
09713 goto quit;
09714 } else if (res < 0) {
09715 ast_debug(1, "Got hung up before digits finished\n");
09716 ast_hangup(chan);
09717 goto quit;
09718 }
09719
09720 if (p->sig == SIG_FGC_CAMA) {
09721 char anibuf[100];
09722
09723 if (ast_safe_sleep(chan,1000) == -1) {
09724 ast_hangup(chan);
09725 goto quit;
09726 }
09727 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09728 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
09729 res = my_getsigstr(chan, anibuf, "#", 10000);
09730 if ((res > 0) && (strlen(anibuf) > 2)) {
09731 if (anibuf[strlen(anibuf) - 1] == '#')
09732 anibuf[strlen(anibuf) - 1] = 0;
09733 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
09734 }
09735 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09736 }
09737
09738 ast_copy_string(exten, dtmfbuf, sizeof(exten));
09739 if (ast_strlen_zero(exten))
09740 ast_copy_string(exten, "s", sizeof(exten));
09741 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
09742
09743 if (exten[0] == '*') {
09744 char *stringp=NULL;
09745 ast_copy_string(exten2, exten, sizeof(exten2));
09746
09747 stringp=exten2 +1;
09748 s1 = strsep(&stringp, "*");
09749 s2 = strsep(&stringp, "*");
09750 if (s2) {
09751 if (!ast_strlen_zero(p->cid_num))
09752 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09753 else
09754 ast_set_callerid(chan, s1, NULL, s1);
09755 ast_copy_string(exten, s2, sizeof(exten));
09756 } else
09757 ast_copy_string(exten, s1, sizeof(exten));
09758 } else if (p->sig == SIG_FEATD)
09759 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09760 }
09761 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09762 if (exten[0] == '*') {
09763 char *stringp=NULL;
09764 ast_copy_string(exten2, exten, sizeof(exten2));
09765
09766 stringp=exten2 +1;
09767 s1 = strsep(&stringp, "#");
09768 s2 = strsep(&stringp, "#");
09769 if (s2) {
09770 if (!ast_strlen_zero(p->cid_num))
09771 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09772 else
09773 if (*(s1 + 2))
09774 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
09775 ast_copy_string(exten, s2 + 1, sizeof(exten));
09776 } else
09777 ast_copy_string(exten, s1 + 2, sizeof(exten));
09778 } else
09779 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
09780 }
09781 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
09782 if (exten[0] == '*') {
09783 char *stringp=NULL;
09784 ast_copy_string(exten2, exten, sizeof(exten2));
09785
09786 stringp=exten2 +1;
09787 s1 = strsep(&stringp, "#");
09788 s2 = strsep(&stringp, "#");
09789 if (s2 && (*(s2 + 1) == '0')) {
09790 if (*(s2 + 2))
09791 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
09792 }
09793 if (s1) ast_copy_string(exten, s1, sizeof(exten));
09794 else ast_copy_string(exten, "911", sizeof(exten));
09795 } else
09796 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
09797 }
09798 if (p->sig == SIG_FEATB) {
09799 if (exten[0] == '*') {
09800 char *stringp=NULL;
09801 ast_copy_string(exten2, exten, sizeof(exten2));
09802
09803 stringp=exten2 +1;
09804 s1 = strsep(&stringp, "#");
09805 ast_copy_string(exten, exten2 + 1, sizeof(exten));
09806 } else
09807 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
09808 }
09809 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
09810 dahdi_wink(p, idx);
09811
09812
09813
09814 if (ast_safe_sleep(chan,100)) goto quit;
09815 }
09816 dahdi_enable_ec(p);
09817 if (NEED_MFDETECT(p)) {
09818 if (p->dsp) {
09819 if (!p->hardwaredtmf)
09820 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
09821 else {
09822 ast_dsp_free(p->dsp);
09823 p->dsp = NULL;
09824 }
09825 }
09826 }
09827
09828 if (ast_exists_extension(chan, chan->context, exten, 1,
09829 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09830 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09831 if (p->dsp) ast_dsp_digitreset(p->dsp);
09832 res = ast_pbx_run(chan);
09833 if (res) {
09834 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09835 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09836 }
09837 goto quit;
09838 } else {
09839 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
09840 sleep(2);
09841 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
09842 if (res < 0)
09843 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
09844 else
09845 sleep(1);
09846 res = ast_streamfile(chan, "ss-noservice", chan->language);
09847 if (res >= 0)
09848 ast_waitstream(chan, "");
09849 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09850 ast_hangup(chan);
09851 goto quit;
09852 }
09853 break;
09854 case SIG_FXOLS:
09855 case SIG_FXOGS:
09856 case SIG_FXOKS:
09857
09858 timeout = firstdigittimeout;
09859
09860
09861 if (p->subs[SUB_THREEWAY].owner)
09862 timeout = 999999;
09863 while (len < AST_MAX_EXTENSION-1) {
09864
09865
09866 if (p->immediate)
09867 res = 's';
09868 else
09869 res = ast_waitfordigit(chan, timeout);
09870 timeout = 0;
09871 if (res < 0) {
09872 ast_debug(1, "waitfordigit returned < 0...\n");
09873 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09874 ast_hangup(chan);
09875 goto quit;
09876 } else if (res) {
09877 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
09878 exten[len++]=res;
09879 exten[len] = '\0';
09880 }
09881 if (!ast_ignore_pattern(chan->context, exten))
09882 tone_zone_play_tone(p->subs[idx].dfd, -1);
09883 else
09884 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09885 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && !ast_parking_ext_valid(exten, chan, chan->context)) {
09886 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
09887 if (getforward) {
09888
09889 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
09890 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
09891 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09892 if (res)
09893 break;
09894 usleep(500000);
09895 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09896 sleep(1);
09897 memset(exten, 0, sizeof(exten));
09898 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
09899 len = 0;
09900 getforward = 0;
09901 } else {
09902 res = tone_zone_play_tone(p->subs[idx].dfd, -1);
09903 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
09904 if (!ast_strlen_zero(p->cid_num)) {
09905 if (!p->hidecallerid)
09906 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
09907 else
09908 ast_set_callerid(chan, NULL, NULL, p->cid_num);
09909 }
09910 if (!ast_strlen_zero(p->cid_name)) {
09911 if (!p->hidecallerid)
09912 ast_set_callerid(chan, NULL, p->cid_name, NULL);
09913 }
09914 ast_setstate(chan, AST_STATE_RING);
09915 dahdi_enable_ec(p);
09916 res = ast_pbx_run(chan);
09917 if (res) {
09918 ast_log(LOG_WARNING, "PBX exited non-zero\n");
09919 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09920 }
09921 goto quit;
09922 }
09923 } else {
09924
09925
09926 timeout = matchdigittimeout;
09927 }
09928 } else if (res == 0) {
09929 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
09930 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09931 dahdi_wait_event(p->subs[idx].dfd);
09932 ast_hangup(chan);
09933 goto quit;
09934 } else if (p->callwaiting && !strcmp(exten, "*70")) {
09935 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
09936
09937 p->callwaiting = 0;
09938 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09939 if (res) {
09940 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09941 chan->name, strerror(errno));
09942 }
09943 len = 0;
09944 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
09945 memset(exten, 0, sizeof(exten));
09946 timeout = firstdigittimeout;
09947
09948 } else if (!strcmp(exten,ast_pickup_ext())) {
09949
09950
09951
09952
09953 if (idx == SUB_REAL) {
09954
09955 if (p->subs[SUB_THREEWAY].owner) {
09956
09957
09958 alloc_sub(p, SUB_CALLWAIT);
09959 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
09960 unalloc_sub(p, SUB_THREEWAY);
09961 }
09962 dahdi_enable_ec(p);
09963 if (ast_pickup_call(chan)) {
09964 ast_debug(1, "No call pickup possible...\n");
09965 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
09966 dahdi_wait_event(p->subs[idx].dfd);
09967 }
09968 ast_hangup(chan);
09969 goto quit;
09970 } else {
09971 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
09972 ast_hangup(chan);
09973 goto quit;
09974 }
09975
09976 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
09977 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
09978
09979 p->hidecallerid = 1;
09980 ast_party_number_free(&chan->caller.id.number);
09981 ast_party_number_init(&chan->caller.id.number);
09982 ast_party_name_free(&chan->caller.id.name);
09983 ast_party_name_init(&chan->caller.id.name);
09984 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09985 if (res) {
09986 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
09987 chan->name, strerror(errno));
09988 }
09989 len = 0;
09990 memset(exten, 0, sizeof(exten));
09991 timeout = firstdigittimeout;
09992 } else if (p->callreturn && !strcmp(exten, "*69")) {
09993 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09994 break;
09995 } else if (!strcmp(exten, "*78")) {
09996 dahdi_dnd(p, 1);
09997
09998 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
09999 getforward = 0;
10000 memset(exten, 0, sizeof(exten));
10001 len = 0;
10002 } else if (!strcmp(exten, "*79")) {
10003 dahdi_dnd(p, 0);
10004
10005 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10006 getforward = 0;
10007 memset(exten, 0, sizeof(exten));
10008 len = 0;
10009 } else if (p->cancallforward && !strcmp(exten, "*72")) {
10010 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10011 getforward = 1;
10012 memset(exten, 0, sizeof(exten));
10013 len = 0;
10014 } else if (p->cancallforward && !strcmp(exten, "*73")) {
10015 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
10016 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10017 memset(p->call_forward, 0, sizeof(p->call_forward));
10018 getforward = 0;
10019 memset(exten, 0, sizeof(exten));
10020 len = 0;
10021 } else if ((p->transfer || p->canpark) && ast_parking_ext_valid(exten, chan, chan->context) &&
10022 p->subs[SUB_THREEWAY].owner &&
10023 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
10024
10025
10026 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
10027 ast_verb(3, "Parking call to '%s'\n", chan->name);
10028 break;
10029 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
10030 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
10031
10032 p->hidecallerid = 0;
10033 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
10034 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
10035 if (res) {
10036 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
10037 chan->name, strerror(errno));
10038 }
10039 len = 0;
10040 memset(exten, 0, sizeof(exten));
10041 timeout = firstdigittimeout;
10042 } else if (!strcmp(exten, "*0")) {
10043 struct ast_channel *nbridge =
10044 p->subs[SUB_THREEWAY].owner;
10045 struct dahdi_pvt *pbridge = NULL;
10046
10047 if (nbridge && ast_bridged_channel(nbridge))
10048 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
10049 if (nbridge && pbridge &&
10050 (nbridge->tech == &dahdi_tech) &&
10051 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
10052 ISTRUNK(pbridge)) {
10053 int func = DAHDI_FLASH;
10054
10055 p->dop.dialstr[0] = '\0';
10056
10057 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
10058 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
10059 nbridge->name, strerror(errno));
10060 }
10061 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10062 unalloc_sub(p, SUB_THREEWAY);
10063 p->owner = p->subs[SUB_REAL].owner;
10064 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
10065 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
10066 ast_hangup(chan);
10067 goto quit;
10068 } else {
10069 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10070 dahdi_wait_event(p->subs[idx].dfd);
10071 tone_zone_play_tone(p->subs[idx].dfd, -1);
10072 swap_subs(p, SUB_REAL, SUB_THREEWAY);
10073 unalloc_sub(p, SUB_THREEWAY);
10074 p->owner = p->subs[SUB_REAL].owner;
10075 ast_hangup(chan);
10076 goto quit;
10077 }
10078 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
10079 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10080 && ((exten[0] != '*') || (strlen(exten) > 2))) {
10081 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
10082 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
10083 chan->context);
10084 break;
10085 }
10086 if (!timeout)
10087 timeout = gendigittimeout;
10088 if (len && !ast_ignore_pattern(chan->context, exten))
10089 tone_zone_play_tone(p->subs[idx].dfd, -1);
10090 }
10091 break;
10092 case SIG_FXSLS:
10093 case SIG_FXSGS:
10094 case SIG_FXSKS:
10095
10096 if (p->use_smdi && p->smdi_iface) {
10097 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
10098
10099 if (smdi_msg != NULL) {
10100 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
10101
10102 if (smdi_msg->type == 'B')
10103 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
10104 else if (smdi_msg->type == 'N')
10105 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
10106
10107 ast_debug(1, "Received SMDI message on %s\n", chan->name);
10108 } else {
10109 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
10110 }
10111 }
10112
10113 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
10114 number = smdi_msg->calling_st;
10115
10116
10117
10118
10119 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING &&
10120 (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN || p->cid_start == CID_START_DTMF_NOALERT))) {
10121
10122 if (p->cid_signalling == CID_SIG_DTMF) {
10123 int k = 0;
10124 cs = NULL;
10125 ast_debug(1, "Receiving DTMF cid on channel %s\n", chan->name);
10126 dahdi_setlinear(p->subs[idx].dfd, 0);
10127
10128
10129
10130
10131
10132
10133 ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
10134 res = 4000;
10135 for (;;) {
10136 struct ast_frame *f;
10137 res = ast_waitfor(chan, res);
10138 if (res <= 0) {
10139
10140
10141
10142
10143
10144 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10145 "Exiting simple switch\n");
10146 ast_hangup(chan);
10147 goto quit;
10148 }
10149 f = ast_read(chan);
10150 if (!f)
10151 break;
10152 if (f->frametype == AST_FRAME_DTMF) {
10153 if (k < ARRAY_LEN(dtmfbuf) - 1) {
10154 dtmfbuf[k++] = f->subclass.integer;
10155 }
10156 ast_debug(1, "CID got digit '%c'\n", f->subclass.integer);
10157 res = 4000;
10158 }
10159 ast_frfree(f);
10160 if (chan->_state == AST_STATE_RING ||
10161 chan->_state == AST_STATE_RINGING)
10162 break;
10163 }
10164 ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
10165 dtmfbuf[k] = '\0';
10166 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10167
10168 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
10169 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10170 ast_debug(1, "CID is '%s', flags %d\n", dtmfcid, flags);
10171
10172 if (!ast_strlen_zero(dtmfcid))
10173 number = dtmfcid;
10174 else
10175 number = NULL;
10176
10177 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
10178 cs = callerid_new(p->cid_signalling);
10179 if (cs) {
10180 samples = 0;
10181 #if 1
10182 bump_gains(p);
10183 #endif
10184
10185 dahdi_setlinear(p->subs[idx].dfd, 0);
10186
10187
10188 for (;;) {
10189 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10190 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10191 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10192 callerid_free(cs);
10193 ast_hangup(chan);
10194 goto quit;
10195 }
10196 if (i & DAHDI_IOMUX_SIGEVENT) {
10197 res = dahdi_get_event(p->subs[idx].dfd);
10198 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10199 if (res == DAHDI_EVENT_NOALARM) {
10200 p->inalarm = 0;
10201 }
10202
10203 if (p->cid_signalling == CID_SIG_V23_JP) {
10204 if (res == DAHDI_EVENT_RINGBEGIN) {
10205 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
10206 usleep(1);
10207 }
10208 } else {
10209 res = 0;
10210 break;
10211 }
10212 } else if (i & DAHDI_IOMUX_READ) {
10213 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10214 if (res < 0) {
10215 if (errno != ELAST) {
10216 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10217 callerid_free(cs);
10218 ast_hangup(chan);
10219 goto quit;
10220 }
10221 break;
10222 }
10223 samples += res;
10224
10225 if (p->cid_signalling == CID_SIG_V23_JP) {
10226 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
10227 } else {
10228 res = callerid_feed(cs, buf, res, AST_LAW(p));
10229 }
10230 if (res < 0) {
10231
10232
10233
10234
10235 ast_log(LOG_WARNING,
10236 "Failed to decode CallerID on channel '%s'\n",
10237 chan->name);
10238 break;
10239 } else if (res)
10240 break;
10241 else if (samples > (8000 * 10))
10242 break;
10243 }
10244 }
10245 if (res == 1) {
10246 callerid_get(cs, &name, &number, &flags);
10247 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10248 }
10249
10250 if (p->cid_signalling == CID_SIG_V23_JP) {
10251 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10252 usleep(1);
10253 }
10254
10255
10256 res = 4000;
10257 for (;;) {
10258 struct ast_frame *f;
10259 res = ast_waitfor(chan, res);
10260 if (res <= 0) {
10261 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
10262 "Exiting simple switch\n");
10263 ast_hangup(chan);
10264 goto quit;
10265 }
10266 if (!(f = ast_read(chan))) {
10267 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
10268 ast_hangup(chan);
10269 goto quit;
10270 }
10271 ast_frfree(f);
10272 if (chan->_state == AST_STATE_RING ||
10273 chan->_state == AST_STATE_RINGING)
10274 break;
10275 }
10276
10277
10278
10279 if (p->usedistinctiveringdetection) {
10280 len = 0;
10281 distMatches = 0;
10282
10283 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10284 curRingData[receivedRingT] = 0;
10285 receivedRingT = 0;
10286 counter = 0;
10287 counter1 = 0;
10288
10289 if (strcmp(p->context,p->defcontext) != 0) {
10290 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10291 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10292 }
10293
10294 for (;;) {
10295 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10296 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10297 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10298 callerid_free(cs);
10299 ast_hangup(chan);
10300 goto quit;
10301 }
10302 if (i & DAHDI_IOMUX_SIGEVENT) {
10303 res = dahdi_get_event(p->subs[idx].dfd);
10304 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10305 if (res == DAHDI_EVENT_NOALARM) {
10306 p->inalarm = 0;
10307 }
10308 res = 0;
10309
10310
10311 curRingData[receivedRingT] = p->ringt;
10312
10313 if (p->ringt < p->ringt_base/2)
10314 break;
10315
10316
10317 if (++receivedRingT == ARRAY_LEN(curRingData))
10318 break;
10319 } else if (i & DAHDI_IOMUX_READ) {
10320 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10321 if (res < 0) {
10322 if (errno != ELAST) {
10323 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10324 callerid_free(cs);
10325 ast_hangup(chan);
10326 goto quit;
10327 }
10328 break;
10329 }
10330 if (p->ringt > 0) {
10331 if (!(--p->ringt)) {
10332 res = -1;
10333 break;
10334 }
10335 }
10336 }
10337 }
10338
10339 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10340 for (counter = 0; counter < 3; counter++) {
10341
10342
10343 distMatches = 0;
10344 for (counter1 = 0; counter1 < 3; counter1++) {
10345 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10346 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10347 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10348 curRingData[counter1]);
10349 distMatches++;
10350 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10351 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10352 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10353 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10354 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10355 distMatches++;
10356 }
10357 }
10358
10359 if (distMatches == 3) {
10360
10361 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10362 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10363 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10364 break;
10365 }
10366 }
10367 }
10368
10369 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10370 #if 1
10371 restore_gains(p);
10372 #endif
10373 } else
10374 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10375 } else {
10376 ast_log(LOG_WARNING, "Channel %s in prering "
10377 "state, but I have nothing to do. "
10378 "Terminating simple switch, should be "
10379 "restarted by the actual ring.\n",
10380 chan->name);
10381 ast_hangup(chan);
10382 goto quit;
10383 }
10384 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
10385 if (p->cid_signalling == CID_SIG_DTMF) {
10386 int k = 0;
10387 cs = NULL;
10388 dahdi_setlinear(p->subs[idx].dfd, 0);
10389 res = 2000;
10390 for (;;) {
10391 struct ast_frame *f;
10392 res = ast_waitfor(chan, res);
10393 if (res <= 0) {
10394 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
10395 "Exiting simple switch\n");
10396 ast_hangup(chan);
10397 return NULL;
10398 }
10399 f = ast_read(chan);
10400 if (f->frametype == AST_FRAME_DTMF) {
10401 dtmfbuf[k++] = f->subclass.integer;
10402 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass.integer);
10403 res = 2000;
10404 }
10405 ast_frfree(f);
10406
10407 if (p->ringt_base == p->ringt)
10408 break;
10409 }
10410 dtmfbuf[k] = '\0';
10411 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10412
10413 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
10414 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
10415 dtmfcid, flags);
10416
10417 if (!ast_strlen_zero(dtmfcid))
10418 number = dtmfcid;
10419 else
10420 number = NULL;
10421
10422 } else {
10423
10424 cs = callerid_new(p->cid_signalling);
10425 if (cs) {
10426 #if 1
10427 bump_gains(p);
10428 #endif
10429 samples = 0;
10430 len = 0;
10431 distMatches = 0;
10432
10433 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
10434 curRingData[receivedRingT] = 0;
10435 receivedRingT = 0;
10436 counter = 0;
10437 counter1 = 0;
10438
10439 if (strcmp(p->context,p->defcontext) != 0) {
10440 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
10441 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
10442 }
10443
10444
10445 dahdi_setlinear(p->subs[idx].dfd, 0);
10446 for (;;) {
10447 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10448 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10449 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10450 callerid_free(cs);
10451 ast_hangup(chan);
10452 goto quit;
10453 }
10454 if (i & DAHDI_IOMUX_SIGEVENT) {
10455 res = dahdi_get_event(p->subs[idx].dfd);
10456 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10457 if (res == DAHDI_EVENT_NOALARM) {
10458 p->inalarm = 0;
10459 }
10460
10461 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
10462 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
10463 p->polarity = POLARITY_IDLE;
10464 callerid_free(cs);
10465 ast_hangup(chan);
10466 goto quit;
10467 }
10468 res = 0;
10469
10470
10471 curRingData[receivedRingT] = p->ringt;
10472
10473 if (p->ringt < p->ringt_base/2)
10474 break;
10475
10476
10477 if (++receivedRingT == ARRAY_LEN(curRingData))
10478 break;
10479 } else if (i & DAHDI_IOMUX_READ) {
10480 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10481 if (res < 0) {
10482 if (errno != ELAST) {
10483 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10484 callerid_free(cs);
10485 ast_hangup(chan);
10486 goto quit;
10487 }
10488 break;
10489 }
10490 if (p->ringt > 0) {
10491 if (!(--p->ringt)) {
10492 res = -1;
10493 break;
10494 }
10495 }
10496 samples += res;
10497 res = callerid_feed(cs, buf, res, AST_LAW(p));
10498 if (res < 0) {
10499
10500
10501
10502
10503 ast_log(LOG_WARNING,
10504 "Failed to decode CallerID on channel '%s'\n",
10505 chan->name);
10506 break;
10507 } else if (res)
10508 break;
10509 else if (samples > (8000 * 10))
10510 break;
10511 }
10512 }
10513 if (res == 1) {
10514 callerid_get(cs, &name, &number, &flags);
10515 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
10516 }
10517 if (distinctiveringaftercid == 1) {
10518
10519 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
10520 curRingData[receivedRingT] = 0;
10521 }
10522 receivedRingT = 0;
10523 ast_verb(3, "Detecting post-CID distinctive ring\n");
10524 for (;;) {
10525 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10526 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
10527 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10528 callerid_free(cs);
10529 ast_hangup(chan);
10530 goto quit;
10531 }
10532 if (i & DAHDI_IOMUX_SIGEVENT) {
10533 res = dahdi_get_event(p->subs[idx].dfd);
10534 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
10535 if (res == DAHDI_EVENT_NOALARM) {
10536 p->inalarm = 0;
10537 }
10538 res = 0;
10539
10540
10541 curRingData[receivedRingT] = p->ringt;
10542
10543 if (p->ringt < p->ringt_base/2)
10544 break;
10545
10546
10547 if (++receivedRingT == ARRAY_LEN(curRingData))
10548 break;
10549 } else if (i & DAHDI_IOMUX_READ) {
10550 res = read(p->subs[idx].dfd, buf, sizeof(buf));
10551 if (res < 0) {
10552 if (errno != ELAST) {
10553 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10554 callerid_free(cs);
10555 ast_hangup(chan);
10556 goto quit;
10557 }
10558 break;
10559 }
10560 if (p->ringt > 0) {
10561 if (!(--p->ringt)) {
10562 res = -1;
10563 break;
10564 }
10565 }
10566 }
10567 }
10568 }
10569 if (p->usedistinctiveringdetection) {
10570
10571 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
10572
10573 for (counter = 0; counter < 3; counter++) {
10574
10575
10576
10577 ast_verb(3, "Checking %d,%d,%d\n",
10578 p->drings.ringnum[counter].ring[0],
10579 p->drings.ringnum[counter].ring[1],
10580 p->drings.ringnum[counter].ring[2]);
10581 distMatches = 0;
10582 for (counter1 = 0; counter1 < 3; counter1++) {
10583 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
10584 if (p->drings.ringnum[counter].ring[counter1] == -1) {
10585 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
10586 curRingData[counter1]);
10587 distMatches++;
10588 }
10589 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
10590 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
10591 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
10592 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
10593 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
10594 distMatches++;
10595 }
10596 }
10597 if (distMatches == 3) {
10598
10599 ast_copy_string(p->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(p->context));
10600 ast_copy_string(chan->context, S_OR(p->drings.ringContext[counter].contextData, p->defcontext), sizeof(chan->context));
10601 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
10602 break;
10603 }
10604 }
10605 }
10606
10607 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
10608 #if 1
10609 restore_gains(p);
10610 #endif
10611 if (res < 0) {
10612 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
10613 }
10614 } else
10615 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
10616 }
10617 } else
10618 cs = NULL;
10619
10620 if (number)
10621 ast_shrink_phone_number(number);
10622 ast_set_callerid(chan, number, name, number);
10623
10624 if (smdi_msg)
10625 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
10626
10627 if (cs)
10628 callerid_free(cs);
10629
10630 my_handle_notify_message(chan, p, flags, -1);
10631
10632 ast_setstate(chan, AST_STATE_RING);
10633 chan->rings = 1;
10634 p->ringt = p->ringt_base;
10635 res = ast_pbx_run(chan);
10636 if (res) {
10637 ast_hangup(chan);
10638 ast_log(LOG_WARNING, "PBX exited non-zero\n");
10639 }
10640 goto quit;
10641 default:
10642 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
10643 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10644 if (res < 0)
10645 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10646 }
10647 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
10648 if (res < 0)
10649 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
10650 ast_hangup(chan);
10651 quit:
10652 ast_mutex_lock(&ss_thread_lock);
10653 ss_thread_count--;
10654 ast_cond_signal(&ss_thread_complete);
10655 ast_mutex_unlock(&ss_thread_lock);
10656 return NULL;
10657 }
10658
10659 struct mwi_thread_data {
10660 struct dahdi_pvt *pvt;
10661 unsigned char buf[READ_SIZE];
10662 size_t len;
10663 };
10664
10665 static int calc_energy(const unsigned char *buf, int len, format_t law)
10666 {
10667 int x;
10668 int sum = 0;
10669
10670 if (!len)
10671 return 0;
10672
10673 for (x = 0; x < len; x++)
10674 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
10675
10676 return sum / len;
10677 }
10678
10679 static void *mwi_thread(void *data)
10680 {
10681 struct mwi_thread_data *mtd = data;
10682 struct callerid_state *cs;
10683 pthread_t threadid;
10684 int samples = 0;
10685 char *name, *number;
10686 int flags;
10687 int i, res;
10688 unsigned int spill_done = 0;
10689 int spill_result = -1;
10690
10691 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
10692 mtd->pvt->mwimonitoractive = 0;
10693
10694 return NULL;
10695 }
10696
10697 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
10698
10699 bump_gains(mtd->pvt);
10700
10701 for (;;) {
10702 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
10703 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
10704 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
10705 goto quit;
10706 }
10707
10708 if (i & DAHDI_IOMUX_SIGEVENT) {
10709 struct ast_channel *chan;
10710
10711
10712
10713
10714 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
10715
10716 switch (res) {
10717 case DAHDI_EVENT_NEONMWI_ACTIVE:
10718 case DAHDI_EVENT_NEONMWI_INACTIVE:
10719 case DAHDI_EVENT_NONE:
10720 case DAHDI_EVENT_BITSCHANGED:
10721 break;
10722 case DAHDI_EVENT_NOALARM:
10723 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10724 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10725
10726 analog_p->inalarm = 0;
10727 }
10728 mtd->pvt->inalarm = 0;
10729 handle_clear_alarms(mtd->pvt);
10730 break;
10731 case DAHDI_EVENT_ALARM:
10732 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10733 struct analog_pvt *analog_p = mtd->pvt->sig_pvt;
10734
10735 analog_p->inalarm = 1;
10736 }
10737 mtd->pvt->inalarm = 1;
10738 res = get_alarms(mtd->pvt);
10739 handle_alarms(mtd->pvt, res);
10740 break;
10741 default:
10742 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to analog_ss_thread\n", res, event2str(res));
10743 callerid_free(cs);
10744
10745 restore_gains(mtd->pvt);
10746 mtd->pvt->ringt = mtd->pvt->ringt_base;
10747
10748 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, NULL))) {
10749 int result;
10750 if (analog_lib_handles(mtd->pvt->sig, mtd->pvt->radio, mtd->pvt->oprmode)) {
10751 result = analog_ss_thread_start(mtd->pvt->sig_pvt, chan);
10752 } else {
10753 result = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
10754 }
10755 if (result) {
10756 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
10757 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
10758 if (res < 0)
10759 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
10760 ast_hangup(chan);
10761 goto quit;
10762 }
10763 goto quit_no_clean;
10764
10765 } else {
10766 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
10767 }
10768 }
10769 } else if (i & DAHDI_IOMUX_READ) {
10770 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
10771 if (errno != ELAST) {
10772 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
10773 goto quit;
10774 }
10775 break;
10776 }
10777 samples += res;
10778 if (!spill_done) {
10779 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
10780
10781
10782
10783
10784 ast_log(LOG_WARNING, "Failed to decode CallerID\n");
10785 break;
10786 } else if (spill_result) {
10787 spill_done = 1;
10788 }
10789 } else {
10790
10791
10792
10793 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
10794 break;
10795 }
10796 if (samples > (8000 * 4))
10797 break;
10798 }
10799 }
10800
10801 if (spill_result == 1) {
10802 callerid_get(cs, &name, &number, &flags);
10803 if (flags & CID_MSGWAITING) {
10804 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
10805 notify_message(mtd->pvt->mailbox, 1);
10806 } else if (flags & CID_NOMSGWAITING) {
10807 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
10808 notify_message(mtd->pvt->mailbox, 0);
10809 } else {
10810 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
10811 }
10812 }
10813
10814
10815 quit:
10816 callerid_free(cs);
10817
10818 restore_gains(mtd->pvt);
10819
10820 quit_no_clean:
10821 mtd->pvt->mwimonitoractive = 0;
10822
10823 ast_free(mtd);
10824
10825 return NULL;
10826 }
10827
10828
10829
10830
10831
10832
10833
10834
10835 static int mwi_send_init(struct dahdi_pvt * pvt)
10836 {
10837 int x, res;
10838
10839 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10840
10841 if (pvt->mwisend_rpas) {
10842 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10843 pvt->mwisendactive = 1;
10844 } else if (pvt->mwisend_fsk) {
10845 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10846 pvt->mwisendactive = 1;
10847 } else {
10848 pvt->mwisendactive = 0;
10849 return 0;
10850 }
10851 #else
10852 if (mwisend_rpas) {
10853 pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
10854 } else {
10855 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10856 }
10857 pvt->mwisendactive = 1;
10858 #endif
10859
10860 if (pvt->cidspill) {
10861 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
10862 ast_free(pvt->cidspill);
10863 pvt->cidspill = NULL;
10864 pvt->cidpos = 0;
10865 pvt->cidlen = 0;
10866 }
10867 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
10868 if (!pvt->cidspill) {
10869 pvt->mwisendactive = 0;
10870 return -1;
10871 }
10872 x = DAHDI_FLUSH_BOTH;
10873 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
10874 x = 3000;
10875 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
10876 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10877 if (pvt->mwisend_fsk) {
10878 #endif
10879 pvt->cidlen = ast_callerid_vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
10880 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
10881 pvt->cidpos = 0;
10882 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10883 }
10884 #endif
10885 return 0;
10886 }
10887
10888 static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
10889 {
10890 struct timeval now;
10891 int res;
10892
10893
10894
10895
10896 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
10897 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10898 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10899
10900 switch ( pvt->mwisend_data.mwisend_current) {
10901 case MWI_SEND_SA:
10902
10903 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
10904 if (res) {
10905 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
10906 goto quit;
10907 }
10908 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
10909 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
10910 break;
10911 case MWI_SEND_SA_WAIT:
10912 break;
10913 case MWI_SEND_PAUSE:
10914 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10915 if (pvt->mwisend_fsk) {
10916 #endif
10917 gettimeofday(&now, NULL);
10918 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
10919 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
10920 }
10921 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10922 } else {
10923 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10924 }
10925 #endif
10926 break;
10927 case MWI_SEND_SPILL:
10928
10929 if(0 < num_read) {
10930 if (num_read > pvt->cidlen - pvt->cidpos)
10931 num_read = pvt->cidlen - pvt->cidpos;
10932 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
10933 if (res > 0) {
10934 pvt->cidpos += res;
10935 if (pvt->cidpos >= pvt->cidlen) {
10936 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
10937 }
10938 } else {
10939 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
10940 goto quit;
10941 }
10942 }
10943 break;
10944 case MWI_SEND_CLEANUP:
10945
10946 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10947 break;
10948 default:
10949
10950 goto quit;
10951 }
10952 }
10953
10954 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
10955 if (pvt->cidspill) {
10956 ast_free(pvt->cidspill);
10957 pvt->cidspill = NULL;
10958 pvt->cidpos = 0;
10959 pvt->cidlen = 0;
10960 }
10961 pvt->mwisendactive = 0;
10962 }
10963 return 0;
10964 quit:
10965 if (pvt->cidspill) {
10966 ast_free(pvt->cidspill);
10967 pvt->cidspill = NULL;
10968 pvt->cidpos = 0;
10969 pvt->cidlen = 0;
10970 }
10971 pvt->mwisendactive = 0;
10972 return -1;
10973 }
10974
10975 static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
10976 {
10977 int handled = 0;
10978
10979 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
10980 switch (event) {
10981 case DAHDI_EVENT_RINGEROFF:
10982 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
10983 handled = 1;
10984
10985 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
10986 ast_log(LOG_WARNING, "Unable to finish RP-AS: %s mwi send aborted\n", strerror(errno));
10987 ast_free(pvt->cidspill);
10988 pvt->cidspill = NULL;
10989 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
10990 pvt->mwisendactive = 0;
10991 } else {
10992 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
10993 gettimeofday(&pvt->mwisend_data.pause, NULL);
10994 }
10995 }
10996 break;
10997
10998 case DAHDI_EVENT_RINGOFFHOOK:
10999 if (pvt->cidspill) {
11000 ast_free(pvt->cidspill);
11001 pvt->cidspill = NULL;
11002 pvt->cidpos = 0;
11003 pvt->cidlen = 0;
11004 }
11005 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
11006 pvt->mwisendactive = 0;
11007 break;
11008 case DAHDI_EVENT_RINGERON:
11009 case DAHDI_EVENT_HOOKCOMPLETE:
11010 break;
11011 default:
11012 break;
11013 }
11014 }
11015 return handled;
11016 }
11017
11018
11019 static int dahdi_destroy_channel_bynum(int channel)
11020 {
11021 struct dahdi_pvt *cur;
11022
11023 ast_mutex_lock(&iflock);
11024 for (cur = iflist; cur; cur = cur->next) {
11025 if (cur->channel == channel) {
11026 int x = DAHDI_FLASH;
11027
11028
11029 ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11030
11031 destroy_channel(cur, 1);
11032 ast_mutex_unlock(&iflock);
11033 ast_module_unref(ast_module_info->self);
11034 return RESULT_SUCCESS;
11035 }
11036 }
11037 ast_mutex_unlock(&iflock);
11038 return RESULT_FAILURE;
11039 }
11040
11041 static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
11042 {
11043 int res;
11044 pthread_t threadid;
11045 struct ast_channel *chan;
11046
11047
11048
11049 switch (event) {
11050 case DAHDI_EVENT_NONE:
11051 case DAHDI_EVENT_BITSCHANGED:
11052 break;
11053 case DAHDI_EVENT_WINKFLASH:
11054 case DAHDI_EVENT_RINGOFFHOOK:
11055 if (i->inalarm) break;
11056 if (i->radio) break;
11057
11058 switch (i->sig) {
11059 case SIG_FXOLS:
11060 case SIG_FXOGS:
11061 case SIG_FXOKS:
11062 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11063 if (res && (errno == EBUSY))
11064 break;
11065
11066
11067 ast_free(i->cidspill);
11068 i->cidspill = NULL;
11069 restore_conference(i);
11070
11071 if (i->immediate) {
11072 dahdi_enable_ec(i);
11073
11074 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
11075 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, NULL);
11076 if (!chan) {
11077 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
11078 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11079 if (res < 0)
11080 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11081 }
11082 } else {
11083
11084 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, NULL);
11085 if (chan) {
11086 if (has_voicemail(i))
11087 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
11088 else
11089 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
11090 if (res < 0)
11091 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
11092 if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11093 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11094 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11095 if (res < 0)
11096 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11097 ast_hangup(chan);
11098 }
11099 } else
11100 ast_log(LOG_WARNING, "Unable to create channel\n");
11101 }
11102 break;
11103 case SIG_FXSLS:
11104 case SIG_FXSGS:
11105 case SIG_FXSKS:
11106 i->ringt = i->ringt_base;
11107
11108 case SIG_EMWINK:
11109 case SIG_FEATD:
11110 case SIG_FEATDMF:
11111 case SIG_FEATDMF_TA:
11112 case SIG_E911:
11113 case SIG_FGC_CAMA:
11114 case SIG_FGC_CAMAMF:
11115 case SIG_FEATB:
11116 case SIG_EM:
11117 case SIG_EM_E1:
11118 case SIG_SFWINK:
11119 case SIG_SF_FEATD:
11120 case SIG_SF_FEATDMF:
11121 case SIG_SF_FEATB:
11122 case SIG_SF:
11123
11124 if (i->cid_start == CID_START_POLARITY_IN) {
11125 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11126 } else {
11127 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, NULL);
11128 }
11129
11130 if (!chan) {
11131 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11132 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11133 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11134 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11135 if (res < 0) {
11136 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11137 }
11138 ast_hangup(chan);
11139 }
11140 break;
11141 default:
11142 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11143 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
11144 if (res < 0)
11145 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
11146 return NULL;
11147 }
11148 break;
11149 case DAHDI_EVENT_NOALARM:
11150 switch (i->sig) {
11151 #if defined(HAVE_PRI)
11152 case SIG_PRI_LIB_HANDLE_CASES:
11153 sig_pri_chan_alarm_notify(i->sig_pvt, 1);
11154 break;
11155 #endif
11156 #if defined(HAVE_SS7)
11157 case SIG_SS7:
11158 sig_ss7_set_alarm(i->sig_pvt, 0);
11159 break;
11160 #endif
11161 default:
11162 i->inalarm = 0;
11163 break;
11164 }
11165 handle_clear_alarms(i);
11166 break;
11167 case DAHDI_EVENT_ALARM:
11168 switch (i->sig) {
11169 #if defined(HAVE_PRI)
11170 case SIG_PRI_LIB_HANDLE_CASES:
11171 sig_pri_chan_alarm_notify(i->sig_pvt, 0);
11172 break;
11173 #endif
11174 #if defined(HAVE_SS7)
11175 case SIG_SS7:
11176 sig_ss7_set_alarm(i->sig_pvt, 1);
11177 break;
11178 #endif
11179 default:
11180 i->inalarm = 1;
11181 break;
11182 }
11183 res = get_alarms(i);
11184 handle_alarms(i, res);
11185
11186 case DAHDI_EVENT_ONHOOK:
11187 if (i->radio)
11188 break;
11189
11190 switch (i->sig) {
11191 case SIG_FXOLS:
11192 case SIG_FXOGS:
11193 case SIG_FEATD:
11194 case SIG_FEATDMF:
11195 case SIG_FEATDMF_TA:
11196 case SIG_E911:
11197 case SIG_FGC_CAMA:
11198 case SIG_FGC_CAMAMF:
11199 case SIG_FEATB:
11200 case SIG_EM:
11201 case SIG_EM_E1:
11202 case SIG_EMWINK:
11203 case SIG_SF_FEATD:
11204 case SIG_SF_FEATDMF:
11205 case SIG_SF_FEATB:
11206 case SIG_SF:
11207 case SIG_SFWINK:
11208 case SIG_FXSLS:
11209 case SIG_FXSGS:
11210 case SIG_FXSKS:
11211 case SIG_FXOKS:
11212 dahdi_disable_ec(i);
11213
11214 #ifdef ZHONE_HACK
11215 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
11216 usleep(1);
11217 #endif
11218 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11219 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
11220 break;
11221 case SIG_SS7:
11222 case SIG_PRI_LIB_HANDLE_CASES:
11223 dahdi_disable_ec(i);
11224 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11225 break;
11226 default:
11227 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
11228 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
11229 return NULL;
11230 }
11231 break;
11232 case DAHDI_EVENT_POLARITY:
11233 switch (i->sig) {
11234 case SIG_FXSLS:
11235 case SIG_FXSKS:
11236 case SIG_FXSGS:
11237
11238
11239
11240
11241 if (i->hanguponpolarityswitch)
11242 i->polarity = POLARITY_REV;
11243 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
11244 i->polarity = POLARITY_REV;
11245 ast_verb(2, "Starting post polarity "
11246 "CID detection on channel %d\n",
11247 i->channel);
11248 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11249 if (!chan) {
11250 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11251 } else if (ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan)) {
11252 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11253 }
11254 }
11255 break;
11256 default:
11257 ast_log(LOG_WARNING, "handle_init_event detected "
11258 "polarity reversal on non-FXO (SIG_FXS) "
11259 "interface %d\n", i->channel);
11260 }
11261 break;
11262 case DAHDI_EVENT_REMOVED:
11263 ast_log(LOG_NOTICE,
11264 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
11265 i->channel);
11266 return i;
11267 case DAHDI_EVENT_NEONMWI_ACTIVE:
11268 if (i->mwimonitor_neon) {
11269 notify_message(i->mailbox, 1);
11270 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
11271 }
11272 break;
11273 case DAHDI_EVENT_NEONMWI_INACTIVE:
11274 if (i->mwimonitor_neon) {
11275 notify_message(i->mailbox, 0);
11276 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
11277 }
11278 break;
11279 }
11280 return NULL;
11281 }
11282
11283 static void *do_monitor(void *data)
11284 {
11285 int count, res, res2, spoint, pollres=0;
11286 struct dahdi_pvt *i;
11287 struct dahdi_pvt *last = NULL;
11288 struct dahdi_pvt *doomed;
11289 time_t thispass = 0, lastpass = 0;
11290 int found;
11291 char buf[1024];
11292 struct pollfd *pfds=NULL;
11293 int lastalloc = -1;
11294
11295
11296
11297 #if 0
11298 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
11299 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
11300 return NULL;
11301 }
11302 ast_debug(1, "Monitor starting...\n");
11303 #endif
11304 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11305
11306 for (;;) {
11307
11308 ast_mutex_lock(&iflock);
11309 if (!pfds || (lastalloc != ifcount)) {
11310 if (pfds) {
11311 ast_free(pfds);
11312 pfds = NULL;
11313 }
11314 if (ifcount) {
11315 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
11316 ast_mutex_unlock(&iflock);
11317 return NULL;
11318 }
11319 }
11320 lastalloc = ifcount;
11321 }
11322
11323
11324 count = 0;
11325 for (i = iflist; i; i = i->next) {
11326 ast_mutex_lock(&i->lock);
11327 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
11328 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11329 struct analog_pvt *p = i->sig_pvt;
11330
11331 if (!p)
11332 ast_log(LOG_ERROR, "No sig_pvt?\n");
11333
11334 if (!p->owner && !p->subs[SUB_REAL].owner) {
11335
11336 pfds[count].fd = i->subs[SUB_REAL].dfd;
11337 pfds[count].events = POLLPRI;
11338 pfds[count].revents = 0;
11339
11340 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11341 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11342 pfds[count].events |= POLLIN;
11343 }
11344 count++;
11345 }
11346 } else {
11347 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
11348
11349 pfds[count].fd = i->subs[SUB_REAL].dfd;
11350 pfds[count].events = POLLPRI;
11351 pfds[count].revents = 0;
11352
11353
11354 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk ||
11355 (i->cid_start == CID_START_DTMF_NOALERT && (i->sig == SIG_FXSLS || i->sig == SIG_FXSGS || i->sig == SIG_FXSKS))) {
11356 pfds[count].events |= POLLIN;
11357 }
11358 count++;
11359 }
11360 }
11361 }
11362 ast_mutex_unlock(&i->lock);
11363 }
11364
11365 ast_mutex_unlock(&iflock);
11366
11367 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11368 pthread_testcancel();
11369
11370 res = poll(pfds, count, 1000);
11371 pthread_testcancel();
11372 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11373
11374
11375 if (res < 0) {
11376 if ((errno != EAGAIN) && (errno != EINTR))
11377 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
11378 continue;
11379 }
11380
11381
11382 ast_mutex_lock(&iflock);
11383 found = 0;
11384 spoint = 0;
11385 lastpass = thispass;
11386 thispass = time(NULL);
11387 doomed = NULL;
11388 for (i = iflist;; i = i->next) {
11389 if (doomed) {
11390 int res;
11391 res = dahdi_destroy_channel_bynum(doomed->channel);
11392 if (res != RESULT_SUCCESS) {
11393 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
11394 }
11395 doomed = NULL;
11396 }
11397 if (!i) {
11398 break;
11399 }
11400
11401 if (thispass != lastpass) {
11402 if (!found && ((i == last) || ((i == iflist) && !last))) {
11403 last = i;
11404 if (last) {
11405 struct analog_pvt *analog_p = last->sig_pvt;
11406
11407 if (analog_p
11408 && !last->mwisendactive
11409 && (last->sig & __DAHDI_SIG_FXO)
11410 && !analog_p->fxsoffhookstate
11411 && !last->owner
11412 && !ast_strlen_zero(last->mailbox)
11413 && (thispass - analog_p->onhooktime > 3)) {
11414 res = has_voicemail(last);
11415 if (analog_p->msgstate != res) {
11416
11417 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
11418 if (res2) {
11419
11420 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
11421 }
11422
11423 if (mwi_send_init(last)) {
11424 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
11425 }
11426 analog_p->msgstate = res;
11427 found ++;
11428 }
11429 }
11430 last = last->next;
11431 }
11432 }
11433 }
11434 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
11435 if (i->radio && !i->owner)
11436 {
11437 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11438 if (res)
11439 {
11440 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
11441
11442 ast_mutex_unlock(&iflock);
11443 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11444 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11445 else
11446 doomed = handle_init_event(i, res);
11447 ast_mutex_lock(&iflock);
11448 }
11449 continue;
11450 }
11451 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
11452 if (pollres & POLLIN) {
11453 if (i->owner || i->subs[SUB_REAL].owner) {
11454 #ifdef HAVE_PRI
11455 if (!i->pri)
11456 #endif
11457 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
11458 continue;
11459 }
11460 if (!i->mwimonitor_fsk && !i->mwisendactive && i->cid_start != CID_START_DTMF_NOALERT) {
11461 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
11462 continue;
11463 }
11464 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
11465 if (res > 0) {
11466 if (i->mwimonitor_fsk) {
11467 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
11468 pthread_attr_t attr;
11469 pthread_t threadid;
11470 struct mwi_thread_data *mtd;
11471
11472 pthread_attr_init(&attr);
11473 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
11474
11475 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
11476 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
11477 mtd->pvt = i;
11478 memcpy(mtd->buf, buf, res);
11479 mtd->len = res;
11480 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
11481 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
11482 ast_free(mtd);
11483 }
11484 i->mwimonitoractive = 1;
11485 }
11486 }
11487
11488 } else if (i->cid_start == CID_START_DTMF_NOALERT) {
11489 int energy;
11490 struct timeval now;
11491
11492
11493
11494 if (1 == i->dtmfcid_holdoff_state) {
11495 gettimeofday(&i->dtmfcid_delay, NULL);
11496 i->dtmfcid_holdoff_state = 2;
11497 } else if (2 == i->dtmfcid_holdoff_state) {
11498 gettimeofday(&now, NULL);
11499 if ((int)(now.tv_sec - i->dtmfcid_delay.tv_sec) * 1000000 + (int)now.tv_usec - (int)i->dtmfcid_delay.tv_usec > 500000) {
11500 i->dtmfcid_holdoff_state = 0;
11501 }
11502 } else {
11503 energy = calc_energy((unsigned char *) buf, res, AST_LAW(i));
11504 if (!i->mwisendactive && energy > dtmfcid_level) {
11505 pthread_t threadid;
11506 struct ast_channel *chan;
11507 ast_mutex_unlock(&iflock);
11508 if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
11509
11510 doomed = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);
11511 i->dtmfcid_holdoff_state = 1;
11512 } else {
11513 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, NULL);
11514 if (!chan) {
11515 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
11516 } else {
11517 res = ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, chan);
11518 if (res) {
11519 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
11520 } else {
11521 i->dtmfcid_holdoff_state = 1;
11522 }
11523 }
11524 }
11525 ast_mutex_lock(&iflock);
11526 }
11527 }
11528 }
11529 if (i->mwisendactive) {
11530 mwi_send_process_buffer(i, res);
11531 }
11532 } else {
11533 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
11534 }
11535 }
11536 if (pollres & POLLPRI) {
11537 if (i->owner || i->subs[SUB_REAL].owner) {
11538 #ifdef HAVE_PRI
11539 if (!i->pri)
11540 #endif
11541 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
11542 continue;
11543 }
11544 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
11545 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
11546
11547 ast_mutex_unlock(&iflock);
11548 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
11549 if (analog_lib_handles(i->sig, i->radio, i->oprmode))
11550 doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
11551 else
11552 doomed = handle_init_event(i, res);
11553 }
11554 ast_mutex_lock(&iflock);
11555 }
11556 }
11557 }
11558 ast_mutex_unlock(&iflock);
11559 }
11560
11561 return NULL;
11562
11563 }
11564
11565 static int restart_monitor(void)
11566 {
11567
11568 if (monitor_thread == AST_PTHREADT_STOP)
11569 return 0;
11570 ast_mutex_lock(&monlock);
11571 if (monitor_thread == pthread_self()) {
11572 ast_mutex_unlock(&monlock);
11573 ast_log(LOG_WARNING, "Cannot kill myself\n");
11574 return -1;
11575 }
11576 if (monitor_thread != AST_PTHREADT_NULL) {
11577
11578 pthread_kill(monitor_thread, SIGURG);
11579 } else {
11580
11581 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
11582 ast_mutex_unlock(&monlock);
11583 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
11584 return -1;
11585 }
11586 }
11587 ast_mutex_unlock(&monlock);
11588 return 0;
11589 }
11590
11591 #if defined(HAVE_PRI)
11592 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
11593 {
11594 int x;
11595 int trunkgroup;
11596
11597 trunkgroup = pris[*span].mastertrunkgroup;
11598 if (trunkgroup) {
11599
11600 for (x = 0; x < NUM_SPANS; x++) {
11601 if (pris[x].pri.trunkgroup == trunkgroup) {
11602 *span = x;
11603 return 0;
11604 }
11605 }
11606 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
11607 *span = -1;
11608 } else {
11609 if (pris[*span].pri.trunkgroup) {
11610 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);
11611 *span = -1;
11612 } else if (pris[*span].mastertrunkgroup) {
11613 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
11614 *span = -1;
11615 } else {
11616 if (si->totalchans == 31) {
11617
11618 pris[*span].dchannels[0] = 16 + offset;
11619 } else if (si->totalchans == 24) {
11620
11621 pris[*span].dchannels[0] = 24 + offset;
11622 } else if (si->totalchans == 3) {
11623
11624 pris[*span].dchannels[0] = 3 + offset;
11625 } else {
11626 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);
11627 *span = -1;
11628 return 0;
11629 }
11630 pris[*span].pri.span = *span + 1;
11631 }
11632 }
11633 return 0;
11634 }
11635 #endif
11636
11637 #if defined(HAVE_PRI)
11638 static int pri_create_trunkgroup(int trunkgroup, int *channels)
11639 {
11640 struct dahdi_spaninfo si;
11641 struct dahdi_params p;
11642 int fd;
11643 int span;
11644 int ospan=0;
11645 int x,y;
11646 for (x = 0; x < NUM_SPANS; x++) {
11647 if (pris[x].pri.trunkgroup == trunkgroup) {
11648 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
11649 return -1;
11650 }
11651 }
11652 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
11653 if (!channels[y])
11654 break;
11655 memset(&si, 0, sizeof(si));
11656 memset(&p, 0, sizeof(p));
11657 fd = open("/dev/dahdi/channel", O_RDWR);
11658 if (fd < 0) {
11659 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
11660 return -1;
11661 }
11662 x = channels[y];
11663 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
11664 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
11665 close(fd);
11666 return -1;
11667 }
11668 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
11669 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
11670 return -1;
11671 }
11672 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
11673 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
11674 close(fd);
11675 return -1;
11676 }
11677 span = p.spanno - 1;
11678 if (pris[span].pri.trunkgroup) {
11679 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
11680 close(fd);
11681 return -1;
11682 }
11683 if (pris[span].pri.pvts[0]) {
11684 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
11685 close(fd);
11686 return -1;
11687 }
11688 if (!y) {
11689 pris[span].pri.trunkgroup = trunkgroup;
11690 ospan = span;
11691 }
11692 pris[ospan].dchannels[y] = channels[y];
11693 pris[span].pri.span = span + 1;
11694 close(fd);
11695 }
11696 return 0;
11697 }
11698 #endif
11699
11700 #if defined(HAVE_PRI)
11701 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
11702 {
11703 if (pris[span].mastertrunkgroup) {
11704 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);
11705 return -1;
11706 }
11707 pris[span].mastertrunkgroup = trunkgroup;
11708 pris[span].prilogicalspan = logicalspan;
11709 return 0;
11710 }
11711 #endif
11712
11713 #if defined(HAVE_SS7)
11714 static unsigned int parse_pointcode(const char *pcstring)
11715 {
11716 unsigned int code1, code2, code3;
11717 int numvals;
11718
11719 numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
11720 if (numvals == 1)
11721 return code1;
11722 if (numvals == 3)
11723 return (code1 << 16) | (code2 << 8) | code3;
11724
11725 return 0;
11726 }
11727 #endif
11728
11729 #if defined(HAVE_SS7)
11730 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
11731 {
11732 if ((linkset < 0) || (linkset >= NUM_SPANS))
11733 return NULL;
11734 else
11735 return &linksets[linkset - 1];
11736 }
11737 #endif
11738
11739 #ifdef HAVE_OPENR2
11740 static void dahdi_r2_destroy_links(void)
11741 {
11742 int i = 0;
11743 if (!r2links) {
11744 return;
11745 }
11746 for (; i < r2links_count; i++) {
11747 if (r2links[i]->r2master != AST_PTHREADT_NULL) {
11748 pthread_cancel(r2links[i]->r2master);
11749 pthread_join(r2links[i]->r2master, NULL);
11750 openr2_context_delete(r2links[i]->protocol_context);
11751 }
11752 ast_free(r2links[i]);
11753 }
11754 ast_free(r2links);
11755 r2links = NULL;
11756 r2links_count = 0;
11757 }
11758
11759 #define R2_LINK_CAPACITY 10
11760 static struct dahdi_mfcr2 *dahdi_r2_get_link(void)
11761 {
11762 struct dahdi_mfcr2 *new_r2link = NULL;
11763 struct dahdi_mfcr2 **new_r2links = NULL;
11764
11765
11766 if (!r2links_count || (r2links[r2links_count - 1]->monitored_count == R2_LINK_CAPACITY)) {
11767 new_r2link = ast_calloc(1, sizeof(**r2links));
11768 if (!new_r2link) {
11769 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11770 return NULL;
11771 }
11772 new_r2links = ast_realloc(r2links, ((r2links_count + 1) * sizeof(*r2links)));
11773 if (!new_r2links) {
11774 ast_log(LOG_ERROR, "Cannot allocate R2 link!\n");
11775 ast_free(new_r2link);
11776 return NULL;
11777 }
11778 r2links = new_r2links;
11779 new_r2link->r2master = AST_PTHREADT_NULL;
11780 r2links[r2links_count] = new_r2link;
11781 r2links_count++;
11782 ast_log(LOG_DEBUG, "Created new R2 link!\n");
11783 }
11784 return r2links[r2links_count - 1];
11785 }
11786
11787 static int dahdi_r2_set_context(struct dahdi_mfcr2 *r2_link, const struct dahdi_chan_conf *conf)
11788 {
11789 char tmplogdir[] = "/tmp";
11790 char logdir[OR2_MAX_PATH];
11791 int threshold = 0;
11792 int snres = 0;
11793 r2_link->protocol_context = openr2_context_new(NULL, &dahdi_r2_event_iface,
11794 &dahdi_r2_transcode_iface, conf->mfcr2.variant, conf->mfcr2.max_ani,
11795 conf->mfcr2.max_dnis);
11796 if (!r2_link->protocol_context) {
11797 return -1;
11798 }
11799 openr2_context_set_log_level(r2_link->protocol_context, conf->mfcr2.loglevel);
11800 openr2_context_set_ani_first(r2_link->protocol_context, conf->mfcr2.get_ani_first);
11801 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
11802 openr2_context_set_skip_category_request(r2_link->protocol_context, conf->mfcr2.skip_category_request);
11803 #endif
11804 openr2_context_set_mf_threshold(r2_link->protocol_context, threshold);
11805 openr2_context_set_mf_back_timeout(r2_link->protocol_context, conf->mfcr2.mfback_timeout);
11806 openr2_context_set_metering_pulse_timeout(r2_link->protocol_context, conf->mfcr2.metering_pulse_timeout);
11807 openr2_context_set_double_answer(r2_link->protocol_context, conf->mfcr2.double_answer);
11808 openr2_context_set_immediate_accept(r2_link->protocol_context, conf->mfcr2.immediate_accept);
11809 if (ast_strlen_zero(conf->mfcr2.logdir)) {
11810 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11811 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11812 }
11813 } else {
11814 snres = snprintf(logdir, sizeof(logdir), "%s/%s/%s", ast_config_AST_LOG_DIR, "mfcr2", conf->mfcr2.logdir);
11815 if (snres >= sizeof(logdir)) {
11816 ast_log(LOG_ERROR, "MFC/R2 logging directory truncated, using %s\n", tmplogdir);
11817 if (openr2_context_set_log_directory(r2_link->protocol_context, tmplogdir)) {
11818 ast_log(LOG_ERROR, "Failed setting default MFC/R2 log directory %s\n", tmplogdir);
11819 }
11820 } else {
11821 if (openr2_context_set_log_directory(r2_link->protocol_context, logdir)) {
11822 ast_log(LOG_ERROR, "Failed setting MFC/R2 log directory %s\n", logdir);
11823 }
11824 }
11825 }
11826 if (!ast_strlen_zero(conf->mfcr2.r2proto_file)) {
11827 if (openr2_context_configure_from_advanced_file(r2_link->protocol_context, conf->mfcr2.r2proto_file)) {
11828 ast_log(LOG_ERROR, "Failed to configure r2context from advanced configuration file %s\n", conf->mfcr2.r2proto_file);
11829 }
11830 }
11831 r2_link->monitored_count = 0;
11832 return 0;
11833 }
11834 #endif
11835
11836
11837
11838
11839
11840
11841 static int sigtype_to_signalling(int sigtype)
11842 {
11843 return sigtype;
11844 }
11845
11846
11847
11848
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858 static int device2chan(const char *subdir, int channel, char *path, int pathlen)
11859 {
11860 struct stat stbuf;
11861 int num;
11862
11863 snprintf(path, pathlen, "/dev/dahdi/%s/%d", subdir, channel);
11864 if (stat(path, &stbuf) < 0) {
11865 ast_log(LOG_ERROR, "stat(%s) failed: %s\n", path, strerror(errno));
11866 return -errno;
11867 }
11868 if (!S_ISCHR(stbuf.st_mode)) {
11869 ast_log(LOG_ERROR, "%s: Not a character device file\n", path);
11870 return -EINVAL;
11871 }
11872 num = minor(stbuf.st_rdev);
11873 ast_log(LOG_DEBUG, "%s -> %d\n", path, num);
11874 return num;
11875
11876 }
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
11893 {
11894
11895 struct dahdi_pvt *tmp;
11896 char fn[80];
11897 struct dahdi_bufferinfo bi;
11898
11899 int res;
11900 int span = 0;
11901 int here = 0;
11902 int x;
11903 struct analog_pvt *analog_p = NULL;
11904 struct dahdi_params p;
11905 #if defined(HAVE_PRI)
11906 struct dahdi_spaninfo si;
11907 struct sig_pri_chan *pri_chan = NULL;
11908 #endif
11909 #if defined(HAVE_SS7)
11910 struct sig_ss7_chan *ss7_chan = NULL;
11911 #endif
11912
11913
11914 for (tmp = iflist; tmp; tmp = tmp->next) {
11915 if (!tmp->destroy) {
11916 if (tmp->channel == channel) {
11917
11918 here = 1;
11919 break;
11920 }
11921 if (tmp->channel > channel) {
11922
11923 tmp = NULL;
11924 break;
11925 }
11926 }
11927 }
11928
11929 if (!here && reloading != 1) {
11930 tmp = ast_calloc(1, sizeof(*tmp));
11931 if (!tmp) {
11932 return NULL;
11933 }
11934 tmp->cc_params = ast_cc_config_params_init();
11935 if (!tmp->cc_params) {
11936 ast_free(tmp);
11937 return NULL;
11938 }
11939 ast_mutex_init(&tmp->lock);
11940 ifcount++;
11941 for (x = 0; x < 3; x++)
11942 tmp->subs[x].dfd = -1;
11943 tmp->channel = channel;
11944 tmp->priindication_oob = conf->chan.priindication_oob;
11945 }
11946
11947 if (tmp) {
11948 int chan_sig = conf->chan.sig;
11949
11950 if (!here) {
11951
11952 if ((channel != CHAN_PSEUDO)) {
11953 int count = 0;
11954
11955 snprintf(fn, sizeof(fn), "%d", channel);
11956
11957 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11958 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) {
11959 usleep(1);
11960 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
11961 count++;
11962 }
11963
11964 if (tmp->subs[SUB_REAL].dfd < 0) {
11965 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);
11966 destroy_dahdi_pvt(tmp);
11967 return NULL;
11968 }
11969 memset(&p, 0, sizeof(p));
11970 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
11971 if (res < 0) {
11972 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
11973 destroy_dahdi_pvt(tmp);
11974 return NULL;
11975 }
11976 if (conf->is_sig_auto)
11977 chan_sig = sigtype_to_signalling(p.sigtype);
11978 if (p.sigtype != (chan_sig & 0x3ffff)) {
11979 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));
11980 destroy_dahdi_pvt(tmp);
11981 return NULL;
11982 }
11983 tmp->law_default = p.curlaw;
11984 tmp->law = p.curlaw;
11985 tmp->span = p.spanno;
11986 span = p.spanno - 1;
11987 } else {
11988 chan_sig = 0;
11989 }
11990 tmp->sig = chan_sig;
11991 tmp->outsigmod = conf->chan.outsigmod;
11992
11993 if (analog_lib_handles(chan_sig, tmp->radio, tmp->oprmode)) {
11994 analog_p = analog_new(dahdisig_to_analogsig(chan_sig), &dahdi_analog_callbacks, tmp);
11995 if (!analog_p) {
11996 destroy_dahdi_pvt(tmp);
11997 return NULL;
11998 }
11999 tmp->sig_pvt = analog_p;
12000 }
12001 #if defined(HAVE_SS7)
12002 if (chan_sig == SIG_SS7) {
12003 struct dahdi_ss7 *ss7;
12004 int clear = 0;
12005
12006 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
12007 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12008 destroy_dahdi_pvt(tmp);
12009 return NULL;
12010 }
12011
12012 ss7 = ss7_resolve_linkset(cur_linkset);
12013 if (!ss7) {
12014 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
12015 destroy_dahdi_pvt(tmp);
12016 return NULL;
12017 }
12018 ss7->ss7.span = cur_linkset;
12019 if (cur_cicbeginswith < 0) {
12020 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
12021 destroy_dahdi_pvt(tmp);
12022 return NULL;
12023 }
12024 ss7_chan = sig_ss7_chan_new(tmp, &dahdi_ss7_callbacks, &ss7->ss7);
12025 if (!ss7_chan) {
12026 destroy_dahdi_pvt(tmp);
12027 return NULL;
12028 }
12029 tmp->sig_pvt = ss7_chan;
12030 tmp->ss7 = &ss7->ss7;
12031
12032 ss7_chan->channel = tmp->channel;
12033 ss7_chan->cic = cur_cicbeginswith++;
12034
12035
12036 ss7_chan->dpc = cur_defaultdpc;
12037
12038 ss7->ss7.pvts[ss7->ss7.numchans++] = ss7_chan;
12039
12040 ast_copy_string(ss7->ss7.internationalprefix, conf->ss7.ss7.internationalprefix, sizeof(ss7->ss7.internationalprefix));
12041 ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
12042 ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
12043 ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
12044
12045 ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
12046 ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
12047 }
12048 #endif
12049 #ifdef HAVE_OPENR2
12050 if (chan_sig == SIG_MFCR2) {
12051 struct dahdi_mfcr2 *r2_link;
12052 r2_link = dahdi_r2_get_link();
12053 if (!r2_link) {
12054 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
12055 destroy_dahdi_pvt(tmp);
12056 return NULL;
12057 }
12058 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
12059 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
12060 destroy_dahdi_pvt(tmp);
12061 return NULL;
12062 }
12063 if (r2_link->numchans == ARRAY_LEN(r2_link->pvts)) {
12064 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
12065 destroy_dahdi_pvt(tmp);
12066 return NULL;
12067 }
12068 r2_link->pvts[r2_link->numchans++] = tmp;
12069 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
12070 tmp->subs[SUB_REAL].dfd,
12071 NULL, NULL);
12072 if (!tmp->r2chan) {
12073 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
12074 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
12075 destroy_dahdi_pvt(tmp);
12076 return NULL;
12077 }
12078 tmp->mfcr2 = r2_link;
12079 if (conf->mfcr2.call_files) {
12080 openr2_chan_enable_call_files(tmp->r2chan);
12081 }
12082 openr2_chan_set_client_data(tmp->r2chan, tmp);
12083
12084 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
12085 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
12086 tmp->mfcr2_category = conf->mfcr2.category;
12087 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
12088 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
12089 tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
12090 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
12091 tmp->mfcr2call = 0;
12092 tmp->mfcr2_dnis_index = 0;
12093 tmp->mfcr2_ani_index = 0;
12094 r2_link->monitored_count++;
12095 }
12096 #endif
12097 #ifdef HAVE_PRI
12098 if (dahdi_sig_pri_lib_handles(chan_sig)) {
12099 int offset;
12100 int matchesdchan;
12101 int x,y;
12102 int myswitchtype = 0;
12103
12104 offset = 0;
12105 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
12106 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
12107 destroy_dahdi_pvt(tmp);
12108 return NULL;
12109 }
12110 if (span >= NUM_SPANS) {
12111 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
12112 destroy_dahdi_pvt(tmp);
12113 return NULL;
12114 } else {
12115 si.spanno = 0;
12116 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12117 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12118 destroy_dahdi_pvt(tmp);
12119 return NULL;
12120 }
12121
12122 tmp->logicalspan = pris[span].prilogicalspan;
12123 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
12124 if (span < 0) {
12125 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
12126 destroy_dahdi_pvt(tmp);
12127 return NULL;
12128 }
12129 myswitchtype = conf->pri.pri.switchtype;
12130
12131 matchesdchan=0;
12132 for (x = 0; x < NUM_SPANS; x++) {
12133 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
12134 if (pris[x].dchannels[y] == tmp->channel) {
12135 matchesdchan = 1;
12136 break;
12137 }
12138 }
12139 }
12140 if (!matchesdchan) {
12141 if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
12142 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
12143 destroy_dahdi_pvt(tmp);
12144 return NULL;
12145 }
12146 if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
12147 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
12148 destroy_dahdi_pvt(tmp);
12149 return NULL;
12150 }
12151 if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
12152 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));
12153 destroy_dahdi_pvt(tmp);
12154 return NULL;
12155 }
12156 if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
12157 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
12158 destroy_dahdi_pvt(tmp);
12159 return NULL;
12160 }
12161 if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
12162 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
12163 destroy_dahdi_pvt(tmp);
12164 return NULL;
12165 }
12166 if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
12167 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
12168 destroy_dahdi_pvt(tmp);
12169 return NULL;
12170 }
12171 if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
12172 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
12173 destroy_dahdi_pvt(tmp);
12174 return NULL;
12175 }
12176 if (pris[span].pri.numchans >= ARRAY_LEN(pris[span].pri.pvts)) {
12177 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
12178 pris[span].pri.trunkgroup);
12179 destroy_dahdi_pvt(tmp);
12180 return NULL;
12181 }
12182
12183 ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
12184 pri_chan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos, pris[span].mastertrunkgroup);
12185 if (!pri_chan) {
12186 destroy_dahdi_pvt(tmp);
12187 return NULL;
12188 }
12189 tmp->sig_pvt = pri_chan;
12190 tmp->pri = &pris[span].pri;
12191
12192 tmp->priexclusive = conf->chan.priexclusive;
12193
12194 if (!tmp->pri->cc_params) {
12195 tmp->pri->cc_params = ast_cc_config_params_init();
12196 if (!tmp->pri->cc_params) {
12197 destroy_dahdi_pvt(tmp);
12198 return NULL;
12199 }
12200 }
12201 ast_cc_copy_config_params(tmp->pri->cc_params,
12202 conf->chan.cc_params);
12203
12204 pris[span].pri.sig = chan_sig;
12205 pris[span].pri.nodetype = conf->pri.pri.nodetype;
12206 pris[span].pri.switchtype = myswitchtype;
12207 pris[span].pri.nsf = conf->pri.pri.nsf;
12208 pris[span].pri.dialplan = conf->pri.pri.dialplan;
12209 pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
12210 pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
12211 pris[span].pri.minunused = conf->pri.pri.minunused;
12212 pris[span].pri.minidle = conf->pri.pri.minidle;
12213 pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
12214 pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
12215 pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
12216 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12217 pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
12218 #endif
12219 #ifdef HAVE_PRI_INBANDDISCONNECT
12220 pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
12221 #endif
12222 #if defined(HAVE_PRI_CALL_HOLD)
12223 pris[span].pri.hold_disconnect_transfer =
12224 conf->pri.pri.hold_disconnect_transfer;
12225 #endif
12226 #if defined(HAVE_PRI_CCSS)
12227 pris[span].pri.cc_ptmp_recall_mode =
12228 conf->pri.pri.cc_ptmp_recall_mode;
12229 pris[span].pri.cc_qsig_signaling_link_req =
12230 conf->pri.pri.cc_qsig_signaling_link_req;
12231 pris[span].pri.cc_qsig_signaling_link_rsp =
12232 conf->pri.pri.cc_qsig_signaling_link_rsp;
12233 #endif
12234 #if defined(HAVE_PRI_CALL_WAITING)
12235 pris[span].pri.max_call_waiting_calls =
12236 conf->pri.pri.max_call_waiting_calls;
12237 pris[span].pri.allow_call_waiting_calls =
12238 conf->pri.pri.allow_call_waiting_calls;
12239 #endif
12240 pris[span].pri.transfer = conf->chan.transfer;
12241 pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
12242 #if defined(HAVE_PRI_AOC_EVENTS)
12243 pris[span].pri.aoc_passthrough_flag = conf->pri.pri.aoc_passthrough_flag;
12244 pris[span].pri.aoce_delayhangup = conf->pri.pri.aoce_delayhangup;
12245 #endif
12246 pris[span].pri.append_msn_to_user_tag = conf->pri.pri.append_msn_to_user_tag;
12247 ast_copy_string(pris[span].pri.initial_user_tag, conf->chan.cid_tag, sizeof(pris[span].pri.initial_user_tag));
12248 ast_copy_string(pris[span].pri.msn_list, conf->pri.pri.msn_list, sizeof(pris[span].pri.msn_list));
12249 #if defined(HAVE_PRI_MWI)
12250 ast_copy_string(pris[span].pri.mwi_mailboxes,
12251 conf->pri.pri.mwi_mailboxes,
12252 sizeof(pris[span].pri.mwi_mailboxes));
12253 #endif
12254 ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
12255 ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
12256 ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
12257 ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
12258 ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
12259 ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
12260 ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
12261 pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
12262
12263 for (x = 0; x < PRI_MAX_TIMERS; x++) {
12264 pris[span].pri.pritimers[x] = conf->pri.pri.pritimers[x];
12265 }
12266
12267 #if defined(HAVE_PRI_CALL_WAITING)
12268
12269 pris[span].pri.ch_cfg.stripmsd = conf->chan.stripmsd;
12270 pris[span].pri.ch_cfg.hidecallerid = conf->chan.hidecallerid;
12271 pris[span].pri.ch_cfg.hidecalleridname = conf->chan.hidecalleridname;
12272 pris[span].pri.ch_cfg.immediate = conf->chan.immediate;
12273 pris[span].pri.ch_cfg.priexclusive = conf->chan.priexclusive;
12274 pris[span].pri.ch_cfg.priindication_oob = conf->chan.priindication_oob;
12275 pris[span].pri.ch_cfg.use_callerid = conf->chan.use_callerid;
12276 pris[span].pri.ch_cfg.use_callingpres = conf->chan.use_callingpres;
12277 ast_copy_string(pris[span].pri.ch_cfg.context, conf->chan.context, sizeof(pris[span].pri.ch_cfg.context));
12278 ast_copy_string(pris[span].pri.ch_cfg.mohinterpret, conf->chan.mohinterpret, sizeof(pris[span].pri.ch_cfg.mohinterpret));
12279 #endif
12280 } else {
12281 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
12282 destroy_dahdi_pvt(tmp);
12283 return NULL;
12284 }
12285 }
12286 }
12287 #endif
12288 } else {
12289
12290 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));
12291 chan_sig = tmp->sig;
12292 if (tmp->subs[SUB_REAL].dfd > -1) {
12293 memset(&p, 0, sizeof(p));
12294 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12295 }
12296 }
12297
12298 switch (chan_sig) {
12299 case SIG_FXSKS:
12300 case SIG_FXSLS:
12301 case SIG_EM:
12302 case SIG_EM_E1:
12303 case SIG_EMWINK:
12304 case SIG_FEATD:
12305 case SIG_FEATDMF:
12306 case SIG_FEATDMF_TA:
12307 case SIG_FEATB:
12308 case SIG_E911:
12309 case SIG_SF:
12310 case SIG_SFWINK:
12311 case SIG_FGC_CAMA:
12312 case SIG_FGC_CAMAMF:
12313 case SIG_SF_FEATD:
12314 case SIG_SF_FEATDMF:
12315 case SIG_SF_FEATB:
12316 p.starttime = 250;
12317 break;
12318 }
12319
12320 if (tmp->radio) {
12321
12322 p.channo = channel;
12323 p.rxwinktime = 1;
12324 p.rxflashtime = 1;
12325 p.starttime = 1;
12326 p.debouncetime = 5;
12327 } else {
12328 p.channo = channel;
12329
12330 if (conf->timing.prewinktime >= 0)
12331 p.prewinktime = conf->timing.prewinktime;
12332 if (conf->timing.preflashtime >= 0)
12333 p.preflashtime = conf->timing.preflashtime;
12334 if (conf->timing.winktime >= 0)
12335 p.winktime = conf->timing.winktime;
12336 if (conf->timing.flashtime >= 0)
12337 p.flashtime = conf->timing.flashtime;
12338 if (conf->timing.starttime >= 0)
12339 p.starttime = conf->timing.starttime;
12340 if (conf->timing.rxwinktime >= 0)
12341 p.rxwinktime = conf->timing.rxwinktime;
12342 if (conf->timing.rxflashtime >= 0)
12343 p.rxflashtime = conf->timing.rxflashtime;
12344 if (conf->timing.debouncetime >= 0)
12345 p.debouncetime = conf->timing.debouncetime;
12346 }
12347
12348
12349 if (tmp->subs[SUB_REAL].dfd >= 0)
12350 {
12351 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
12352 if (res < 0) {
12353 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
12354 destroy_dahdi_pvt(tmp);
12355 return NULL;
12356 }
12357 }
12358 #if 1
12359 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
12360 memset(&bi, 0, sizeof(bi));
12361 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12362 if (!res) {
12363 bi.txbufpolicy = conf->chan.buf_policy;
12364 bi.rxbufpolicy = conf->chan.buf_policy;
12365 bi.numbufs = conf->chan.buf_no;
12366 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12367 if (res < 0) {
12368 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
12369 }
12370 } else {
12371 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
12372 }
12373 tmp->buf_policy = conf->chan.buf_policy;
12374 tmp->buf_no = conf->chan.buf_no;
12375 tmp->usefaxbuffers = conf->chan.usefaxbuffers;
12376 tmp->faxbuf_policy = conf->chan.faxbuf_policy;
12377 tmp->faxbuf_no = conf->chan.faxbuf_no;
12378
12379
12380
12381
12382 tmp->bufsize = bi.bufsize;
12383 }
12384 #endif
12385 tmp->immediate = conf->chan.immediate;
12386 tmp->transfertobusy = conf->chan.transfertobusy;
12387 if (chan_sig & __DAHDI_SIG_FXS) {
12388 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
12389 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
12390 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
12391 }
12392 tmp->ringt_base = ringt_base;
12393 tmp->firstradio = 0;
12394 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
12395 tmp->permcallwaiting = conf->chan.callwaiting;
12396 else
12397 tmp->permcallwaiting = 0;
12398
12399 tmp->destroy = 0;
12400 tmp->drings = conf->chan.drings;
12401
12402
12403 if (tmp->drings.ringnum[0].range == 0)
12404 tmp->drings.ringnum[0].range = 10;
12405 if (tmp->drings.ringnum[1].range == 0)
12406 tmp->drings.ringnum[1].range = 10;
12407 if (tmp->drings.ringnum[2].range == 0)
12408 tmp->drings.ringnum[2].range = 10;
12409
12410 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
12411 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
12412 tmp->threewaycalling = conf->chan.threewaycalling;
12413 tmp->adsi = conf->chan.adsi;
12414 tmp->use_smdi = conf->chan.use_smdi;
12415 tmp->permhidecallerid = conf->chan.hidecallerid;
12416 tmp->hidecalleridname = conf->chan.hidecalleridname;
12417 tmp->callreturn = conf->chan.callreturn;
12418 tmp->echocancel = conf->chan.echocancel;
12419 tmp->echotraining = conf->chan.echotraining;
12420 tmp->pulse = conf->chan.pulse;
12421 if (tmp->echocancel.head.tap_length) {
12422 tmp->echocanbridged = conf->chan.echocanbridged;
12423 } else {
12424 if (conf->chan.echocanbridged)
12425 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
12426 tmp->echocanbridged = 0;
12427 }
12428 tmp->busydetect = conf->chan.busydetect;
12429 tmp->busycount = conf->chan.busycount;
12430 tmp->busy_tonelength = conf->chan.busy_tonelength;
12431 tmp->busy_quietlength = conf->chan.busy_quietlength;
12432 tmp->callprogress = conf->chan.callprogress;
12433 tmp->waitfordialtone = conf->chan.waitfordialtone;
12434 tmp->cancallforward = conf->chan.cancallforward;
12435 tmp->dtmfrelax = conf->chan.dtmfrelax;
12436 tmp->callwaiting = tmp->permcallwaiting;
12437 tmp->hidecallerid = tmp->permhidecallerid;
12438 tmp->channel = channel;
12439 tmp->stripmsd = conf->chan.stripmsd;
12440 tmp->use_callerid = conf->chan.use_callerid;
12441 tmp->cid_signalling = conf->chan.cid_signalling;
12442 tmp->cid_start = conf->chan.cid_start;
12443 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
12444 tmp->restrictcid = conf->chan.restrictcid;
12445 tmp->use_callingpres = conf->chan.use_callingpres;
12446 if (tmp->usedistinctiveringdetection) {
12447 if (!tmp->use_callerid) {
12448 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
12449 tmp->use_callerid = 1;
12450 }
12451 }
12452
12453 if (tmp->cid_signalling == CID_SIG_SMDI) {
12454 if (!tmp->use_smdi) {
12455 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
12456 tmp->use_smdi = 1;
12457 }
12458 }
12459 if (tmp->use_smdi) {
12460 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
12461 if (!(tmp->smdi_iface)) {
12462 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
12463 tmp->use_smdi = 0;
12464 }
12465 }
12466
12467 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
12468 tmp->amaflags = conf->chan.amaflags;
12469 if (!here) {
12470 tmp->confno = -1;
12471 tmp->propconfno = -1;
12472 }
12473 tmp->canpark = conf->chan.canpark;
12474 tmp->transfer = conf->chan.transfer;
12475 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
12476 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
12477 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
12478 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
12479 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
12480 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
12481 tmp->cid_ton = 0;
12482 if (analog_lib_handles(tmp->sig, tmp->radio, tmp->oprmode)) {
12483 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
12484 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
12485 } else {
12486 tmp->cid_num[0] = '\0';
12487 tmp->cid_name[0] = '\0';
12488 }
12489 #if defined(HAVE_PRI)
12490 if (dahdi_sig_pri_lib_handles(tmp->sig)) {
12491 tmp->cid_tag[0] = '\0';
12492 } else
12493 #endif
12494 {
12495 ast_copy_string(tmp->cid_tag, conf->chan.cid_tag, sizeof(tmp->cid_tag));
12496 }
12497 tmp->cid_subaddr[0] = '\0';
12498 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
12499 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
12500 char *mailbox, *context;
12501 mailbox = context = ast_strdupa(tmp->mailbox);
12502 strsep(&context, "@");
12503 if (ast_strlen_zero(context))
12504 context = "default";
12505 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "Dahdi MWI subscription", NULL,
12506 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
12507 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
12508 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
12509 AST_EVENT_IE_END);
12510 }
12511 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12512 tmp->mwisend_setting = conf->chan.mwisend_setting;
12513 tmp->mwisend_fsk = conf->chan.mwisend_fsk;
12514 tmp->mwisend_rpas = conf->chan.mwisend_rpas;
12515 #endif
12516
12517 tmp->group = conf->chan.group;
12518 tmp->callgroup = conf->chan.callgroup;
12519 tmp->pickupgroup= conf->chan.pickupgroup;
12520 if (conf->chan.vars) {
12521 struct ast_variable *v, *tmpvar;
12522 for (v = conf->chan.vars ; v ; v = v->next) {
12523 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
12524 tmpvar->next = tmp->vars;
12525 tmp->vars = tmpvar;
12526 }
12527 }
12528 }
12529 tmp->cid_rxgain = conf->chan.cid_rxgain;
12530 tmp->rxgain = conf->chan.rxgain;
12531 tmp->txgain = conf->chan.txgain;
12532 tmp->txdrc = conf->chan.txdrc;
12533 tmp->rxdrc = conf->chan.rxdrc;
12534 tmp->tonezone = conf->chan.tonezone;
12535 if (tmp->subs[SUB_REAL].dfd > -1) {
12536 set_actual_gain(tmp->subs[SUB_REAL].dfd, tmp->rxgain, tmp->txgain, tmp->rxdrc, tmp->txdrc, tmp->law);
12537 if (tmp->dsp)
12538 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
12539 update_conf(tmp);
12540 if (!here) {
12541 switch (chan_sig) {
12542 case SIG_PRI_LIB_HANDLE_CASES:
12543 case SIG_SS7:
12544 case SIG_MFCR2:
12545 break;
12546 default:
12547
12548 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
12549 break;
12550 }
12551 }
12552 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
12553 #ifdef HAVE_PRI
12554 memset(&si, 0, sizeof(si));
12555 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
12556 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
12557 destroy_dahdi_pvt(tmp);
12558 return NULL;
12559 }
12560 #endif
12561 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
12562
12563 switch (tmp->sig) {
12564 #ifdef HAVE_PRI
12565 case SIG_PRI_LIB_HANDLE_CASES:
12566 sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
12567 break;
12568 #endif
12569 #if defined(HAVE_SS7)
12570 case SIG_SS7:
12571 sig_ss7_set_alarm(tmp->sig_pvt, 1);
12572 break;
12573 #endif
12574 default:
12575
12576 analog_p = tmp->sig_pvt;
12577 if (analog_p) {
12578 analog_p->inalarm = 1;
12579 }
12580 tmp->inalarm = 1;
12581 break;
12582 }
12583 handle_alarms(tmp, res);
12584 }
12585 }
12586
12587 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12588 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12589 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12590 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
12591 ast_cc_copy_config_params(tmp->cc_params, conf->chan.cc_params);
12592
12593 if (!here) {
12594 tmp->locallyblocked = 0;
12595 tmp->remotelyblocked = 0;
12596 switch (tmp->sig) {
12597 #if defined(HAVE_PRI)
12598 case SIG_PRI_LIB_HANDLE_CASES:
12599 tmp->inservice = 1;
12600 #if defined(HAVE_PRI_SERVICE_MESSAGES)
12601 ((struct sig_pri_chan *) tmp->sig_pvt)->service_status = 0;
12602 if (chan_sig == SIG_PRI) {
12603 char db_chan_name[20];
12604 char db_answer[5];
12605
12606
12607
12608
12609
12610 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, tmp->channel);
12611 if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
12612 unsigned *why;
12613
12614 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
12615 if (tmp->pri->enable_service_message_support) {
12616 char state;
12617
12618 sscanf(db_answer, "%1c:%30u", &state, why);
12619
12620
12621 *why &= (SRVST_NEAREND | SRVST_FAREND);
12622 }
12623 if (!*why) {
12624 ast_db_del(db_chan_name, SRVST_DBKEY);
12625 }
12626 }
12627 }
12628 #endif
12629 break;
12630 #endif
12631 #if defined(HAVE_SS7)
12632 case SIG_SS7:
12633 tmp->inservice = 0;
12634 break;
12635 #endif
12636 default:
12637
12638 tmp->inservice = 1;
12639 break;
12640 }
12641 }
12642
12643 switch (tmp->sig) {
12644 #if defined(HAVE_PRI)
12645 case SIG_PRI_LIB_HANDLE_CASES:
12646 if (pri_chan) {
12647 pri_chan->channel = tmp->channel;
12648 pri_chan->hidecallerid = tmp->hidecallerid;
12649 pri_chan->hidecalleridname = tmp->hidecalleridname;
12650 pri_chan->immediate = tmp->immediate;
12651 pri_chan->inalarm = tmp->inalarm;
12652 pri_chan->priexclusive = tmp->priexclusive;
12653 pri_chan->priindication_oob = tmp->priindication_oob;
12654 pri_chan->use_callerid = tmp->use_callerid;
12655 pri_chan->use_callingpres = tmp->use_callingpres;
12656 ast_copy_string(pri_chan->context, tmp->context,
12657 sizeof(pri_chan->context));
12658 ast_copy_string(pri_chan->mohinterpret, tmp->mohinterpret,
12659 sizeof(pri_chan->mohinterpret));
12660 pri_chan->stripmsd = tmp->stripmsd;
12661 }
12662 break;
12663 #endif
12664 #if defined(HAVE_SS7)
12665 case SIG_SS7:
12666 if (ss7_chan) {
12667 ss7_chan->inalarm = tmp->inalarm;
12668
12669 ss7_chan->stripmsd = tmp->stripmsd;
12670 ss7_chan->hidecallerid = tmp->hidecallerid;
12671 ss7_chan->use_callerid = tmp->use_callerid;
12672 ss7_chan->use_callingpres = tmp->use_callingpres;
12673 ss7_chan->immediate = tmp->immediate;
12674 ss7_chan->locallyblocked = tmp->locallyblocked;
12675 ss7_chan->remotelyblocked = tmp->remotelyblocked;
12676 ast_copy_string(ss7_chan->context, tmp->context,
12677 sizeof(ss7_chan->context));
12678 ast_copy_string(ss7_chan->mohinterpret, tmp->mohinterpret,
12679 sizeof(ss7_chan->mohinterpret));
12680 }
12681 break;
12682 #endif
12683 default:
12684
12685 analog_p = tmp->sig_pvt;
12686 if (analog_p) {
12687 analog_p->channel = tmp->channel;
12688 analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
12689 analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
12690 analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
12691 analog_p->permcallwaiting = conf->chan.callwaiting;
12692 analog_p->callreturn = conf->chan.callreturn;
12693 analog_p->cancallforward = conf->chan.cancallforward;
12694 analog_p->canpark = conf->chan.canpark;
12695 analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
12696 analog_p->immediate = conf->chan.immediate;
12697 analog_p->permhidecallerid = conf->chan.permhidecallerid;
12698 analog_p->pulse = conf->chan.pulse;
12699 analog_p->threewaycalling = conf->chan.threewaycalling;
12700 analog_p->transfer = conf->chan.transfer;
12701 analog_p->transfertobusy = conf->chan.transfertobusy;
12702 analog_p->use_callerid = tmp->use_callerid;
12703 analog_p->use_smdi = tmp->use_smdi;
12704 analog_p->smdi_iface = tmp->smdi_iface;
12705 analog_p->outsigmod = ANALOG_SIG_NONE;
12706 analog_p->echotraining = conf->chan.echotraining;
12707 analog_p->cid_signalling = conf->chan.cid_signalling;
12708 analog_p->stripmsd = conf->chan.stripmsd;
12709 switch (conf->chan.cid_start) {
12710 case CID_START_POLARITY:
12711 analog_p->cid_start = ANALOG_CID_START_POLARITY;
12712 break;
12713 case CID_START_POLARITY_IN:
12714 analog_p->cid_start = ANALOG_CID_START_POLARITY_IN;
12715 break;
12716 case CID_START_DTMF_NOALERT:
12717 analog_p->cid_start = ANALOG_CID_START_DTMF_NOALERT;
12718 break;
12719 default:
12720 analog_p->cid_start = ANALOG_CID_START_RING;
12721 break;
12722 }
12723 analog_p->callwaitingcallerid = conf->chan.callwaitingcallerid;
12724 analog_p->ringt = conf->chan.ringt;
12725 analog_p->ringt_base = ringt_base;
12726 analog_p->chan_tech = &dahdi_tech;
12727 analog_p->onhooktime = time(NULL);
12728 if (chan_sig & __DAHDI_SIG_FXO) {
12729 memset(&p, 0, sizeof(p));
12730 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
12731 if (!res) {
12732 analog_p->fxsoffhookstate = p.rxisoffhook;
12733 }
12734 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
12735 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
12736 #endif
12737 }
12738 analog_p->msgstate = -1;
12739
12740 ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
12741 ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
12742 ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
12743
12744 analog_config_complete(analog_p);
12745 }
12746 break;
12747 }
12748 #if defined(HAVE_PRI)
12749 if (tmp->channel == CHAN_PSEUDO) {
12750
12751
12752
12753
12754 dahdi_pseudo_parms.buf_no = tmp->buf_no;
12755 dahdi_pseudo_parms.buf_policy = tmp->buf_policy;
12756 dahdi_pseudo_parms.faxbuf_no = tmp->faxbuf_no;
12757 dahdi_pseudo_parms.faxbuf_policy = tmp->faxbuf_policy;
12758 }
12759 #endif
12760 }
12761 if (tmp && !here) {
12762
12763 dahdi_iflist_insert(tmp);
12764 }
12765 return tmp;
12766 }
12767
12768 static int is_group_or_channel_match(struct dahdi_pvt *p, int span, ast_group_t groupmatch, int *groupmatched, int channelmatch, int *channelmatched)
12769 {
12770 #if defined(HAVE_PRI)
12771 if (0 < span) {
12772
12773 if (!p->pri || p->pri->span != span) {
12774 return 0;
12775 }
12776 if (!groupmatch && channelmatch == -1) {
12777
12778 *groupmatched = 1;
12779 return 1;
12780 }
12781 }
12782 #endif
12783
12784 if (groupmatch) {
12785 if ((p->group & groupmatch) != groupmatch)
12786
12787 return 0;
12788 *groupmatched = 1;
12789 }
12790
12791 if (channelmatch != -1) {
12792 if (p->channel != channelmatch)
12793
12794 return 0;
12795 *channelmatched = 1;
12796 }
12797
12798 return 1;
12799 }
12800
12801 static int available(struct dahdi_pvt **pvt, int is_specific_channel)
12802 {
12803 struct dahdi_pvt *p = *pvt;
12804
12805 if (p->inalarm)
12806 return 0;
12807
12808 if (analog_lib_handles(p->sig, p->radio, p->oprmode))
12809 return analog_available(p->sig_pvt);
12810
12811 switch (p->sig) {
12812 #if defined(HAVE_PRI)
12813 case SIG_PRI_LIB_HANDLE_CASES:
12814 {
12815 struct sig_pri_chan *pvt_chan;
12816 int res;
12817
12818 pvt_chan = p->sig_pvt;
12819 res = sig_pri_available(&pvt_chan, is_specific_channel);
12820 *pvt = pvt_chan->chan_pvt;
12821 return res;
12822 }
12823 #endif
12824 #if defined(HAVE_SS7)
12825 case SIG_SS7:
12826 return sig_ss7_available(p->sig_pvt);
12827 #endif
12828 default:
12829 break;
12830 }
12831
12832 if (p->locallyblocked || p->remotelyblocked) {
12833 return 0;
12834 }
12835
12836
12837 if (!p->owner) {
12838 #ifdef HAVE_OPENR2
12839
12840 if (p->mfcr2) {
12841 if (p->mfcr2call) {
12842 return 0;
12843 } else {
12844 return 1;
12845 }
12846 }
12847 #endif
12848 return 1;
12849 }
12850
12851 return 0;
12852 }
12853
12854 #if defined(HAVE_PRI)
12855 #if defined(HAVE_PRI_CALL_WAITING)
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868 static void my_pri_init_config(void *priv, struct sig_pri_span *pri)
12869 {
12870 struct dahdi_pvt *pvt = priv;
12871
12872 pvt->stripmsd = pri->ch_cfg.stripmsd;
12873 pvt->hidecallerid = pri->ch_cfg.hidecallerid;
12874 pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
12875 pvt->immediate = pri->ch_cfg.immediate;
12876 pvt->priexclusive = pri->ch_cfg.priexclusive;
12877 pvt->priindication_oob = pri->ch_cfg.priindication_oob;
12878 pvt->use_callerid = pri->ch_cfg.use_callerid;
12879 pvt->use_callingpres = pri->ch_cfg.use_callingpres;
12880 ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
12881 ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
12882 }
12883 #endif
12884 #endif
12885
12886 #if defined(HAVE_PRI)
12887
12888
12889
12890
12891
12892
12893
12894
12895
12896
12897
12898
12899 static int dahdi_new_pri_nobch_channel(struct sig_pri_span *pri)
12900 {
12901 int pvt_idx;
12902 int res;
12903 unsigned idx;
12904 struct dahdi_pvt *pvt;
12905 struct sig_pri_chan *chan;
12906 struct dahdi_bufferinfo bi;
12907
12908 static int nobch_channel = CHAN_PSEUDO;
12909
12910
12911 for (pvt_idx = 0; pvt_idx < pri->numchans; ++pvt_idx) {
12912 if (!pri->pvts[pvt_idx]) {
12913 break;
12914 }
12915 }
12916 if (pri->numchans == pvt_idx) {
12917 if (ARRAY_LEN(pri->pvts) <= pvt_idx) {
12918 ast_log(LOG_ERROR, "Unable to add a no-B-channel interface!\n");
12919 return -1;
12920 }
12921
12922
12923 pri->pvts[pvt_idx] = NULL;
12924 ++pri->numchans;
12925 }
12926
12927 pvt = ast_calloc(1, sizeof(*pvt));
12928 if (!pvt) {
12929 return -1;
12930 }
12931 pvt->cc_params = ast_cc_config_params_init();
12932 if (!pvt->cc_params) {
12933 ast_free(pvt);
12934 return -1;
12935 }
12936 ast_mutex_init(&pvt->lock);
12937 for (idx = 0; idx < ARRAY_LEN(pvt->subs); ++idx) {
12938 pvt->subs[idx].dfd = -1;
12939 }
12940 pvt->buf_no = dahdi_pseudo_parms.buf_no;
12941 pvt->buf_policy = dahdi_pseudo_parms.buf_policy;
12942 pvt->faxbuf_no = dahdi_pseudo_parms.faxbuf_no;
12943 pvt->faxbuf_policy = dahdi_pseudo_parms.faxbuf_policy;
12944
12945 chan = sig_pri_chan_new(pvt, &dahdi_pri_callbacks, pri, 0, 0, 0);
12946 if (!chan) {
12947 destroy_dahdi_pvt(pvt);
12948 return -1;
12949 }
12950 chan->no_b_channel = 1;
12951
12952
12953
12954
12955
12956
12957 pvt->law_default = DAHDI_LAW_ALAW;
12958
12959 pvt->sig = pri->sig;
12960 pvt->outsigmod = -1;
12961 pvt->pri = pri;
12962 pvt->sig_pvt = chan;
12963 pri->pvts[pvt_idx] = chan;
12964
12965 pvt->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
12966 if (pvt->subs[SUB_REAL].dfd < 0) {
12967 ast_log(LOG_ERROR, "Unable to open no B channel interface pseudo channel: %s\n",
12968 strerror(errno));
12969 destroy_dahdi_pvt(pvt);
12970 return -1;
12971 }
12972 memset(&bi, 0, sizeof(bi));
12973 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
12974 if (!res) {
12975 pvt->bufsize = bi.bufsize;
12976 bi.txbufpolicy = pvt->buf_policy;
12977 bi.rxbufpolicy = pvt->buf_policy;
12978 bi.numbufs = pvt->buf_no;
12979 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
12980 if (res < 0) {
12981 ast_log(LOG_WARNING,
12982 "Unable to set buffer policy on no B channel interface: %s\n",
12983 strerror(errno));
12984 }
12985 } else
12986 ast_log(LOG_WARNING,
12987 "Unable to check buffer policy on no B channel interface: %s\n",
12988 strerror(errno));
12989
12990 --nobch_channel;
12991 if (CHAN_PSEUDO < nobch_channel) {
12992 nobch_channel = CHAN_PSEUDO - 1;
12993 }
12994 pvt->channel = nobch_channel;
12995 chan->channel = pvt->channel;
12996
12997 dahdi_nobch_insert(pri, pvt);
12998
12999 return pvt_idx;
13000 }
13001 #endif
13002
13003
13004
13005
13006
13007
13008 static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
13009 {
13010 struct dahdi_pvt *p;
13011 struct dahdi_bufferinfo bi;
13012 int res;
13013
13014 p = ast_malloc(sizeof(*p));
13015 if (!p) {
13016 return NULL;
13017 }
13018 *p = *src;
13019
13020
13021 p->cc_params = ast_cc_config_params_init();
13022 if (!p->cc_params) {
13023 ast_free(p);
13024 return NULL;
13025 }
13026 ast_cc_copy_config_params(p->cc_params, src->cc_params);
13027
13028 p->which_iflist = DAHDI_IFLIST_NONE;
13029 p->next = NULL;
13030 p->prev = NULL;
13031 ast_mutex_init(&p->lock);
13032 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
13033 if (p->subs[SUB_REAL].dfd < 0) {
13034 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
13035 destroy_dahdi_pvt(p);
13036 return NULL;
13037 }
13038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
13039 if (!res) {
13040 bi.txbufpolicy = src->buf_policy;
13041 bi.rxbufpolicy = src->buf_policy;
13042 bi.numbufs = src->buf_no;
13043 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
13044 if (res < 0) {
13045 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
13046 }
13047 } else
13048 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
13049 p->destroy = 1;
13050 dahdi_iflist_insert(p);
13051 return p;
13052 }
13053
13054 struct dahdi_starting_point {
13055
13056 ast_group_t groupmatch;
13057
13058 int channelmatch;
13059
13060 int rr_starting_point;
13061
13062 int span;
13063
13064 int cadance;
13065
13066 char opt;
13067
13068 char backwards;
13069
13070 char roundrobin;
13071 };
13072 static struct dahdi_pvt *determine_starting_point(const char *data, struct dahdi_starting_point *param)
13073 {
13074 char *dest;
13075 char *s;
13076 int x;
13077 int res = 0;
13078 struct dahdi_pvt *p;
13079 char *subdir = NULL;
13080 AST_DECLARE_APP_ARGS(args,
13081 AST_APP_ARG(group);
13082
13083
13084 AST_APP_ARG(other);
13085 );
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110 if (data) {
13111 dest = ast_strdupa(data);
13112 } else {
13113 ast_log(LOG_WARNING, "Channel requested with no data\n");
13114 return NULL;
13115 }
13116 AST_NONSTANDARD_APP_ARGS(args, dest, '/');
13117 if (!args.argc || ast_strlen_zero(args.group)) {
13118 ast_log(LOG_WARNING, "No channel/group specified\n");
13119 return NULL;
13120 }
13121
13122
13123 memset(param, 0, sizeof(*param));
13124 param->channelmatch = -1;
13125
13126 if (strchr(args.group, '!') != NULL) {
13127 char *prev = args.group;
13128 while ((s = strchr(prev, '!')) != NULL) {
13129 *s++ = '/';
13130 prev = s;
13131 }
13132 *(prev - 1) = '\0';
13133 subdir = args.group;
13134 args.group = prev;
13135 } else if (args.group[0] == 'i') {
13136
13137 res = sscanf(args.group + 1, "%30d", &x);
13138 if (res < 1) {
13139 ast_log(LOG_WARNING, "Unable to determine ISDN span for data %s\n", data);
13140 return NULL;
13141 }
13142 param->span = x;
13143
13144
13145 s = strchr(args.group, '-');
13146 if (!s) {
13147
13148 return iflist;
13149 }
13150 args.group = s + 1;
13151 res = 0;
13152 }
13153 if (toupper(args.group[0]) == 'G' || toupper(args.group[0])=='R') {
13154
13155 s = args.group + 1;
13156 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13157 if (res < 1) {
13158 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", data);
13159 return NULL;
13160 }
13161 param->groupmatch = ((ast_group_t) 1 << x);
13162
13163 if (toupper(args.group[0]) == 'G') {
13164 if (args.group[0] == 'G') {
13165 param->backwards = 1;
13166 p = ifend;
13167 } else
13168 p = iflist;
13169 } else {
13170 if (ARRAY_LEN(round_robin) <= x) {
13171 ast_log(LOG_WARNING, "Round robin index %d out of range for data %s\n",
13172 x, data);
13173 return NULL;
13174 }
13175 if (args.group[0] == 'R') {
13176 param->backwards = 1;
13177 p = round_robin[x] ? round_robin[x]->prev : ifend;
13178 if (!p)
13179 p = ifend;
13180 } else {
13181 p = round_robin[x] ? round_robin[x]->next : iflist;
13182 if (!p)
13183 p = iflist;
13184 }
13185 param->roundrobin = 1;
13186 param->rr_starting_point = x;
13187 }
13188 } else {
13189 s = args.group;
13190 if (!strcasecmp(s, "pseudo")) {
13191
13192 x = CHAN_PSEUDO;
13193 param->channelmatch = x;
13194 } else {
13195 res = sscanf(s, "%30d%1c%30d", &x, ¶m->opt, ¶m->cadance);
13196 if (res < 1) {
13197 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", data);
13198 return NULL;
13199 } else {
13200 param->channelmatch = x;
13201 }
13202 }
13203 if (subdir) {
13204 char path[PATH_MAX];
13205 struct stat stbuf;
13206
13207 snprintf(path, sizeof(path), "/dev/dahdi/%s/%d",
13208 subdir, param->channelmatch);
13209 if (stat(path, &stbuf) < 0) {
13210 ast_log(LOG_WARNING, "stat(%s) failed: %s\n",
13211 path, strerror(errno));
13212 return NULL;
13213 }
13214 if (!S_ISCHR(stbuf.st_mode)) {
13215 ast_log(LOG_ERROR, "%s: Not a character device file\n",
13216 path);
13217 return NULL;
13218 }
13219 param->channelmatch = minor(stbuf.st_rdev);
13220 }
13221
13222 p = iflist;
13223 }
13224
13225 if (param->opt == 'r' && res < 3) {
13226 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", data);
13227 param->opt = '\0';
13228 }
13229
13230 return p;
13231 }
13232
13233 static struct ast_channel *dahdi_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
13234 {
13235 int callwait = 0;
13236 struct dahdi_pvt *p;
13237 struct ast_channel *tmp = NULL;
13238 struct dahdi_pvt *exitpvt;
13239 int channelmatched = 0;
13240 int groupmatched = 0;
13241 int transcapdigital = 0;
13242 struct dahdi_starting_point start;
13243
13244 ast_mutex_lock(&iflock);
13245 p = determine_starting_point(data, &start);
13246 if (!p) {
13247
13248 ast_mutex_unlock(&iflock);
13249 return NULL;
13250 }
13251
13252
13253 exitpvt = p;
13254 while (p && !tmp) {
13255 if (start.roundrobin)
13256 round_robin[start.rr_starting_point] = p;
13257
13258 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)
13259 && available(&p, channelmatched)) {
13260 ast_debug(1, "Using channel %d\n", p->channel);
13261
13262 callwait = (p->owner != NULL);
13263 #ifdef HAVE_OPENR2
13264 if (p->mfcr2) {
13265 ast_mutex_lock(&p->lock);
13266 if (p->mfcr2call) {
13267 ast_mutex_unlock(&p->lock);
13268 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
13269 goto next;
13270 }
13271 p->mfcr2call = 1;
13272 ast_mutex_unlock(&p->lock);
13273 }
13274 #endif
13275 if (p->channel == CHAN_PSEUDO) {
13276 p = duplicate_pseudo(p);
13277 if (!p) {
13278 break;
13279 }
13280 }
13281
13282
13283 switch (start.opt) {
13284 case '\0':
13285
13286 break;
13287 case 'c':
13288
13289 p->confirmanswer = 1;
13290 break;
13291 case 'r':
13292
13293 p->distinctivering = start.cadance;
13294 break;
13295 case 'd':
13296
13297 transcapdigital = AST_TRANS_CAP_DIGITAL;
13298 break;
13299 default:
13300 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", start.opt, (char *)data);
13301 break;
13302 }
13303
13304 p->outgoing = 1;
13305 if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
13306 tmp = analog_request(p->sig_pvt, &callwait, requestor);
13307 #ifdef HAVE_PRI
13308 } else if (dahdi_sig_pri_lib_handles(p->sig)) {
13309 sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
13310 sizeof(p->dnid));
13311 tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor, transcapdigital);
13312 #endif
13313 #if defined(HAVE_SS7)
13314 } else if (p->sig == SIG_SS7) {
13315 tmp = sig_ss7_request(p->sig_pvt, SIG_SS7_DEFLAW, requestor, transcapdigital);
13316 #endif
13317 } else {
13318 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, requestor ? requestor->linkedid : "");
13319 }
13320 if (!tmp) {
13321 p->outgoing = 0;
13322 #if defined(HAVE_PRI)
13323 #if defined(HAVE_PRI_CALL_WAITING)
13324 switch (p->sig) {
13325 case SIG_PRI_LIB_HANDLE_CASES:
13326 if (((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting) {
13327 ((struct sig_pri_chan *) p->sig_pvt)->is_call_waiting = 0;
13328 ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
13329 }
13330 break;
13331 default:
13332 break;
13333 }
13334 #endif
13335 #endif
13336 } else {
13337 snprintf(p->dialstring, sizeof(p->dialstring), "DAHDI/%s", (char *) data);
13338 }
13339 break;
13340 }
13341 #ifdef HAVE_OPENR2
13342 next:
13343 #endif
13344 if (start.backwards) {
13345 p = p->prev;
13346 if (!p)
13347 p = ifend;
13348 } else {
13349 p = p->next;
13350 if (!p)
13351 p = iflist;
13352 }
13353
13354 if (p == exitpvt)
13355 break;
13356 }
13357 ast_mutex_unlock(&iflock);
13358 restart_monitor();
13359 if (cause && !tmp) {
13360 if (callwait || channelmatched) {
13361 *cause = AST_CAUSE_BUSY;
13362 } else if (groupmatched) {
13363 *cause = AST_CAUSE_CONGESTION;
13364 } else {
13365
13366
13367
13368
13369 }
13370 }
13371
13372 return tmp;
13373 }
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385 static int dahdi_devicestate(void *data)
13386 {
13387 #if defined(HAVE_PRI)
13388 char *device;
13389 unsigned span;
13390 int res;
13391
13392 device = data;
13393
13394 if (*device != 'I') {
13395
13396 return AST_DEVICE_UNKNOWN;
13397 }
13398 res = sscanf(device, "I%30u", &span);
13399 if (res != 1 || !span || NUM_SPANS < span) {
13400
13401 return AST_DEVICE_UNKNOWN;
13402 }
13403 device = strchr(device, '/');
13404 if (!device) {
13405
13406 return AST_DEVICE_UNKNOWN;
13407 }
13408
13409
13410
13411
13412
13413 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13414 ++device;
13415 if (!strcmp(device, "congestion"))
13416 #endif
13417 {
13418 return pris[span - 1].pri.congestion_devstate;
13419 }
13420 #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER)
13421 else if (!strcmp(device, "threshold")) {
13422 return pris[span - 1].pri.threshold_devstate;
13423 }
13424 return AST_DEVICE_UNKNOWN;
13425 #endif
13426 #else
13427 return AST_DEVICE_UNKNOWN;
13428 #endif
13429 }
13430
13431
13432
13433
13434
13435
13436
13437
13438
13439
13440
13441
13442
13443
13444
13445
13446
13447 static int dahdi_cc_callback(struct ast_channel *inbound, const char *dest, ast_cc_callback_fn callback)
13448 {
13449 struct dahdi_pvt *p;
13450 struct dahdi_pvt *exitpvt;
13451 struct dahdi_starting_point start;
13452 int groupmatched = 0;
13453 int channelmatched = 0;
13454
13455 ast_mutex_lock(&iflock);
13456 p = determine_starting_point(dest, &start);
13457 if (!p) {
13458 ast_mutex_unlock(&iflock);
13459 return -1;
13460 }
13461 exitpvt = p;
13462 for (;;) {
13463 if (is_group_or_channel_match(p, start.span, start.groupmatch, &groupmatched, start.channelmatch, &channelmatched)) {
13464
13465 struct ast_str *device_name;
13466 char *dash;
13467 const char *monitor_type;
13468 char dialstring[AST_CHANNEL_NAME];
13469 char full_device_name[AST_CHANNEL_NAME];
13470
13471 switch (ast_get_cc_monitor_policy(p->cc_params)) {
13472 case AST_CC_MONITOR_NEVER:
13473 break;
13474 case AST_CC_MONITOR_NATIVE:
13475 case AST_CC_MONITOR_ALWAYS:
13476 case AST_CC_MONITOR_GENERIC:
13477 #if defined(HAVE_PRI)
13478 if (dahdi_sig_pri_lib_handles(p->sig)) {
13479
13480
13481
13482
13483 snprintf(full_device_name, sizeof(full_device_name),
13484 "DAHDI/I%d/congestion", p->pri->span);
13485 } else
13486 #endif
13487 {
13488 #if defined(HAVE_PRI)
13489 device_name = create_channel_name(p, 1, "");
13490 #else
13491 device_name = create_channel_name(p);
13492 #endif
13493 snprintf(full_device_name, sizeof(full_device_name), "DAHDI/%s",
13494 device_name ? ast_str_buffer(device_name) : "");
13495 ast_free(device_name);
13496
13497
13498
13499
13500
13501 dash = strrchr(full_device_name, '-');
13502 if (dash) {
13503 *dash = '\0';
13504 }
13505 }
13506 snprintf(dialstring, sizeof(dialstring), "DAHDI/%s", dest);
13507
13508
13509
13510
13511
13512
13513
13514 monitor_type = AST_CC_GENERIC_MONITOR_TYPE;
13515 callback(inbound,
13516 #if defined(HAVE_PRI)
13517 p->pri ? p->pri->cc_params : p->cc_params,
13518 #else
13519 p->cc_params,
13520 #endif
13521 monitor_type, full_device_name, dialstring, NULL);
13522 break;
13523 }
13524 }
13525 p = start.backwards ? p->prev : p->next;
13526 if (!p) {
13527 p = start.backwards ? ifend : iflist;
13528 }
13529 if (p == exitpvt) {
13530 break;
13531 }
13532 }
13533 ast_mutex_unlock(&iflock);
13534 return 0;
13535 }
13536
13537 #if defined(HAVE_SS7)
13538 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
13539 {
13540 int i;
13541
13542 if (ss7) {
13543 for (i = 0; i < NUM_SPANS; i++) {
13544 if (linksets[i].ss7.ss7 == ss7) {
13545 ast_verbose("[%d] %s", i + 1, s);
13546 return;
13547 }
13548 }
13549 }
13550 ast_verbose("%s", s);
13551 }
13552 #endif
13553
13554 #if defined(HAVE_SS7)
13555 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
13556 {
13557 int i;
13558
13559 if (ss7) {
13560 for (i = 0; i < NUM_SPANS; i++) {
13561 if (linksets[i].ss7.ss7 == ss7) {
13562 ast_log(LOG_ERROR, "[%d] %s", i + 1, s);
13563 return;
13564 }
13565 }
13566 }
13567 ast_log(LOG_ERROR, "%s", s);
13568 }
13569 #endif
13570
13571 #if defined(HAVE_OPENR2)
13572 static void *mfcr2_monitor(void *data)
13573 {
13574 struct dahdi_mfcr2 *mfcr2 = data;
13575
13576
13577
13578
13579
13580 struct pollfd pollers[ARRAY_LEN(mfcr2->pvts)];
13581 int res = 0;
13582 int i = 0;
13583 int oldstate = 0;
13584 int quit_loop = 0;
13585 int maxsleep = 20;
13586 int was_idle = 0;
13587 int pollsize = 0;
13588
13589
13590 for (i = 0; i < mfcr2->numchans; i++) {
13591 openr2_chan_set_idle(mfcr2->pvts[i]->r2chan);
13592 openr2_chan_handle_cas(mfcr2->pvts[i]->r2chan);
13593 }
13594 while (1) {
13595
13596
13597 pollsize = 0;
13598 for (i = 0; i < mfcr2->numchans; i++) {
13599 pollers[i].revents = 0;
13600 pollers[i].events = 0;
13601 if (mfcr2->pvts[i]->owner) {
13602 continue;
13603 }
13604 if (!mfcr2->pvts[i]->r2chan) {
13605 ast_log(LOG_DEBUG, "Wow, no r2chan on channel %d\n", mfcr2->pvts[i]->channel);
13606 quit_loop = 1;
13607 break;
13608 }
13609 openr2_chan_enable_read(mfcr2->pvts[i]->r2chan);
13610 pollers[i].events = POLLIN | POLLPRI;
13611 pollers[i].fd = mfcr2->pvts[i]->subs[SUB_REAL].dfd;
13612 pollsize++;
13613 }
13614 if (quit_loop) {
13615 break;
13616 }
13617 if (pollsize == 0) {
13618 if (!was_idle) {
13619 ast_log(LOG_DEBUG, "Monitor thread going idle since everybody has an owner\n");
13620 was_idle = 1;
13621 }
13622 poll(NULL, 0, maxsleep);
13623 continue;
13624 }
13625 was_idle = 0;
13626
13627
13628 pthread_testcancel();
13629 res = poll(pollers, mfcr2->numchans, maxsleep);
13630 pthread_testcancel();
13631 if ((res < 0) && (errno != EINTR)) {
13632 ast_log(LOG_ERROR, "going out, poll failed: %s\n", strerror(errno));
13633 break;
13634 }
13635
13636 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
13637 for (i = 0; i < mfcr2->numchans; i++) {
13638 if (pollers[i].revents & POLLPRI || pollers[i].revents & POLLIN) {
13639 openr2_chan_process_event(mfcr2->pvts[i]->r2chan);
13640 }
13641 }
13642 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
13643 }
13644 ast_log(LOG_NOTICE, "Quitting MFC/R2 monitor thread\n");
13645 return 0;
13646 }
13647 #endif
13648
13649 #if defined(HAVE_PRI)
13650 #ifndef PRI_RESTART
13651 #error "Upgrade your libpri"
13652 #endif
13653 static void dahdi_pri_message(struct pri *pri, char *s)
13654 {
13655 int x, y;
13656 int dchan = -1, span = -1, dchancount = 0;
13657
13658 if (pri) {
13659 for (x = 0; x < NUM_SPANS; x++) {
13660 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13661 if (pris[x].pri.dchans[y])
13662 dchancount++;
13663
13664 if (pris[x].pri.dchans[y] == pri)
13665 dchan = y;
13666 }
13667 if (dchan >= 0) {
13668 span = x;
13669 break;
13670 }
13671 dchancount = 0;
13672 }
13673 if (dchancount > 1 && (span > -1))
13674 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
13675 else if (span > -1)
13676 ast_verbose("%d %s", span+1, s);
13677 else
13678 ast_verbose("%s", s);
13679 } else
13680 ast_verbose("%s", s);
13681
13682 ast_mutex_lock(&pridebugfdlock);
13683
13684 if (pridebugfd >= 0) {
13685 if (write(pridebugfd, s, strlen(s)) < 0) {
13686 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13687 }
13688 }
13689
13690 ast_mutex_unlock(&pridebugfdlock);
13691 }
13692 #endif
13693
13694 #if defined(HAVE_PRI)
13695 static void dahdi_pri_error(struct pri *pri, char *s)
13696 {
13697 int x, y;
13698 int dchan = -1, span = -1;
13699 int dchancount = 0;
13700
13701 if (pri) {
13702 for (x = 0; x < NUM_SPANS; x++) {
13703 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13704 if (pris[x].pri.dchans[y])
13705 dchancount++;
13706
13707 if (pris[x].pri.dchans[y] == pri)
13708 dchan = y;
13709 }
13710 if (dchan >= 0) {
13711 span = x;
13712 break;
13713 }
13714 dchancount = 0;
13715 }
13716 if ((dchancount > 1) && (span > -1))
13717 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
13718 else if (span > -1)
13719 ast_log(LOG_ERROR, "%d %s", span+1, s);
13720 else
13721 ast_log(LOG_ERROR, "%s", s);
13722 } else
13723 ast_log(LOG_ERROR, "%s", s);
13724
13725 ast_mutex_lock(&pridebugfdlock);
13726
13727 if (pridebugfd >= 0) {
13728 if (write(pridebugfd, s, strlen(s)) < 0) {
13729 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
13730 }
13731 }
13732
13733 ast_mutex_unlock(&pridebugfdlock);
13734 }
13735 #endif
13736
13737 #if defined(HAVE_PRI)
13738 static int prepare_pri(struct dahdi_pri *pri)
13739 {
13740 int i, res, x;
13741 struct dahdi_params p;
13742 struct dahdi_bufferinfo bi;
13743 struct dahdi_spaninfo si;
13744
13745 pri->pri.calls = &dahdi_pri_callbacks;
13746
13747 for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
13748 if (!pri->dchannels[i])
13749 break;
13750 pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
13751 x = pri->dchannels[i];
13752 if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
13753 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13754 return -1;
13755 }
13756 memset(&p, 0, sizeof(p));
13757 res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
13758 if (res) {
13759 dahdi_close_pri_fd(pri, i);
13760 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13761 return -1;
13762 }
13763 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13764 dahdi_close_pri_fd(pri, i);
13765 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13766 return -1;
13767 }
13768 memset(&si, 0, sizeof(si));
13769 res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
13770 if (res) {
13771 dahdi_close_pri_fd(pri, i);
13772 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13773 }
13774 if (!si.alarms) {
13775 pri_event_noalarm(&pri->pri, i, 1);
13776 } else {
13777 pri_event_alarm(&pri->pri, i, 1);
13778 }
13779 memset(&bi, 0, sizeof(bi));
13780 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13781 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13782 bi.numbufs = 32;
13783 bi.bufsize = 1024;
13784 if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
13785 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13786 dahdi_close_pri_fd(pri, i);
13787 return -1;
13788 }
13789 pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
13790 }
13791 return 0;
13792 }
13793 #endif
13794
13795 #if defined(HAVE_PRI)
13796 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
13797 {
13798 int which, span;
13799 char *ret = NULL;
13800
13801 if (pos != rpos)
13802 return ret;
13803
13804 for (which = span = 0; span < NUM_SPANS; span++) {
13805 if (pris[span].pri.pri && ++which > state) {
13806 if (asprintf(&ret, "%d", span + 1) < 0) {
13807 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13808 }
13809 break;
13810 }
13811 }
13812 return ret;
13813 }
13814 #endif
13815
13816 #if defined(HAVE_PRI)
13817 static char *complete_span_4(const char *line, const char *word, int pos, int state)
13818 {
13819 return complete_span_helper(line,word,pos,state,3);
13820 }
13821 #endif
13822
13823 #if defined(HAVE_PRI)
13824 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13825 {
13826 int myfd;
13827 switch (cmd) {
13828 case CLI_INIT:
13829 e->command = "pri set debug file";
13830 e->usage = "Usage: pri set debug file [output-file]\n"
13831 " Sends PRI debug output to the specified output file\n";
13832 return NULL;
13833 case CLI_GENERATE:
13834 return NULL;
13835 }
13836 if (a->argc < 5)
13837 return CLI_SHOWUSAGE;
13838
13839 if (ast_strlen_zero(a->argv[4]))
13840 return CLI_SHOWUSAGE;
13841
13842 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13843 if (myfd < 0) {
13844 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13845 return CLI_SUCCESS;
13846 }
13847
13848 ast_mutex_lock(&pridebugfdlock);
13849
13850 if (pridebugfd >= 0)
13851 close(pridebugfd);
13852
13853 pridebugfd = myfd;
13854 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13855 ast_mutex_unlock(&pridebugfdlock);
13856 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13857 return CLI_SUCCESS;
13858 }
13859 #endif
13860
13861 #if defined(HAVE_PRI)
13862 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13863 {
13864 int span;
13865 int x;
13866 int level = 0;
13867 switch (cmd) {
13868 case CLI_INIT:
13869 e->command = "pri set debug {on|off|0|1|2} span";
13870 e->usage =
13871 "Usage: pri set debug {<level>|on|off} span <span>\n"
13872 " Enables debugging on a given PRI span\n";
13873 return NULL;
13874 case CLI_GENERATE:
13875 return complete_span_4(a->line, a->word, a->pos, a->n);
13876 }
13877 if (a->argc < 6) {
13878 return CLI_SHOWUSAGE;
13879 }
13880
13881 if (!strcasecmp(a->argv[3], "on")) {
13882 level = 1;
13883 } else if (!strcasecmp(a->argv[3], "off")) {
13884 level = 0;
13885 } else {
13886 level = atoi(a->argv[3]);
13887 }
13888 span = atoi(a->argv[5]);
13889 if ((span < 1) || (span > NUM_SPANS)) {
13890 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13891 return CLI_SUCCESS;
13892 }
13893 if (!pris[span-1].pri.pri) {
13894 ast_cli(a->fd, "No PRI running on span %d\n", span);
13895 return CLI_SUCCESS;
13896 }
13897
13898
13899 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
13900 if (pris[span - 1].pri.dchans[x]) {
13901 switch (level) {
13902 case 0:
13903 pri_set_debug(pris[span - 1].pri.dchans[x], 0);
13904 break;
13905 case 1:
13906 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_NORMAL);
13907 break;
13908 default:
13909 pri_set_debug(pris[span - 1].pri.dchans[x], SIG_PRI_DEBUG_INTENSE);
13910 break;
13911 }
13912 }
13913 }
13914 if (level == 0) {
13915
13916 ast_mutex_lock(&pridebugfdlock);
13917 if (0 <= pridebugfd) {
13918 close(pridebugfd);
13919 pridebugfd = -1;
13920 ast_cli(a->fd, "Disabled PRI debug output to file '%s'\n",
13921 pridebugfilename);
13922 }
13923 ast_mutex_unlock(&pridebugfdlock);
13924 }
13925 pris[span - 1].pri.debug = (level) ? 1 : 0;
13926 ast_cli(a->fd, "%s debugging on span %d\n", (level) ? "Enabled" : "Disabled", span);
13927 return CLI_SUCCESS;
13928 }
13929 #endif
13930
13931 #if defined(HAVE_PRI_SERVICE_MESSAGES)
13932 static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a, int changestatus)
13933 {
13934 unsigned *why;
13935 int channel;
13936 int trunkgroup;
13937 int x, y, fd = a->fd;
13938 int interfaceid = 0;
13939 char *c;
13940 char db_chan_name[20], db_answer[5];
13941 struct dahdi_pvt *tmp;
13942 struct dahdi_pri *pri;
13943
13944 if (a->argc < 5 || a->argc > 6)
13945 return CLI_SHOWUSAGE;
13946 if ((c = strchr(a->argv[4], ':'))) {
13947 if (sscanf(a->argv[4], "%30d:%30d", &trunkgroup, &channel) != 2)
13948 return CLI_SHOWUSAGE;
13949 if ((trunkgroup < 1) || (channel < 1))
13950 return CLI_SHOWUSAGE;
13951 pri = NULL;
13952 for (x=0;x<NUM_SPANS;x++) {
13953 if (pris[x].pri.trunkgroup == trunkgroup) {
13954 pri = pris + x;
13955 break;
13956 }
13957 }
13958 if (!pri) {
13959 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
13960 return CLI_FAILURE;
13961 }
13962 } else
13963 channel = atoi(a->argv[4]);
13964
13965 if (a->argc == 6)
13966 interfaceid = atoi(a->argv[5]);
13967
13968
13969 for (x = 0; x < NUM_SPANS; x++) {
13970 for (y = 0; y < SIG_PRI_NUM_DCHANS; y++) {
13971 if (pris[x].dchannels[y] == channel) {
13972 pri = pris + x;
13973 if (pri->pri.enable_service_message_support) {
13974 ast_mutex_lock(&pri->pri.lock);
13975 pri_maintenance_service(pri->pri.pri, interfaceid, -1, changestatus);
13976 ast_mutex_unlock(&pri->pri.lock);
13977 } else {
13978 ast_cli(fd,
13979 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
13980 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
13981 }
13982 return CLI_SUCCESS;
13983 }
13984 }
13985 }
13986
13987
13988 ast_mutex_lock(&iflock);
13989 for (tmp = iflist; tmp; tmp = tmp->next) {
13990 if (tmp->pri && tmp->channel == channel) {
13991 ast_mutex_unlock(&iflock);
13992 ast_mutex_lock(&tmp->pri->lock);
13993 if (!tmp->pri->enable_service_message_support) {
13994 ast_mutex_unlock(&tmp->pri->lock);
13995 ast_cli(fd,
13996 "\n\tThis operation has not been enabled in chan_dahdi.conf, set 'service_message_support=yes' to use this operation.\n"
13997 "\tNote only 4ESS, 5ESS, and NI2 switch types are supported.\n\n");
13998 return CLI_SUCCESS;
13999 }
14000 snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, tmp->span, channel);
14001 why = &((struct sig_pri_chan *) tmp->sig_pvt)->service_status;
14002 switch(changestatus) {
14003 case 0:
14004
14005 ast_db_del(db_chan_name, SRVST_DBKEY);
14006 *why &= ~SRVST_NEAREND;
14007 if (*why) {
14008 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14009 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14010 } else {
14011 dahdi_pri_update_span_devstate(tmp->pri);
14012 }
14013 break;
14014
14015 case 2:
14016
14017 ast_db_del(db_chan_name, SRVST_DBKEY);
14018 *why |= SRVST_NEAREND;
14019 snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS, *why);
14020 ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
14021 dahdi_pri_update_span_devstate(tmp->pri);
14022 break;
14023
14024
14025 default:
14026 ast_log(LOG_WARNING, "Unsupported changestatus: '%d'\n", changestatus);
14027 break;
14028 }
14029 pri_maintenance_bservice(tmp->pri->pri, tmp->sig_pvt, changestatus);
14030 ast_mutex_unlock(&tmp->pri->lock);
14031 return CLI_SUCCESS;
14032 }
14033 }
14034 ast_mutex_unlock(&iflock);
14035
14036 ast_cli(fd, "Unable to find given channel %d, possibly not a PRI\n", channel);
14037 return CLI_FAILURE;
14038 }
14039
14040 static char *handle_pri_service_enable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14041 {
14042 switch (cmd) {
14043 case CLI_INIT:
14044 e->command = "pri service enable channel";
14045 e->usage =
14046 "Usage: pri service enable channel <channel> [<interface id>]\n"
14047 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14048 " to restore a channel to service, with optional interface id\n"
14049 " as agreed upon with remote switch operator\n";
14050 return NULL;
14051 case CLI_GENERATE:
14052 return NULL;
14053 }
14054 return handle_pri_service_generic(e, cmd, a, 0);
14055 }
14056
14057 static char *handle_pri_service_disable_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14058 {
14059 switch (cmd) {
14060 case CLI_INIT:
14061 e->command = "pri service disable channel";
14062 e->usage =
14063 "Usage: pri service disable channel <chan num> [<interface id>]\n"
14064 " Send an AT&T / NFAS / CCS ANSI T1.607 maintenance message\n"
14065 " to remove a channel from service, with optional interface id\n"
14066 " as agreed upon with remote switch operator\n";
14067 return NULL;
14068 case CLI_GENERATE:
14069 return NULL;
14070 }
14071 return handle_pri_service_generic(e, cmd, a, 2);
14072 }
14073 #endif
14074
14075 #if defined(HAVE_PRI)
14076 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14077 {
14078 int span;
14079
14080 switch (cmd) {
14081 case CLI_INIT:
14082 e->command = "pri show spans";
14083 e->usage =
14084 "Usage: pri show spans\n"
14085 " Displays PRI Information\n";
14086 return NULL;
14087 case CLI_GENERATE:
14088 return NULL;
14089 }
14090
14091 if (a->argc != 3)
14092 return CLI_SHOWUSAGE;
14093
14094 for (span = 0; span < NUM_SPANS; span++) {
14095 if (pris[span].pri.pri) {
14096 sig_pri_cli_show_spans(a->fd, span + 1, &pris[span].pri);
14097 }
14098 }
14099 return CLI_SUCCESS;
14100 }
14101 #endif
14102
14103 #if defined(HAVE_PRI)
14104 static char *handle_pri_show_span(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 span";
14111 e->usage =
14112 "Usage: pri show span <span>\n"
14113 " Displays PRI Information on a given PRI span\n";
14114 return NULL;
14115 case CLI_GENERATE:
14116 return complete_span_4(a->line, a->word, a->pos, a->n);
14117 }
14118
14119 if (a->argc < 4)
14120 return CLI_SHOWUSAGE;
14121 span = atoi(a->argv[3]);
14122 if ((span < 1) || (span > NUM_SPANS)) {
14123 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
14124 return CLI_SUCCESS;
14125 }
14126 if (!pris[span-1].pri.pri) {
14127 ast_cli(a->fd, "No PRI running on span %d\n", span);
14128 return CLI_SUCCESS;
14129 }
14130
14131 sig_pri_cli_show_span(a->fd, pris[span-1].dchannels, &pris[span-1].pri);
14132
14133 return CLI_SUCCESS;
14134 }
14135 #endif
14136
14137 #if defined(HAVE_PRI)
14138 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14139 {
14140 int x;
14141 int span;
14142 int count=0;
14143 int debug;
14144
14145 switch (cmd) {
14146 case CLI_INIT:
14147 e->command = "pri show debug";
14148 e->usage =
14149 "Usage: pri show debug\n"
14150 " Show the debug state of pri spans\n";
14151 return NULL;
14152 case CLI_GENERATE:
14153 return NULL;
14154 }
14155
14156 for (span = 0; span < NUM_SPANS; span++) {
14157 if (pris[span].pri.pri) {
14158 for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
14159 if (pris[span].pri.dchans[x]) {
14160 debug = pri_get_debug(pris[span].pri.dchans[x]);
14161 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" );
14162 count++;
14163 }
14164 }
14165 }
14166
14167 }
14168 ast_mutex_lock(&pridebugfdlock);
14169 if (pridebugfd >= 0)
14170 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
14171 ast_mutex_unlock(&pridebugfdlock);
14172
14173 if (!count)
14174 ast_cli(a->fd, "No PRI running\n");
14175 return CLI_SUCCESS;
14176 }
14177 #endif
14178
14179 #if defined(HAVE_PRI)
14180 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14181 {
14182 switch (cmd) {
14183 case CLI_INIT:
14184 e->command = "pri show version";
14185 e->usage =
14186 "Usage: pri show version\n"
14187 "Show libpri version information\n";
14188 return NULL;
14189 case CLI_GENERATE:
14190 return NULL;
14191 }
14192
14193 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
14194
14195 return CLI_SUCCESS;
14196 }
14197 #endif
14198
14199 #if defined(HAVE_PRI)
14200 static struct ast_cli_entry dahdi_pri_cli[] = {
14201 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
14202 #if defined(HAVE_PRI_SERVICE_MESSAGES)
14203 AST_CLI_DEFINE(handle_pri_service_enable_channel, "Return a channel to service"),
14204 AST_CLI_DEFINE(handle_pri_service_disable_channel, "Remove a channel from service"),
14205 #endif
14206 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
14207 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
14208 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
14209 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
14210 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
14211 };
14212 #endif
14213
14214 #ifdef HAVE_OPENR2
14215
14216 static char *handle_mfcr2_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14217 {
14218 switch (cmd) {
14219 case CLI_INIT:
14220 e->command = "mfcr2 show version";
14221 e->usage =
14222 "Usage: mfcr2 show version\n"
14223 " Shows the version of the OpenR2 library being used.\n";
14224 return NULL;
14225 case CLI_GENERATE:
14226 return NULL;
14227 }
14228 ast_cli(a->fd, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
14229 return CLI_SUCCESS;
14230 }
14231
14232 static char *handle_mfcr2_show_variants(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14233 {
14234 #define FORMAT "%4s %40s\n"
14235 int i = 0;
14236 int numvariants = 0;
14237 const openr2_variant_entry_t *variants;
14238 switch (cmd) {
14239 case CLI_INIT:
14240 e->command = "mfcr2 show variants";
14241 e->usage =
14242 "Usage: mfcr2 show variants\n"
14243 " Shows the list of MFC/R2 variants supported.\n";
14244 return NULL;
14245 case CLI_GENERATE:
14246 return NULL;
14247 }
14248 if (!(variants = openr2_proto_get_variant_list(&numvariants))) {
14249 ast_cli(a->fd, "Failed to get list of variants.\n");
14250 return CLI_FAILURE;
14251 }
14252 ast_cli(a->fd, FORMAT, "Variant Code", "Country");
14253 for (i = 0; i < numvariants; i++) {
14254 ast_cli(a->fd, FORMAT, variants[i].name, variants[i].country);
14255 }
14256 return CLI_SUCCESS;
14257 #undef FORMAT
14258 }
14259
14260 static char *handle_mfcr2_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14261 {
14262 #define FORMAT "%4s %-7.7s %-7.7s %-8.8s %-9.9s %-16.16s %-8.8s %-8.8s\n"
14263 int filtertype = 0;
14264 int targetnum = 0;
14265 char channo[5];
14266 char anino[5];
14267 char dnisno[5];
14268 struct dahdi_pvt *p;
14269 openr2_context_t *r2context;
14270 openr2_variant_t r2variant;
14271 switch (cmd) {
14272 case CLI_INIT:
14273 e->command = "mfcr2 show channels [group|context]";
14274 e->usage =
14275 "Usage: mfcr2 show channels [group <group> | context <context>]\n"
14276 " Shows the DAHDI channels configured with MFC/R2 signaling.\n";
14277 return NULL;
14278 case CLI_GENERATE:
14279 return NULL;
14280 }
14281 if (!((a->argc == 3) || (a->argc == 5))) {
14282 return CLI_SHOWUSAGE;
14283 }
14284 if (a->argc == 5) {
14285 if (!strcasecmp(a->argv[3], "group")) {
14286 targetnum = atoi(a->argv[4]);
14287 if ((targetnum < 0) || (targetnum > 63))
14288 return CLI_SHOWUSAGE;
14289 targetnum = 1 << targetnum;
14290 filtertype = 1;
14291 } else if (!strcasecmp(a->argv[3], "context")) {
14292 filtertype = 2;
14293 } else {
14294 return CLI_SHOWUSAGE;
14295 }
14296 }
14297 ast_cli(a->fd, FORMAT, "Chan", "Variant", "Max ANI", "Max DNIS", "ANI First", "Immediate Accept", "Tx CAS", "Rx CAS");
14298 ast_mutex_lock(&iflock);
14299 for (p = iflist; p; p = p->next) {
14300 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14301 continue;
14302 }
14303 if (filtertype) {
14304 switch(filtertype) {
14305 case 1:
14306 if (p->group != targetnum) {
14307 continue;
14308 }
14309 break;
14310 case 2:
14311 if (strcasecmp(p->context, a->argv[4])) {
14312 continue;
14313 }
14314 break;
14315 default:
14316 ;
14317 }
14318 }
14319 r2context = openr2_chan_get_context(p->r2chan);
14320 r2variant = openr2_context_get_variant(r2context);
14321 snprintf(channo, sizeof(channo), "%d", p->channel);
14322 snprintf(anino, sizeof(anino), "%d", openr2_context_get_max_ani(r2context));
14323 snprintf(dnisno, sizeof(dnisno), "%d", openr2_context_get_max_dnis(r2context));
14324 ast_cli(a->fd, FORMAT, channo, openr2_proto_get_variant_string(r2variant),
14325 anino, dnisno, openr2_context_get_ani_first(r2context) ? "Yes" : "No",
14326 openr2_context_get_immediate_accept(r2context) ? "Yes" : "No",
14327 openr2_chan_get_tx_cas_string(p->r2chan), openr2_chan_get_rx_cas_string(p->r2chan));
14328 }
14329 ast_mutex_unlock(&iflock);
14330 return CLI_SUCCESS;
14331 #undef FORMAT
14332 }
14333
14334 static char *handle_mfcr2_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14335 {
14336 struct dahdi_pvt *p = NULL;
14337 int channo = 0;
14338 char *toklevel = NULL;
14339 char *saveptr = NULL;
14340 char *logval = NULL;
14341 openr2_log_level_t loglevel = OR2_LOG_NOTHING;
14342 openr2_log_level_t tmplevel = OR2_LOG_NOTHING;
14343 switch (cmd) {
14344 case CLI_INIT:
14345 e->command = "mfcr2 set debug";
14346 e->usage =
14347 "Usage: mfcr2 set debug <loglevel> <channel>\n"
14348 " Set a new logging level for the specified channel.\n"
14349 " If no channel is specified the logging level will be applied to all channels.\n";
14350 return NULL;
14351 case CLI_GENERATE:
14352 return NULL;
14353 }
14354 if (a->argc < 4) {
14355 return CLI_SHOWUSAGE;
14356 }
14357 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14358 logval = ast_strdupa(a->argv[3]);
14359 toklevel = strtok_r(logval, ",", &saveptr);
14360 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14361 ast_cli(a->fd, "Invalid MFC/R2 logging level '%s'.\n", a->argv[3]);
14362 return CLI_FAILURE;
14363 } else if (OR2_LOG_NOTHING == tmplevel) {
14364 loglevel = tmplevel;
14365 } else {
14366 loglevel |= tmplevel;
14367 while ((toklevel = strtok_r(NULL, ",", &saveptr))) {
14368 if (-1 == (tmplevel = openr2_log_get_level(toklevel))) {
14369 ast_cli(a->fd, "Ignoring invalid logging level: '%s'.\n", toklevel);
14370 continue;
14371 }
14372 loglevel |= tmplevel;
14373 }
14374 }
14375 ast_mutex_lock(&iflock);
14376 for (p = iflist; p; p = p->next) {
14377 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14378 continue;
14379 }
14380 if ((channo != -1) && (p->channel != channo )) {
14381 continue;
14382 }
14383 openr2_chan_set_log_level(p->r2chan, loglevel);
14384 if (channo != -1) {
14385 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for channel %d.\n", a->argv[3], p->channel);
14386 break;
14387 }
14388 }
14389 if ((channo != -1) && !p) {
14390 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14391 }
14392 if (channo == -1) {
14393 ast_cli(a->fd, "MFC/R2 debugging set to '%s' for all channels.\n", a->argv[3]);
14394 }
14395 ast_mutex_unlock(&iflock);
14396 return CLI_SUCCESS;
14397 }
14398
14399 static char *handle_mfcr2_call_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14400 {
14401 struct dahdi_pvt *p = NULL;
14402 int channo = 0;
14403 switch (cmd) {
14404 case CLI_INIT:
14405 e->command = "mfcr2 call files [on|off]";
14406 e->usage =
14407 "Usage: mfcr2 call files [on|off] <channel>\n"
14408 " Enable call files creation on the specified channel.\n"
14409 " If no channel is specified call files creation policy will be applied to all channels.\n";
14410 return NULL;
14411 case CLI_GENERATE:
14412 return NULL;
14413 }
14414 if (a->argc < 4) {
14415 return CLI_SHOWUSAGE;
14416 }
14417 channo = (a->argc == 5) ? atoi(a->argv[4]) : -1;
14418 ast_mutex_lock(&iflock);
14419 for (p = iflist; p; p = p->next) {
14420 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14421 continue;
14422 }
14423 if ((channo != -1) && (p->channel != channo )) {
14424 continue;
14425 }
14426 if (ast_true(a->argv[3])) {
14427 openr2_chan_enable_call_files(p->r2chan);
14428 } else {
14429 openr2_chan_disable_call_files(p->r2chan);
14430 }
14431 if (channo != -1) {
14432 if (ast_true(a->argv[3])) {
14433 ast_cli(a->fd, "MFC/R2 call files enabled for channel %d.\n", p->channel);
14434 } else {
14435 ast_cli(a->fd, "MFC/R2 call files disabled for channel %d.\n", p->channel);
14436 }
14437 break;
14438 }
14439 }
14440 if ((channo != -1) && !p) {
14441 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14442 }
14443 if (channo == -1) {
14444 if (ast_true(a->argv[3])) {
14445 ast_cli(a->fd, "MFC/R2 Call files enabled for all channels.\n");
14446 } else {
14447 ast_cli(a->fd, "MFC/R2 Call files disabled for all channels.\n");
14448 }
14449 }
14450 ast_mutex_unlock(&iflock);
14451 return CLI_SUCCESS;
14452 }
14453
14454 static char *handle_mfcr2_set_idle(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14455 {
14456 struct dahdi_pvt *p = NULL;
14457 int channo = 0;
14458 switch (cmd) {
14459 case CLI_INIT:
14460 e->command = "mfcr2 set idle";
14461 e->usage =
14462 "Usage: mfcr2 set idle <channel>\n"
14463 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14464 " Force the given channel into IDLE state.\n"
14465 " If no channel is specified, all channels will be set to IDLE.\n";
14466 return NULL;
14467 case CLI_GENERATE:
14468 return NULL;
14469 }
14470 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14471 ast_mutex_lock(&iflock);
14472 for (p = iflist; p; p = p->next) {
14473 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14474 continue;
14475 }
14476 if ((channo != -1) && (p->channel != channo )) {
14477 continue;
14478 }
14479 openr2_chan_set_idle(p->r2chan);
14480 ast_mutex_lock(&p->lock);
14481 p->locallyblocked = 0;
14482 p->mfcr2call = 0;
14483 ast_mutex_unlock(&p->lock);
14484 if (channo != -1) {
14485 break;
14486 }
14487 }
14488 if ((channo != -1) && !p) {
14489 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14490 }
14491 ast_mutex_unlock(&iflock);
14492 return CLI_SUCCESS;
14493 }
14494
14495 static char *handle_mfcr2_set_blocked(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14496 {
14497 struct dahdi_pvt *p = NULL;
14498 int channo = 0;
14499 switch (cmd) {
14500 case CLI_INIT:
14501 e->command = "mfcr2 set blocked";
14502 e->usage =
14503 "Usage: mfcr2 set blocked <channel>\n"
14504 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n"
14505 " Force the given channel into BLOCKED state.\n"
14506 " If no channel is specified, all channels will be set to BLOCKED.\n";
14507 return NULL;
14508 case CLI_GENERATE:
14509 return NULL;
14510 }
14511 channo = (a->argc == 4) ? atoi(a->argv[3]) : -1;
14512 ast_mutex_lock(&iflock);
14513 for (p = iflist; p; p = p->next) {
14514 if (!(p->sig & SIG_MFCR2) || !p->r2chan) {
14515 continue;
14516 }
14517 if ((channo != -1) && (p->channel != channo )) {
14518 continue;
14519 }
14520 openr2_chan_set_blocked(p->r2chan);
14521 ast_mutex_lock(&p->lock);
14522 p->locallyblocked = 1;
14523 ast_mutex_unlock(&p->lock);
14524 if (channo != -1) {
14525 break;
14526 }
14527 }
14528 if ((channo != -1) && !p) {
14529 ast_cli(a->fd, "MFC/R2 channel %d not found.\n", channo);
14530 }
14531 ast_mutex_unlock(&iflock);
14532 return CLI_SUCCESS;
14533 }
14534
14535 static struct ast_cli_entry dahdi_mfcr2_cli[] = {
14536 AST_CLI_DEFINE(handle_mfcr2_version, "Show OpenR2 library version"),
14537 AST_CLI_DEFINE(handle_mfcr2_show_variants, "Show supported MFC/R2 variants"),
14538 AST_CLI_DEFINE(handle_mfcr2_show_channels, "Show MFC/R2 channels"),
14539 AST_CLI_DEFINE(handle_mfcr2_set_debug, "Set MFC/R2 channel logging level"),
14540 AST_CLI_DEFINE(handle_mfcr2_call_files, "Enable/Disable MFC/R2 call files"),
14541 AST_CLI_DEFINE(handle_mfcr2_set_idle, "Reset MFC/R2 channel forcing it to IDLE"),
14542 AST_CLI_DEFINE(handle_mfcr2_set_blocked, "Reset MFC/R2 channel forcing it to BLOCKED"),
14543 };
14544
14545 #endif
14546
14547 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14548 {
14549 int channel;
14550 int ret;
14551 switch (cmd) {
14552 case CLI_INIT:
14553 e->command = "dahdi destroy channel";
14554 e->usage =
14555 "Usage: dahdi destroy channel <chan num>\n"
14556 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
14557 return NULL;
14558 case CLI_GENERATE:
14559 return NULL;
14560 }
14561 if (a->argc != 4)
14562 return CLI_SHOWUSAGE;
14563
14564 channel = atoi(a->argv[3]);
14565 ret = dahdi_destroy_channel_bynum(channel);
14566 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14567 }
14568
14569 static void dahdi_softhangup_all(void)
14570 {
14571 struct dahdi_pvt *p;
14572 retry:
14573 ast_mutex_lock(&iflock);
14574 for (p = iflist; p; p = p->next) {
14575 ast_mutex_lock(&p->lock);
14576 if (p->owner && !p->restartpending) {
14577 if (ast_channel_trylock(p->owner)) {
14578 if (option_debug > 2)
14579 ast_verbose("Avoiding deadlock\n");
14580
14581 ast_mutex_unlock(&p->lock);
14582 ast_mutex_unlock(&iflock);
14583 goto retry;
14584 }
14585 if (option_debug > 2)
14586 ast_verbose("Softhanging up on %s\n", p->owner->name);
14587 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14588 p->restartpending = 1;
14589 num_restart_pending++;
14590 ast_channel_unlock(p->owner);
14591 }
14592 ast_mutex_unlock(&p->lock);
14593 }
14594 ast_mutex_unlock(&iflock);
14595 }
14596
14597 static int setup_dahdi(int reload);
14598 static int dahdi_restart(void)
14599 {
14600 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14601 int i, j;
14602 #endif
14603 int cancel_code;
14604 struct dahdi_pvt *p;
14605
14606 ast_mutex_lock(&restart_lock);
14607 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14608 dahdi_softhangup_all();
14609 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14610 #ifdef HAVE_OPENR2
14611 dahdi_r2_destroy_links();
14612 #endif
14613
14614 #if defined(HAVE_PRI)
14615 for (i = 0; i < NUM_SPANS; i++) {
14616 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL)) {
14617 cancel_code = pthread_cancel(pris[i].pri.master);
14618 pthread_kill(pris[i].pri.master, SIGURG);
14619 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);
14620 pthread_join(pris[i].pri.master, NULL);
14621 ast_debug(4, "Joined thread of span %d\n", i);
14622 }
14623 }
14624 #endif
14625
14626 #if defined(HAVE_SS7)
14627 for (i = 0; i < NUM_SPANS; i++) {
14628 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL)) {
14629 cancel_code = pthread_cancel(linksets[i].ss7.master);
14630 pthread_kill(linksets[i].ss7.master, SIGURG);
14631 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);
14632 pthread_join(linksets[i].ss7.master, NULL);
14633 ast_debug(4, "Joined thread of span %d\n", i);
14634 }
14635 }
14636 #endif
14637
14638 ast_mutex_lock(&monlock);
14639 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14640 cancel_code = pthread_cancel(monitor_thread);
14641 pthread_kill(monitor_thread, SIGURG);
14642 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14643 pthread_join(monitor_thread, NULL);
14644 ast_debug(4, "Joined monitor thread\n");
14645 }
14646 monitor_thread = AST_PTHREADT_NULL;
14647
14648 ast_mutex_lock(&ss_thread_lock);
14649 while (ss_thread_count > 0) {
14650 int x = DAHDI_FLASH;
14651 ast_debug(3, "Waiting on %d analog_ss_thread(s) to finish\n", ss_thread_count);
14652
14653 ast_mutex_lock(&iflock);
14654 for (p = iflist; p; p = p->next) {
14655 if (p->owner) {
14656
14657 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
14658 }
14659 }
14660 ast_mutex_unlock(&iflock);
14661 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14662 }
14663
14664
14665 dahdi_softhangup_all();
14666 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14667 destroy_all_channels();
14668 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14669
14670 ast_mutex_unlock(&monlock);
14671
14672 #ifdef HAVE_PRI
14673 for (i = 0; i < NUM_SPANS; i++) {
14674 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++)
14675 dahdi_close_pri_fd(&(pris[i]), j);
14676 }
14677
14678 memset(pris, 0, sizeof(pris));
14679 for (i = 0; i < NUM_SPANS; i++) {
14680 sig_pri_init_pri(&pris[i].pri);
14681 }
14682 pri_set_error(dahdi_pri_error);
14683 pri_set_message(dahdi_pri_message);
14684 #endif
14685 #if defined(HAVE_SS7)
14686 for (i = 0; i < NUM_SPANS; i++) {
14687 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++)
14688 dahdi_close_ss7_fd(&(linksets[i]), j);
14689 }
14690
14691 memset(linksets, 0, sizeof(linksets));
14692 for (i = 0; i < NUM_SPANS; i++) {
14693 sig_ss7_init_linkset(&linksets[i].ss7);
14694 }
14695 ss7_set_error(dahdi_ss7_error);
14696 ss7_set_message(dahdi_ss7_message);
14697 #endif
14698
14699 if (setup_dahdi(2) != 0) {
14700 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14701 ast_mutex_unlock(&ss_thread_lock);
14702 return 1;
14703 }
14704 ast_mutex_unlock(&ss_thread_lock);
14705 ast_mutex_unlock(&restart_lock);
14706 return 0;
14707 }
14708
14709 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14710 {
14711 switch (cmd) {
14712 case CLI_INIT:
14713 e->command = "dahdi restart";
14714 e->usage =
14715 "Usage: dahdi restart\n"
14716 " Restarts the DAHDI channels: destroys them all and then\n"
14717 " re-reads them from chan_dahdi.conf.\n"
14718 " Note that this will STOP any running CALL on DAHDI channels.\n"
14719 "";
14720 return NULL;
14721 case CLI_GENERATE:
14722 return NULL;
14723 }
14724 if (a->argc != 2)
14725 return CLI_SHOWUSAGE;
14726
14727 if (dahdi_restart() != 0)
14728 return CLI_FAILURE;
14729 return CLI_SUCCESS;
14730 }
14731
14732 static int action_dahdirestart(struct mansession *s, const struct message *m)
14733 {
14734 if (dahdi_restart() != 0) {
14735 astman_send_error(s, m, "Failed rereading DAHDI configuration");
14736 return 1;
14737 }
14738 astman_send_ack(s, m, "DAHDIRestart: Success");
14739 return 0;
14740 }
14741
14742 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14743 {
14744 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14745 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14746 unsigned int targetnum = 0;
14747 int filtertype = 0;
14748 struct dahdi_pvt *tmp = NULL;
14749 char tmps[20] = "";
14750 char statestr[20] = "";
14751 char blockstr[20] = "";
14752
14753 switch (cmd) {
14754 case CLI_INIT:
14755 e->command = "dahdi show channels [group|context]";
14756 e->usage =
14757 "Usage: dahdi show channels [ group <group> | context <context> ]\n"
14758 " Shows a list of available channels with optional filtering\n"
14759 " <group> must be a number between 0 and 63\n";
14760 return NULL;
14761 case CLI_GENERATE:
14762 return NULL;
14763 }
14764
14765
14766
14767 if (!((a->argc == 3) || (a->argc == 5)))
14768 return CLI_SHOWUSAGE;
14769
14770 if (a->argc == 5) {
14771 if (!strcasecmp(a->argv[3], "group")) {
14772 targetnum = atoi(a->argv[4]);
14773 if ((targetnum < 0) || (targetnum > 63))
14774 return CLI_SHOWUSAGE;
14775 targetnum = 1 << targetnum;
14776 filtertype = 1;
14777 } else if (!strcasecmp(a->argv[3], "context")) {
14778 filtertype = 2;
14779 }
14780 }
14781
14782 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14783 ast_mutex_lock(&iflock);
14784 for (tmp = iflist; tmp; tmp = tmp->next) {
14785 if (filtertype) {
14786 switch(filtertype) {
14787 case 1:
14788 if (!(tmp->group & targetnum)) {
14789 continue;
14790 }
14791 break;
14792 case 2:
14793 if (strcasecmp(tmp->context, a->argv[4])) {
14794 continue;
14795 }
14796 break;
14797 default:
14798 ;
14799 }
14800 }
14801 if (tmp->channel > 0) {
14802 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14803 } else
14804 ast_copy_string(tmps, "pseudo", sizeof(tmps));
14805
14806 if (tmp->locallyblocked)
14807 blockstr[0] = 'L';
14808 else
14809 blockstr[0] = ' ';
14810
14811 if (tmp->remotelyblocked)
14812 blockstr[1] = 'R';
14813 else
14814 blockstr[1] = ' ';
14815
14816 blockstr[2] = '\0';
14817
14818 snprintf(statestr, sizeof(statestr), "%s", "In Service");
14819
14820 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14821 }
14822 ast_mutex_unlock(&iflock);
14823 return CLI_SUCCESS;
14824 #undef FORMAT
14825 #undef FORMAT2
14826 }
14827
14828 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
14829 {
14830 int channel;
14831 struct dahdi_pvt *tmp = NULL;
14832 struct dahdi_confinfo ci;
14833 struct dahdi_params ps;
14834 int x;
14835
14836 switch (cmd) {
14837 case CLI_INIT:
14838 e->command = "dahdi show channel";
14839 e->usage =
14840 "Usage: dahdi show channel <chan num>\n"
14841 " Detailed information about a given channel\n";
14842 return NULL;
14843 case CLI_GENERATE:
14844 return NULL;
14845 }
14846
14847 if (a->argc != 4)
14848 return CLI_SHOWUSAGE;
14849
14850 channel = atoi(a->argv[3]);
14851
14852 ast_mutex_lock(&iflock);
14853 for (tmp = iflist; tmp; tmp = tmp->next) {
14854 if (tmp->channel == channel) {
14855 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14856 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14857 ast_cli(a->fd, "Span: %d\n", tmp->span);
14858 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14859 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14860 ast_cli(a->fd, "Context: %s\n", tmp->context);
14861 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14862 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14863 #if defined(HAVE_PRI)
14864 #if defined(HAVE_PRI_SUBADDR)
14865 ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
14866 #endif
14867 #endif
14868 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14869 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14870 if (tmp->vars) {
14871 struct ast_variable *v;
14872 ast_cli(a->fd, "Variables:\n");
14873 for (v = tmp->vars ; v ; v = v->next)
14874 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
14875 }
14876 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14877 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14878 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14879 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14880 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14881 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)" : "");
14882 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)" : "");
14883 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)" : "");
14884 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14885 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14886 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14887 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14888 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14889 if (tmp->busydetect) {
14890 #if defined(BUSYDETECT_TONEONLY)
14891 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14892 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14893 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14894 #endif
14895 #ifdef BUSYDETECT_DEBUG
14896 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
14897 #endif
14898 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
14899 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14900 }
14901 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14902 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14903 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14904 ast_cli(a->fd, "Default law: %s\n", tmp->law_default == DAHDI_LAW_MULAW ? "ulaw" : tmp->law_default == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14905 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14906 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14907 ast_cli(a->fd, "Gains (RX/TX): %.2f/%.2f\n", tmp->rxgain, tmp->txgain);
14908 ast_cli(a->fd, "Dynamic Range Compression (RX/TX): %.2f/%.2f\n", tmp->rxdrc, tmp->txdrc);
14909 ast_cli(a->fd, "DND: %s\n", dahdi_dnd(tmp, -1) ? "yes" : "no");
14910 ast_cli(a->fd, "Echo Cancellation:\n");
14911
14912 if (tmp->echocancel.head.tap_length) {
14913 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14914 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14915 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14916 }
14917 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14918 } else {
14919 ast_cli(a->fd, "\tnone\n");
14920 }
14921 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14922 if (tmp->master)
14923 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14924 for (x = 0; x < MAX_SLAVES; x++) {
14925 if (tmp->slaves[x])
14926 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14927 }
14928 #ifdef HAVE_OPENR2
14929 if (tmp->mfcr2) {
14930 char calldir[OR2_MAX_PATH];
14931 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14932 openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14933 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14934 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14935 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14936 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14937 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14938 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14939 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14940 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14941 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14942 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14943 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14944 #endif
14945 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14946 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14947 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14948 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14949 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14950 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14951 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14952 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14953 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14954 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14955 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14956 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14957 }
14958 #endif
14959 #if defined(HAVE_SS7)
14960 if (tmp->ss7) {
14961 struct sig_ss7_chan *chan = tmp->sig_pvt;
14962
14963 ast_cli(a->fd, "CIC: %d\n", chan->cic);
14964 }
14965 #endif
14966 #ifdef HAVE_PRI
14967 if (tmp->pri) {
14968 struct sig_pri_chan *chan = tmp->sig_pvt;
14969
14970 ast_cli(a->fd, "PRI Flags: ");
14971 if (chan->resetting)
14972 ast_cli(a->fd, "Resetting ");
14973 if (chan->call)
14974 ast_cli(a->fd, "Call ");
14975 ast_cli(a->fd, "\n");
14976 if (tmp->logicalspan)
14977 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14978 else
14979 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14980 }
14981 #endif
14982 memset(&ci, 0, sizeof(ci));
14983 ps.channo = tmp->channel;
14984 if (tmp->subs[SUB_REAL].dfd > -1) {
14985 memset(&ci, 0, sizeof(ci));
14986 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14987 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14988 }
14989 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14990 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14991 }
14992 memset(&ps, 0, sizeof(ps));
14993 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14994 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14995 } else {
14996 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14997 }
14998 }
14999 ast_mutex_unlock(&iflock);
15000 return CLI_SUCCESS;
15001 }
15002 }
15003 ast_mutex_unlock(&iflock);
15004
15005 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15006 return CLI_FAILURE;
15007 }
15008
15009 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15010 {
15011 int i, j;
15012 switch (cmd) {
15013 case CLI_INIT:
15014 e->command = "dahdi show cadences";
15015 e->usage =
15016 "Usage: dahdi show cadences\n"
15017 " Shows all cadences currently defined\n";
15018 return NULL;
15019 case CLI_GENERATE:
15020 return NULL;
15021 }
15022 for (i = 0; i < num_cadence; i++) {
15023 char output[1024];
15024 char tmp[16], tmp2[64];
15025 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
15026 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
15027
15028 for (j = 0; j < 16; j++) {
15029 if (cadences[i].ringcadence[j] == 0)
15030 break;
15031 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
15032 if (cidrings[i] * 2 - 1 == j)
15033 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
15034 else
15035 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
15036 if (j != 0)
15037 strncat(output, ",", sizeof(output) - strlen(output) - 1);
15038 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
15039 }
15040 ast_cli(a->fd,"%s\n",output);
15041 }
15042 return CLI_SUCCESS;
15043 }
15044
15045
15046 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15047 {
15048 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
15049 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
15050 int span;
15051 int res;
15052 char alarmstr[50];
15053
15054 int ctl;
15055 struct dahdi_spaninfo s;
15056
15057 switch (cmd) {
15058 case CLI_INIT:
15059 e->command = "dahdi show status";
15060 e->usage =
15061 "Usage: dahdi show status\n"
15062 " Shows a list of DAHDI cards with status\n";
15063 return NULL;
15064 case CLI_GENERATE:
15065 return NULL;
15066 }
15067 ctl = open("/dev/dahdi/ctl", O_RDWR);
15068 if (ctl < 0) {
15069 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
15070 return CLI_FAILURE;
15071 }
15072 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
15073
15074 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
15075 s.spanno = span;
15076 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
15077 if (res) {
15078 continue;
15079 }
15080 alarmstr[0] = '\0';
15081 if (s.alarms > 0) {
15082 if (s.alarms & DAHDI_ALARM_BLUE)
15083 strcat(alarmstr, "BLU/");
15084 if (s.alarms & DAHDI_ALARM_YELLOW)
15085 strcat(alarmstr, "YEL/");
15086 if (s.alarms & DAHDI_ALARM_RED)
15087 strcat(alarmstr, "RED/");
15088 if (s.alarms & DAHDI_ALARM_LOOPBACK)
15089 strcat(alarmstr, "LB/");
15090 if (s.alarms & DAHDI_ALARM_RECOVER)
15091 strcat(alarmstr, "REC/");
15092 if (s.alarms & DAHDI_ALARM_NOTOPEN)
15093 strcat(alarmstr, "NOP/");
15094 if (!strlen(alarmstr))
15095 strcat(alarmstr, "UUU/");
15096 if (strlen(alarmstr)) {
15097
15098 alarmstr[strlen(alarmstr) - 1] = '\0';
15099 }
15100 } else {
15101 if (s.numchans)
15102 strcpy(alarmstr, "OK");
15103 else
15104 strcpy(alarmstr, "UNCONFIGURED");
15105 }
15106
15107 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
15108 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
15109 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
15110 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
15111 "CAS",
15112 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
15113 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
15114 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
15115 "Unk",
15116 s.lineconfig & DAHDI_CONFIG_CRC4 ?
15117 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
15118 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "",
15119 lbostr[s.lbo]
15120 );
15121 }
15122 close(ctl);
15123
15124 return CLI_SUCCESS;
15125 #undef FORMAT
15126 #undef FORMAT2
15127 }
15128
15129 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15130 {
15131 int pseudo_fd = -1;
15132 struct dahdi_versioninfo vi;
15133
15134 switch (cmd) {
15135 case CLI_INIT:
15136 e->command = "dahdi show version";
15137 e->usage =
15138 "Usage: dahdi show version\n"
15139 " Shows the DAHDI version in use\n";
15140 return NULL;
15141 case CLI_GENERATE:
15142 return NULL;
15143 }
15144 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
15145 ast_cli(a->fd, "Failed to open control file to get version.\n");
15146 return CLI_SUCCESS;
15147 }
15148
15149 strcpy(vi.version, "Unknown");
15150 strcpy(vi.echo_canceller, "Unknown");
15151
15152 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
15153 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
15154 else
15155 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
15156
15157 close(pseudo_fd);
15158
15159 return CLI_SUCCESS;
15160 }
15161
15162 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15163 {
15164 int channel;
15165 int gain;
15166 int tx;
15167 struct dahdi_hwgain hwgain;
15168 struct dahdi_pvt *tmp = NULL;
15169
15170 switch (cmd) {
15171 case CLI_INIT:
15172 e->command = "dahdi set hwgain";
15173 e->usage =
15174 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
15175 " Sets the hardware gain on a a given channel, overriding the\n"
15176 " value provided at module loadtime, whether the channel is in\n"
15177 " use or not. Changes take effect immediately.\n"
15178 " <rx|tx> which direction do you want to change (relative to our module)\n"
15179 " <chan num> is the channel number relative to the device\n"
15180 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15181 return NULL;
15182 case CLI_GENERATE:
15183 return NULL;
15184 }
15185
15186 if (a->argc != 6)
15187 return CLI_SHOWUSAGE;
15188
15189 if (!strcasecmp("rx", a->argv[3]))
15190 tx = 0;
15191 else if (!strcasecmp("tx", a->argv[3]))
15192 tx = 1;
15193 else
15194 return CLI_SHOWUSAGE;
15195
15196 channel = atoi(a->argv[4]);
15197 gain = atof(a->argv[5])*10.0;
15198
15199 ast_mutex_lock(&iflock);
15200
15201 for (tmp = iflist; tmp; tmp = tmp->next) {
15202
15203 if (tmp->channel != channel)
15204 continue;
15205
15206 if (tmp->subs[SUB_REAL].dfd == -1)
15207 break;
15208
15209 hwgain.newgain = gain;
15210 hwgain.tx = tx;
15211 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15212 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15213 ast_mutex_unlock(&iflock);
15214 return CLI_FAILURE;
15215 }
15216 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15217 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15218 break;
15219 }
15220
15221 ast_mutex_unlock(&iflock);
15222
15223 if (tmp)
15224 return CLI_SUCCESS;
15225
15226 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15227 return CLI_FAILURE;
15228
15229 }
15230
15231 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15232 {
15233 int channel;
15234 float gain;
15235 int tx;
15236 int res;
15237 struct dahdi_pvt *tmp = NULL;
15238
15239 switch (cmd) {
15240 case CLI_INIT:
15241 e->command = "dahdi set swgain";
15242 e->usage =
15243 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15244 " Sets the software gain on a a given channel, overriding the\n"
15245 " value provided at module loadtime, whether the channel is in\n"
15246 " use or not. Changes take effect immediately.\n"
15247 " <rx|tx> which direction do you want to change (relative to our module)\n"
15248 " <chan num> is the channel number relative to the device\n"
15249 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15250 return NULL;
15251 case CLI_GENERATE:
15252 return NULL;
15253 }
15254
15255 if (a->argc != 6)
15256 return CLI_SHOWUSAGE;
15257
15258 if (!strcasecmp("rx", a->argv[3]))
15259 tx = 0;
15260 else if (!strcasecmp("tx", a->argv[3]))
15261 tx = 1;
15262 else
15263 return CLI_SHOWUSAGE;
15264
15265 channel = atoi(a->argv[4]);
15266 gain = atof(a->argv[5]);
15267
15268 ast_mutex_lock(&iflock);
15269 for (tmp = iflist; tmp; tmp = tmp->next) {
15270
15271 if (tmp->channel != channel)
15272 continue;
15273
15274 if (tmp->subs[SUB_REAL].dfd == -1)
15275 break;
15276
15277 if (tx)
15278 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, gain, tmp->txdrc, tmp->law);
15279 else
15280 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, gain, tmp->rxdrc, tmp->law);
15281
15282 if (res) {
15283 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15284 ast_mutex_unlock(&iflock);
15285 return CLI_FAILURE;
15286 }
15287
15288 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15289 tx ? "tx" : "rx", gain, channel);
15290 break;
15291 }
15292 ast_mutex_unlock(&iflock);
15293
15294 if (tmp)
15295 return CLI_SUCCESS;
15296
15297 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15298 return CLI_FAILURE;
15299
15300 }
15301
15302 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15303 {
15304 int channel;
15305 int on;
15306 struct dahdi_pvt *dahdi_chan = NULL;
15307
15308 switch (cmd) {
15309 case CLI_INIT:
15310 e->command = "dahdi set dnd";
15311 e->usage =
15312 "Usage: dahdi set dnd <chan#> <on|off>\n"
15313 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15314 " Changes take effect immediately.\n"
15315 " <chan num> is the channel number\n"
15316 " <on|off> Enable or disable DND mode?\n"
15317 ;
15318 return NULL;
15319 case CLI_GENERATE:
15320 return NULL;
15321 }
15322
15323 if (a->argc != 5)
15324 return CLI_SHOWUSAGE;
15325
15326 if ((channel = atoi(a->argv[3])) <= 0) {
15327 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15328 return CLI_SHOWUSAGE;
15329 }
15330
15331 if (ast_true(a->argv[4]))
15332 on = 1;
15333 else if (ast_false(a->argv[4]))
15334 on = 0;
15335 else {
15336 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15337 return CLI_SHOWUSAGE;
15338 }
15339
15340 ast_mutex_lock(&iflock);
15341 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15342 if (dahdi_chan->channel != channel)
15343 continue;
15344
15345
15346 dahdi_dnd(dahdi_chan, on);
15347 break;
15348 }
15349 ast_mutex_unlock(&iflock);
15350
15351 if (!dahdi_chan) {
15352 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15353 return CLI_FAILURE;
15354 }
15355
15356 return CLI_SUCCESS;
15357 }
15358
15359 static struct ast_cli_entry dahdi_cli[] = {
15360 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
15361 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
15362 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
15363 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
15364 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
15365 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
15366 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
15367 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
15368 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
15369 AST_CLI_DEFINE(dahdi_set_dnd, "Sets/resets DND (Do Not Disturb) mode on a channel"),
15370 };
15371
15372 #define TRANSFER 0
15373 #define HANGUP 1
15374
15375 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
15376 {
15377 if (p) {
15378 switch (mode) {
15379 case TRANSFER:
15380 p->fake_event = DAHDI_EVENT_WINKFLASH;
15381 break;
15382 case HANGUP:
15383 p->fake_event = DAHDI_EVENT_ONHOOK;
15384 break;
15385 default:
15386 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15387 }
15388 }
15389 return 0;
15390 }
15391 static struct dahdi_pvt *find_channel(int channel)
15392 {
15393 struct dahdi_pvt *p;
15394
15395 ast_mutex_lock(&iflock);
15396 for (p = iflist; p; p = p->next) {
15397 if (p->channel == channel) {
15398 break;
15399 }
15400 }
15401 ast_mutex_unlock(&iflock);
15402 return p;
15403 }
15404
15405 static int action_dahdidndon(struct mansession *s, const struct message *m)
15406 {
15407 struct dahdi_pvt *p = NULL;
15408 const char *channel = astman_get_header(m, "DAHDIChannel");
15409
15410 if (ast_strlen_zero(channel)) {
15411 astman_send_error(s, m, "No channel specified");
15412 return 0;
15413 }
15414 p = find_channel(atoi(channel));
15415 if (!p) {
15416 astman_send_error(s, m, "No such channel");
15417 return 0;
15418 }
15419 dahdi_dnd(p, 1);
15420 astman_send_ack(s, m, "DND Enabled");
15421 return 0;
15422 }
15423
15424 static int action_dahdidndoff(struct mansession *s, const struct message *m)
15425 {
15426 struct dahdi_pvt *p = NULL;
15427 const char *channel = astman_get_header(m, "DAHDIChannel");
15428
15429 if (ast_strlen_zero(channel)) {
15430 astman_send_error(s, m, "No channel specified");
15431 return 0;
15432 }
15433 p = find_channel(atoi(channel));
15434 if (!p) {
15435 astman_send_error(s, m, "No such channel");
15436 return 0;
15437 }
15438 dahdi_dnd(p, 0);
15439 astman_send_ack(s, m, "DND Disabled");
15440 return 0;
15441 }
15442
15443 static int action_transfer(struct mansession *s, const struct message *m)
15444 {
15445 struct dahdi_pvt *p = NULL;
15446 const char *channel = astman_get_header(m, "DAHDIChannel");
15447
15448 if (ast_strlen_zero(channel)) {
15449 astman_send_error(s, m, "No channel specified");
15450 return 0;
15451 }
15452 p = find_channel(atoi(channel));
15453 if (!p) {
15454 astman_send_error(s, m, "No such channel");
15455 return 0;
15456 }
15457 dahdi_fake_event(p,TRANSFER);
15458 astman_send_ack(s, m, "DAHDITransfer");
15459 return 0;
15460 }
15461
15462 static int action_transferhangup(struct mansession *s, const struct message *m)
15463 {
15464 struct dahdi_pvt *p = NULL;
15465 const char *channel = astman_get_header(m, "DAHDIChannel");
15466
15467 if (ast_strlen_zero(channel)) {
15468 astman_send_error(s, m, "No channel specified");
15469 return 0;
15470 }
15471 p = find_channel(atoi(channel));
15472 if (!p) {
15473 astman_send_error(s, m, "No such channel");
15474 return 0;
15475 }
15476 dahdi_fake_event(p,HANGUP);
15477 astman_send_ack(s, m, "DAHDIHangup");
15478 return 0;
15479 }
15480
15481 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
15482 {
15483 struct dahdi_pvt *p = NULL;
15484 const char *channel = astman_get_header(m, "DAHDIChannel");
15485 const char *number = astman_get_header(m, "Number");
15486 int i;
15487
15488 if (ast_strlen_zero(channel)) {
15489 astman_send_error(s, m, "No channel specified");
15490 return 0;
15491 }
15492 if (ast_strlen_zero(number)) {
15493 astman_send_error(s, m, "No number specified");
15494 return 0;
15495 }
15496 p = find_channel(atoi(channel));
15497 if (!p) {
15498 astman_send_error(s, m, "No such channel");
15499 return 0;
15500 }
15501 if (!p->owner) {
15502 astman_send_error(s, m, "Channel does not have it's owner");
15503 return 0;
15504 }
15505 for (i = 0; i < strlen(number); i++) {
15506 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = number[i] };
15507 dahdi_queue_frame(p, &f);
15508 }
15509 astman_send_ack(s, m, "DAHDIDialOffhook");
15510 return 0;
15511 }
15512
15513 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
15514 {
15515 struct dahdi_pvt *tmp = NULL;
15516 const char *id = astman_get_header(m, "ActionID");
15517 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15518 char idText[256] = "";
15519 int channels = 0;
15520 int dahdichanquery = -1;
15521 if (!ast_strlen_zero(dahdichannel)) {
15522 dahdichanquery = atoi(dahdichannel);
15523 }
15524
15525 astman_send_ack(s, m, "DAHDI channel status will follow");
15526 if (!ast_strlen_zero(id))
15527 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15528
15529 ast_mutex_lock(&iflock);
15530
15531 for (tmp = iflist; tmp; tmp = tmp->next) {
15532 if (tmp->channel > 0) {
15533 int alm;
15534
15535
15536 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15537 continue;
15538
15539 alm = get_alarms(tmp);
15540 channels++;
15541 if (tmp->owner) {
15542
15543 astman_append(s,
15544 "Event: DAHDIShowChannels\r\n"
15545 "DAHDIChannel: %d\r\n"
15546 "Channel: %s\r\n"
15547 "Uniqueid: %s\r\n"
15548 "AccountCode: %s\r\n"
15549 "Signalling: %s\r\n"
15550 "SignallingCode: %d\r\n"
15551 "Context: %s\r\n"
15552 "DND: %s\r\n"
15553 "Alarm: %s\r\n"
15554 "%s"
15555 "\r\n",
15556 tmp->channel,
15557 tmp->owner->name,
15558 tmp->owner->uniqueid,
15559 tmp->owner->accountcode,
15560 sig2str(tmp->sig),
15561 tmp->sig,
15562 tmp->context,
15563 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15564 alarm2str(alm), idText);
15565 } else {
15566 astman_append(s,
15567 "Event: DAHDIShowChannels\r\n"
15568 "DAHDIChannel: %d\r\n"
15569 "Signalling: %s\r\n"
15570 "SignallingCode: %d\r\n"
15571 "Context: %s\r\n"
15572 "DND: %s\r\n"
15573 "Alarm: %s\r\n"
15574 "%s"
15575 "\r\n",
15576 tmp->channel, sig2str(tmp->sig), tmp->sig,
15577 tmp->context,
15578 dahdi_dnd(tmp, -1) ? "Enabled" : "Disabled",
15579 alarm2str(alm), idText);
15580 }
15581 }
15582 }
15583
15584 ast_mutex_unlock(&iflock);
15585
15586 astman_append(s,
15587 "Event: DAHDIShowChannelsComplete\r\n"
15588 "%s"
15589 "Items: %d\r\n"
15590 "\r\n",
15591 idText,
15592 channels);
15593 return 0;
15594 }
15595
15596 #if defined(HAVE_SS7)
15597 static int linkset_addsigchan(int sigchan)
15598 {
15599 struct dahdi_ss7 *link;
15600 int res;
15601 int curfd;
15602 struct dahdi_params params;
15603 struct dahdi_bufferinfo bi;
15604 struct dahdi_spaninfo si;
15605
15606 if (sigchan < 0) {
15607 ast_log(LOG_ERROR, "Invalid sigchan!\n");
15608 return -1;
15609 }
15610 if (cur_ss7type < 0) {
15611 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15612 return -1;
15613 }
15614 if (cur_pointcode < 0) {
15615 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15616 return -1;
15617 }
15618 if (cur_adjpointcode < 0) {
15619 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15620 return -1;
15621 }
15622 if (cur_defaultdpc < 0) {
15623 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15624 return -1;
15625 }
15626 if (cur_networkindicator < 0) {
15627 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15628 return -1;
15629 }
15630 link = ss7_resolve_linkset(cur_linkset);
15631 if (!link) {
15632 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
15633 return -1;
15634 }
15635 if (link->ss7.numsigchans >= SIG_SS7_NUM_DCHANS) {
15636 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15637 return -1;
15638 }
15639
15640 curfd = link->ss7.numsigchans;
15641
15642
15643 link->ss7.fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15644 if (link->ss7.fds[curfd] < 0) {
15645 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan,
15646 strerror(errno));
15647 return -1;
15648 }
15649 if (ioctl(link->ss7.fds[curfd], DAHDI_SPECIFY, &sigchan) == -1) {
15650 dahdi_close_ss7_fd(link, curfd);
15651 ast_log(LOG_ERROR, "Unable to specify SS7 sigchan %d (%s)\n", sigchan,
15652 strerror(errno));
15653 return -1;
15654 }
15655
15656
15657 memset(¶ms, 0, sizeof(params));
15658 res = ioctl(link->ss7.fds[curfd], DAHDI_GET_PARAMS, ¶ms);
15659 if (res) {
15660 dahdi_close_ss7_fd(link, curfd);
15661 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan,
15662 strerror(errno));
15663 return -1;
15664 }
15665 if (params.sigtype != DAHDI_SIG_HDLCFCS
15666 && params.sigtype != DAHDI_SIG_HARDHDLC
15667 && params.sigtype != DAHDI_SIG_MTP2) {
15668 dahdi_close_ss7_fd(link, curfd);
15669 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15670 return -1;
15671 }
15672
15673
15674 memset(&bi, 0, sizeof(bi));
15675 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15676 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15677 bi.numbufs = 32;
15678 bi.bufsize = 512;
15679 if (ioctl(link->ss7.fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15680 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n",
15681 sigchan, strerror(errno));
15682 dahdi_close_ss7_fd(link, curfd);
15683 return -1;
15684 }
15685
15686
15687 memset(&si, 0, sizeof(si));
15688 res = ioctl(link->ss7.fds[curfd], DAHDI_SPANSTAT, &si);
15689 if (res) {
15690 dahdi_close_ss7_fd(link, curfd);
15691 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan,
15692 strerror(errno));
15693 }
15694
15695 res = sig_ss7_add_sigchan(&link->ss7, curfd, cur_ss7type,
15696 (params.sigtype == DAHDI_SIG_MTP2)
15697 ? SS7_TRANSPORT_DAHDIMTP2
15698 : SS7_TRANSPORT_DAHDIDCHAN,
15699 si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
15700 if (res) {
15701 dahdi_close_ss7_fd(link, curfd);
15702 return -1;
15703 }
15704
15705 ++link->ss7.numsigchans;
15706
15707 return 0;
15708 }
15709 #endif
15710
15711 #if defined(HAVE_SS7)
15712 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15713 {
15714 int span;
15715 switch (cmd) {
15716 case CLI_INIT:
15717 e->command = "ss7 set debug {on|off} linkset";
15718 e->usage =
15719 "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15720 " Enables debugging on a given SS7 linkset\n";
15721 return NULL;
15722 case CLI_GENERATE:
15723 return NULL;
15724 }
15725 if (a->argc < 6)
15726 return CLI_SHOWUSAGE;
15727 span = atoi(a->argv[5]);
15728 if ((span < 1) || (span > NUM_SPANS)) {
15729 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15730 return CLI_SUCCESS;
15731 }
15732 if (!linksets[span-1].ss7.ss7) {
15733 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15734 } else {
15735 if (!strcasecmp(a->argv[3], "on")) {
15736 ss7_set_debug(linksets[span-1].ss7.ss7, SIG_SS7_DEBUG);
15737 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15738 } else {
15739 ss7_set_debug(linksets[span-1].ss7.ss7, 0);
15740 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15741 }
15742 }
15743
15744 return CLI_SUCCESS;
15745 }
15746 #endif
15747
15748 #if defined(HAVE_SS7)
15749 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15750 {
15751 int linkset, cic;
15752 int blocked = -1, i;
15753 switch (cmd) {
15754 case CLI_INIT:
15755 e->command = "ss7 block cic";
15756 e->usage =
15757 "Usage: ss7 block cic <linkset> <CIC>\n"
15758 " Sends a remote blocking request for the given CIC on the specified linkset\n";
15759 return NULL;
15760 case CLI_GENERATE:
15761 return NULL;
15762 }
15763 if (a->argc == 5)
15764 linkset = atoi(a->argv[3]);
15765 else
15766 return CLI_SHOWUSAGE;
15767
15768 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15769 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15770 return CLI_SUCCESS;
15771 }
15772
15773 if (!linksets[linkset-1].ss7.ss7) {
15774 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15775 return CLI_SUCCESS;
15776 }
15777
15778 cic = atoi(a->argv[4]);
15779
15780 if (cic < 1) {
15781 ast_cli(a->fd, "Invalid CIC specified!\n");
15782 return CLI_SUCCESS;
15783 }
15784
15785 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15786 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15787 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15788 if (!blocked) {
15789 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15790 isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15791 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15792 }
15793 }
15794 }
15795
15796 if (blocked < 0) {
15797 ast_cli(a->fd, "Invalid CIC specified!\n");
15798 return CLI_SUCCESS;
15799 }
15800
15801 if (!blocked)
15802 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15803 else
15804 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15805
15806
15807 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15808
15809 return CLI_SUCCESS;
15810 }
15811 #endif
15812
15813 #if defined(HAVE_SS7)
15814 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15815 {
15816 int linkset;
15817 int i;
15818 switch (cmd) {
15819 case CLI_INIT:
15820 e->command = "ss7 block linkset";
15821 e->usage =
15822 "Usage: ss7 block linkset <linkset number>\n"
15823 " Sends a remote blocking request for all CICs on the given linkset\n";
15824 return NULL;
15825 case CLI_GENERATE:
15826 return NULL;
15827 }
15828 if (a->argc == 4)
15829 linkset = atoi(a->argv[3]);
15830 else
15831 return CLI_SHOWUSAGE;
15832
15833 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15834 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15835 return CLI_SUCCESS;
15836 }
15837
15838 if (!linksets[linkset-1].ss7.ss7) {
15839 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15840 return CLI_SUCCESS;
15841 }
15842
15843 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15844 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15845 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15846 isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15847 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15848 }
15849
15850
15851 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15852
15853 return CLI_SUCCESS;
15854 }
15855 #endif
15856
15857 #if defined(HAVE_SS7)
15858 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15859 {
15860 int linkset, cic;
15861 int i, blocked = -1;
15862 switch (cmd) {
15863 case CLI_INIT:
15864 e->command = "ss7 unblock cic";
15865 e->usage =
15866 "Usage: ss7 unblock cic <linkset> <CIC>\n"
15867 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
15868 return NULL;
15869 case CLI_GENERATE:
15870 return NULL;
15871 }
15872
15873 if (a->argc == 5)
15874 linkset = atoi(a->argv[3]);
15875 else
15876 return CLI_SHOWUSAGE;
15877
15878 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15879 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15880 return CLI_SUCCESS;
15881 }
15882
15883 if (!linksets[linkset-1].ss7.ss7) {
15884 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15885 return CLI_SUCCESS;
15886 }
15887
15888 cic = atoi(a->argv[4]);
15889
15890 if (cic < 1) {
15891 ast_cli(a->fd, "Invalid CIC specified!\n");
15892 return CLI_SUCCESS;
15893 }
15894
15895 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15896 if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
15897 blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
15898 if (blocked) {
15899 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15900 isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15901 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15902 }
15903 }
15904 }
15905
15906 if (blocked > 0)
15907 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15908
15909
15910 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15911
15912 return CLI_SUCCESS;
15913 }
15914 #endif
15915
15916 #if defined(HAVE_SS7)
15917 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15918 {
15919 int linkset;
15920 int i;
15921 switch (cmd) {
15922 case CLI_INIT:
15923 e->command = "ss7 unblock linkset";
15924 e->usage =
15925 "Usage: ss7 unblock linkset <linkset number>\n"
15926 " Sends a remote unblocking request for all CICs on the specified linkset\n";
15927 return NULL;
15928 case CLI_GENERATE:
15929 return NULL;
15930 }
15931
15932 if (a->argc == 4)
15933 linkset = atoi(a->argv[3]);
15934 else
15935 return CLI_SHOWUSAGE;
15936
15937 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15938 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15939 return CLI_SUCCESS;
15940 }
15941
15942 if (!linksets[linkset-1].ss7.ss7) {
15943 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15944 return CLI_SUCCESS;
15945 }
15946
15947 for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
15948 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
15949 ast_mutex_lock(&linksets[linkset-1].ss7.lock);
15950 isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
15951 ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
15952 }
15953
15954
15955 pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
15956
15957 return CLI_SUCCESS;
15958 }
15959 #endif
15960
15961 #if defined(HAVE_SS7)
15962 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15963 {
15964 int linkset;
15965 struct sig_ss7_linkset *ss7;
15966 switch (cmd) {
15967 case CLI_INIT:
15968 e->command = "ss7 show linkset";
15969 e->usage =
15970 "Usage: ss7 show linkset <span>\n"
15971 " Shows the status of an SS7 linkset.\n";
15972 return NULL;
15973 case CLI_GENERATE:
15974 return NULL;
15975 }
15976
15977 if (a->argc < 4)
15978 return CLI_SHOWUSAGE;
15979 linkset = atoi(a->argv[3]);
15980 if ((linkset < 1) || (linkset > NUM_SPANS)) {
15981 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15982 return CLI_SUCCESS;
15983 }
15984 ss7 = &linksets[linkset - 1].ss7;
15985 if (!ss7->ss7) {
15986 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15987 return CLI_SUCCESS;
15988 }
15989
15990 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15991
15992 return CLI_SUCCESS;
15993 }
15994 #endif
15995
15996 #if defined(HAVE_SS7)
15997 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
15998 {
15999 switch (cmd) {
16000 case CLI_INIT:
16001 e->command = "ss7 show version";
16002 e->usage =
16003 "Usage: ss7 show version\n"
16004 " Show the libss7 version\n";
16005 return NULL;
16006 case CLI_GENERATE:
16007 return NULL;
16008 }
16009
16010 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
16011
16012 return CLI_SUCCESS;
16013 }
16014 #endif
16015
16016 #if defined(HAVE_SS7)
16017 static struct ast_cli_entry dahdi_ss7_cli[] = {
16018 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
16019 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
16020 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
16021 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
16022 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
16023 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
16024 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
16025 };
16026 #endif
16027
16028 #if defined(HAVE_PRI)
16029 #if defined(HAVE_PRI_CCSS)
16030
16031
16032
16033
16034
16035
16036
16037
16038
16039
16040
16041
16042
16043
16044
16045
16046
16047 static int dahdi_pri_cc_agent_init(struct ast_cc_agent *agent, struct ast_channel *chan)
16048 {
16049 struct dahdi_pvt *pvt;
16050 struct sig_pri_chan *pvt_chan;
16051 int res;
16052
16053 ast_assert(!strcmp(chan->tech->type, "DAHDI"));
16054
16055 pvt = chan->tech_pvt;
16056 if (dahdi_sig_pri_lib_handles(pvt->sig)) {
16057 pvt_chan = pvt->sig_pvt;
16058 } else {
16059 pvt_chan = NULL;
16060 }
16061 if (!pvt_chan) {
16062 return -1;
16063 }
16064
16065 ast_module_ref(ast_module_info->self);
16066
16067 res = sig_pri_cc_agent_init(agent, pvt_chan);
16068 if (res) {
16069 ast_module_unref(ast_module_info->self);
16070 }
16071 return res;
16072 }
16073 #endif
16074 #endif
16075
16076 #if defined(HAVE_PRI)
16077 #if defined(HAVE_PRI_CCSS)
16078
16079
16080
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091 static void dahdi_pri_cc_agent_destructor(struct ast_cc_agent *agent)
16092 {
16093 sig_pri_cc_agent_destructor(agent);
16094
16095 ast_module_unref(ast_module_info->self);
16096 }
16097 #endif
16098 #endif
16099
16100 #if defined(HAVE_PRI)
16101 #if defined(HAVE_PRI_CCSS)
16102 static struct ast_cc_agent_callbacks dahdi_pri_cc_agent_callbacks = {
16103 .type = dahdi_pri_cc_type,
16104 .init = dahdi_pri_cc_agent_init,
16105 .start_offer_timer = sig_pri_cc_agent_start_offer_timer,
16106 .stop_offer_timer = sig_pri_cc_agent_stop_offer_timer,
16107 .ack = sig_pri_cc_agent_req_ack,
16108 .status_request = sig_pri_cc_agent_status_req,
16109 .stop_ringing = sig_pri_cc_agent_stop_ringing,
16110 .party_b_free = sig_pri_cc_agent_party_b_free,
16111 .start_monitoring = sig_pri_cc_agent_start_monitoring,
16112 .callee_available = sig_pri_cc_agent_callee_available,
16113 .destructor = dahdi_pri_cc_agent_destructor,
16114 };
16115 #endif
16116 #endif
16117
16118 #if defined(HAVE_PRI)
16119 #if defined(HAVE_PRI_CCSS)
16120 static struct ast_cc_monitor_callbacks dahdi_pri_cc_monitor_callbacks = {
16121 .type = dahdi_pri_cc_type,
16122 .request_cc = sig_pri_cc_monitor_req_cc,
16123 .suspend = sig_pri_cc_monitor_suspend,
16124 .unsuspend = sig_pri_cc_monitor_unsuspend,
16125 .status_response = sig_pri_cc_monitor_status_rsp,
16126 .cancel_available_timer = sig_pri_cc_monitor_cancel_available_timer,
16127 .destructor = sig_pri_cc_monitor_destructor,
16128 };
16129 #endif
16130 #endif
16131
16132 static int __unload_module(void)
16133 {
16134 struct dahdi_pvt *p;
16135 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16136 int i, j;
16137 #endif
16138
16139 #ifdef HAVE_PRI
16140 for (i = 0; i < NUM_SPANS; i++) {
16141 if (pris[i].pri.master != AST_PTHREADT_NULL)
16142 pthread_cancel(pris[i].pri.master);
16143 }
16144 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
16145 ast_unregister_application(dahdi_send_keypad_facility_app);
16146 #ifdef HAVE_PRI_PROG_W_CAUSE
16147 ast_unregister_application(dahdi_send_callrerouting_facility_app);
16148 #endif
16149 #endif
16150 #if defined(HAVE_SS7)
16151 for (i = 0; i < NUM_SPANS; i++) {
16152 if (linksets[i].ss7.master != AST_PTHREADT_NULL)
16153 pthread_cancel(linksets[i].ss7.master);
16154 }
16155 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
16156 #endif
16157 #if defined(HAVE_OPENR2)
16158 dahdi_r2_destroy_links();
16159 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
16160 ast_unregister_application(dahdi_accept_r2_call_app);
16161 #endif
16162
16163 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
16164 ast_manager_unregister("DAHDIDialOffhook");
16165 ast_manager_unregister("DAHDIHangup");
16166 ast_manager_unregister("DAHDITransfer");
16167 ast_manager_unregister("DAHDIDNDoff");
16168 ast_manager_unregister("DAHDIDNDon");
16169 ast_manager_unregister("DAHDIShowChannels");
16170 ast_manager_unregister("DAHDIRestart");
16171 ast_data_unregister(NULL);
16172 ast_channel_unregister(&dahdi_tech);
16173
16174
16175 ast_mutex_lock(&iflock);
16176 for (p = iflist; p; p = p->next) {
16177 if (p->owner)
16178 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
16179 }
16180 ast_mutex_unlock(&iflock);
16181
16182 ast_mutex_lock(&monlock);
16183 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
16184 pthread_cancel(monitor_thread);
16185 pthread_kill(monitor_thread, SIGURG);
16186 pthread_join(monitor_thread, NULL);
16187 }
16188 monitor_thread = AST_PTHREADT_STOP;
16189 ast_mutex_unlock(&monlock);
16190
16191 destroy_all_channels();
16192
16193 #if defined(HAVE_PRI)
16194 for (i = 0; i < NUM_SPANS; i++) {
16195 if (pris[i].pri.master && (pris[i].pri.master != AST_PTHREADT_NULL))
16196 pthread_join(pris[i].pri.master, NULL);
16197 for (j = 0; j < SIG_PRI_NUM_DCHANS; j++) {
16198 dahdi_close_pri_fd(&(pris[i]), j);
16199 }
16200 sig_pri_stop_pri(&pris[i].pri);
16201 }
16202 #if defined(HAVE_PRI_CCSS)
16203 ast_cc_agent_unregister(&dahdi_pri_cc_agent_callbacks);
16204 ast_cc_monitor_unregister(&dahdi_pri_cc_monitor_callbacks);
16205 #endif
16206 sig_pri_unload();
16207 #endif
16208
16209 #if defined(HAVE_SS7)
16210 for (i = 0; i < NUM_SPANS; i++) {
16211 if (linksets[i].ss7.master && (linksets[i].ss7.master != AST_PTHREADT_NULL))
16212 pthread_join(linksets[i].ss7.master, NULL);
16213 for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
16214 dahdi_close_ss7_fd(&(linksets[i]), j);
16215 }
16216 }
16217 #endif
16218 ast_cond_destroy(&ss_thread_complete);
16219 return 0;
16220 }
16221
16222 static int unload_module(void)
16223 {
16224 #if defined(HAVE_PRI) || defined(HAVE_SS7)
16225 int y;
16226 #endif
16227 #ifdef HAVE_PRI
16228 for (y = 0; y < NUM_SPANS; y++)
16229 ast_mutex_destroy(&pris[y].pri.lock);
16230 #endif
16231 #if defined(HAVE_SS7)
16232 for (y = 0; y < NUM_SPANS; y++)
16233 ast_mutex_destroy(&linksets[y].ss7.lock);
16234 #endif
16235 return __unload_module();
16236 }
16237
16238 static void string_replace(char *str, int char1, int char2)
16239 {
16240 for (; *str; str++) {
16241 if (*str == char1) {
16242 *str = char2;
16243 }
16244 }
16245 }
16246
16247 static char *parse_spanchan(char *chanstr, char **subdir)
16248 {
16249 char *p;
16250
16251 if ((p = strrchr(chanstr, '!')) == NULL) {
16252 *subdir = NULL;
16253 return chanstr;
16254 }
16255 *p++ = '\0';
16256 string_replace(chanstr, '!', '/');
16257 *subdir = chanstr;
16258 return p;
16259 }
16260
16261 static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
16262 {
16263 char *c, *chan;
16264 char *subdir;
16265 int x, start, finish;
16266 struct dahdi_pvt *tmp;
16267
16268 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
16269 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
16270 return -1;
16271 }
16272
16273 c = ast_strdupa(value);
16274 c = parse_spanchan(c, &subdir);
16275
16276 while ((chan = strsep(&c, ","))) {
16277 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
16278
16279 } else if (sscanf(chan, "%30d", &start)) {
16280
16281 finish = start;
16282 } else if (!strcasecmp(chan, "pseudo")) {
16283 finish = start = CHAN_PSEUDO;
16284 if (found_pseudo)
16285 *found_pseudo = 1;
16286 } else {
16287 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16288 return -1;
16289 }
16290 if (finish < start) {
16291 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16292 x = finish;
16293 finish = start;
16294 start = x;
16295 }
16296
16297 for (x = start; x <= finish; x++) {
16298 char fn[PATH_MAX];
16299 int real_channel = x;
16300
16301 if (!ast_strlen_zero(subdir)) {
16302 real_channel = device2chan(subdir, x, fn, sizeof(fn));
16303 if (real_channel < 0) {
16304 if (conf->ignore_failed_channels) {
16305 ast_log(LOG_WARNING, "Failed configuring %s!%d, (got %d). But moving on to others.\n",
16306 subdir, x, real_channel);
16307 continue;
16308 } else {
16309 ast_log(LOG_ERROR, "Failed configuring %s!%d, (got %d).\n",
16310 subdir, x, real_channel);
16311 return -1;
16312 }
16313 }
16314 }
16315 tmp = mkintf(real_channel, conf, reload);
16316
16317 if (tmp) {
16318 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", real_channel, sig2str(tmp->sig));
16319 } else {
16320 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16321 (reload == 1) ? "reconfigure" : "register", value);
16322 return -1;
16323 }
16324 }
16325 }
16326
16327 return 0;
16328 }
16329
16330
16331
16332 #define MAX_CHANLIST_LEN 80
16333
16334 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
16335 {
16336 char *parse = ast_strdupa(data);
16337 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16338 unsigned int param_count;
16339 unsigned int x;
16340
16341 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16342 return;
16343
16344 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16345
16346
16347
16348 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16349
16350 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16351 confp->chan.echocancel.head.tap_length = x;
16352 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16353 confp->chan.echocancel.head.tap_length = 128;
16354
16355
16356
16357 for (x = 1; x < param_count; x++) {
16358 struct {
16359 char *name;
16360 char *value;
16361 } param;
16362
16363 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) {
16364 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16365 continue;
16366 }
16367
16368 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16369 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16370 continue;
16371 }
16372
16373 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16374
16375 if (param.value) {
16376 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16377 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16378 continue;
16379 }
16380 }
16381 confp->chan.echocancel.head.param_count++;
16382 }
16383 }
16384
16385
16386 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
16387
16388 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
16389
16390 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
16391 {
16392 struct dahdi_pvt *tmp;
16393 int y;
16394 int found_pseudo = 0;
16395 char dahdichan[MAX_CHANLIST_LEN] = {};
16396
16397 for (; v; v = v->next) {
16398 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16399 continue;
16400
16401
16402 if (!strcasecmp(v->name, "parkinglot")) {
16403 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16404 }
16405
16406
16407 if (!strcasecmp(v->name, "channel") || !strcasecmp(v->name, "channels")) {
16408 if (options & PROC_DAHDI_OPT_NOCHAN) {
16409 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16410 continue;
16411 }
16412 if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
16413 if (confp->ignore_failed_channels) {
16414 ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
16415 continue;
16416 } else {
16417 return -1;
16418 }
16419 }
16420 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16421 } else if (!strcasecmp(v->name, "ignore_failed_channels")) {
16422 confp->ignore_failed_channels = ast_true(v->value);
16423 } else if (!strcasecmp(v->name, "buffers")) {
16424 if (parse_buffers_policy(v->value, &confp->chan.buf_no, &confp->chan.buf_policy)) {
16425 ast_log(LOG_WARNING, "Using default buffer policy.\n");
16426 confp->chan.buf_no = numbufs;
16427 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16428 }
16429 } else if (!strcasecmp(v->name, "faxbuffers")) {
16430 if (!parse_buffers_policy(v->value, &confp->chan.faxbuf_no, &confp->chan.faxbuf_policy)) {
16431 confp->chan.usefaxbuffers = 1;
16432 }
16433 } else if (!strcasecmp(v->name, "dahdichan")) {
16434 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16435 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16436 usedistinctiveringdetection = ast_true(v->value);
16437 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16438 distinctiveringaftercid = ast_true(v->value);
16439 } else if (!strcasecmp(v->name, "dring1context")) {
16440 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16441 } else if (!strcasecmp(v->name, "dring2context")) {
16442 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16443 } else if (!strcasecmp(v->name, "dring3context")) {
16444 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16445 } else if (!strcasecmp(v->name, "dring1range")) {
16446 confp->chan.drings.ringnum[0].range = atoi(v->value);
16447 } else if (!strcasecmp(v->name, "dring2range")) {
16448 confp->chan.drings.ringnum[1].range = atoi(v->value);
16449 } else if (!strcasecmp(v->name, "dring3range")) {
16450 confp->chan.drings.ringnum[2].range = atoi(v->value);
16451 } else if (!strcasecmp(v->name, "dring1")) {
16452 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]);
16453 } else if (!strcasecmp(v->name, "dring2")) {
16454 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]);
16455 } else if (!strcasecmp(v->name, "dring3")) {
16456 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]);
16457 } else if (!strcasecmp(v->name, "usecallerid")) {
16458 confp->chan.use_callerid = ast_true(v->value);
16459 } else if (!strcasecmp(v->name, "cidsignalling")) {
16460 if (!strcasecmp(v->value, "bell"))
16461 confp->chan.cid_signalling = CID_SIG_BELL;
16462 else if (!strcasecmp(v->value, "v23"))
16463 confp->chan.cid_signalling = CID_SIG_V23;
16464 else if (!strcasecmp(v->value, "dtmf"))
16465 confp->chan.cid_signalling = CID_SIG_DTMF;
16466 else if (!strcasecmp(v->value, "smdi"))
16467 confp->chan.cid_signalling = CID_SIG_SMDI;
16468 else if (!strcasecmp(v->value, "v23_jp"))
16469 confp->chan.cid_signalling = CID_SIG_V23_JP;
16470 else if (ast_true(v->value))
16471 confp->chan.cid_signalling = CID_SIG_BELL;
16472 } else if (!strcasecmp(v->name, "cidstart")) {
16473 if (!strcasecmp(v->value, "ring"))
16474 confp->chan.cid_start = CID_START_RING;
16475 else if (!strcasecmp(v->value, "polarity_in"))
16476 confp->chan.cid_start = CID_START_POLARITY_IN;
16477 else if (!strcasecmp(v->value, "polarity"))
16478 confp->chan.cid_start = CID_START_POLARITY;
16479 else if (!strcasecmp(v->value, "dtmf"))
16480 confp->chan.cid_start = CID_START_DTMF_NOALERT;
16481 else if (ast_true(v->value))
16482 confp->chan.cid_start = CID_START_RING;
16483 } else if (!strcasecmp(v->name, "threewaycalling")) {
16484 confp->chan.threewaycalling = ast_true(v->value);
16485 } else if (!strcasecmp(v->name, "cancallforward")) {
16486 confp->chan.cancallforward = ast_true(v->value);
16487 } else if (!strcasecmp(v->name, "relaxdtmf")) {
16488 if (ast_true(v->value))
16489 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16490 else
16491 confp->chan.dtmfrelax = 0;
16492 } else if (!strcasecmp(v->name, "mailbox")) {
16493 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16494 } else if (!strcasecmp(v->name, "hasvoicemail")) {
16495 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16496 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16497 }
16498 } else if (!strcasecmp(v->name, "adsi")) {
16499 confp->chan.adsi = ast_true(v->value);
16500 } else if (!strcasecmp(v->name, "usesmdi")) {
16501 confp->chan.use_smdi = ast_true(v->value);
16502 } else if (!strcasecmp(v->name, "smdiport")) {
16503 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16504 } else if (!strcasecmp(v->name, "transfer")) {
16505 confp->chan.transfer = ast_true(v->value);
16506 } else if (!strcasecmp(v->name, "canpark")) {
16507 confp->chan.canpark = ast_true(v->value);
16508 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16509 confp->chan.echocanbridged = ast_true(v->value);
16510 } else if (!strcasecmp(v->name, "busydetect")) {
16511 confp->chan.busydetect = ast_true(v->value);
16512 } else if (!strcasecmp(v->name, "busycount")) {
16513 confp->chan.busycount = atoi(v->value);
16514 } else if (!strcasecmp(v->name, "busypattern")) {
16515 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16516 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16517 }
16518 } else if (!strcasecmp(v->name, "callprogress")) {
16519 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16520 if (ast_true(v->value))
16521 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16522 } else if (!strcasecmp(v->name, "waitfordialtone")) {
16523 confp->chan.waitfordialtone = atoi(v->value);
16524 } else if (!strcasecmp(v->name, "faxdetect")) {
16525 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16526 if (!strcasecmp(v->value, "incoming")) {
16527 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16528 } else if (!strcasecmp(v->value, "outgoing")) {
16529 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16530 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16531 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16532 } else if (!strcasecmp(v->name, "echocancel")) {
16533 process_echocancel(confp, v->value, v->lineno);
16534 } else if (!strcasecmp(v->name, "echotraining")) {
16535 if (sscanf(v->value, "%30d", &y) == 1) {
16536 if ((y < 10) || (y > 4000)) {
16537 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16538 } else {
16539 confp->chan.echotraining = y;
16540 }
16541 } else if (ast_true(v->value)) {
16542 confp->chan.echotraining = 400;
16543 } else
16544 confp->chan.echotraining = 0;
16545 } else if (!strcasecmp(v->name, "hidecallerid")) {
16546 confp->chan.hidecallerid = ast_true(v->value);
16547 } else if (!strcasecmp(v->name, "hidecalleridname")) {
16548 confp->chan.hidecalleridname = ast_true(v->value);
16549 } else if (!strcasecmp(v->name, "pulsedial")) {
16550 confp->chan.pulse = ast_true(v->value);
16551 } else if (!strcasecmp(v->name, "callreturn")) {
16552 confp->chan.callreturn = ast_true(v->value);
16553 } else if (!strcasecmp(v->name, "callwaiting")) {
16554 confp->chan.callwaiting = ast_true(v->value);
16555 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16556 confp->chan.callwaitingcallerid = ast_true(v->value);
16557 } else if (!strcasecmp(v->name, "context")) {
16558 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16559 } else if (!strcasecmp(v->name, "language")) {
16560 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16561 } else if (!strcasecmp(v->name, "progzone")) {
16562 ast_copy_string(progzone, v->value, sizeof(progzone));
16563 } else if (!strcasecmp(v->name, "mohinterpret")
16564 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16565 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16566 } else if (!strcasecmp(v->name, "mohsuggest")) {
16567 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16568 } else if (!strcasecmp(v->name, "parkinglot")) {
16569 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16570 } else if (!strcasecmp(v->name, "stripmsd")) {
16571 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16572 confp->chan.stripmsd = atoi(v->value);
16573 } else if (!strcasecmp(v->name, "jitterbuffers")) {
16574 numbufs = atoi(v->value);
16575 } else if (!strcasecmp(v->name, "group")) {
16576 confp->chan.group = ast_get_group(v->value);
16577 } else if (!strcasecmp(v->name, "callgroup")) {
16578 if (!strcasecmp(v->value, "none"))
16579 confp->chan.callgroup = 0;
16580 else
16581 confp->chan.callgroup = ast_get_group(v->value);
16582 } else if (!strcasecmp(v->name, "pickupgroup")) {
16583 if (!strcasecmp(v->value, "none"))
16584 confp->chan.pickupgroup = 0;
16585 else
16586 confp->chan.pickupgroup = ast_get_group(v->value);
16587 } else if (!strcasecmp(v->name, "setvar")) {
16588 char *varname = ast_strdupa(v->value), *varval = NULL;
16589 struct ast_variable *tmpvar;
16590 if (varname && (varval = strchr(varname, '='))) {
16591 *varval++ = '\0';
16592 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16593 tmpvar->next = confp->chan.vars;
16594 confp->chan.vars = tmpvar;
16595 }
16596 }
16597 } else if (!strcasecmp(v->name, "immediate")) {
16598 confp->chan.immediate = ast_true(v->value);
16599 } else if (!strcasecmp(v->name, "transfertobusy")) {
16600 confp->chan.transfertobusy = ast_true(v->value);
16601 } else if (!strcasecmp(v->name, "mwimonitor")) {
16602 confp->chan.mwimonitor_neon = 0;
16603 confp->chan.mwimonitor_fsk = 0;
16604 confp->chan.mwimonitor_rpas = 0;
16605 if (strcasestr(v->value, "fsk")) {
16606 confp->chan.mwimonitor_fsk = 1;
16607 }
16608 if (strcasestr(v->value, "rpas")) {
16609 confp->chan.mwimonitor_rpas = 1;
16610 }
16611 if (strcasestr(v->value, "neon")) {
16612 confp->chan.mwimonitor_neon = 1;
16613 }
16614
16615 if (ast_true(v->value)) {
16616 confp->chan.mwimonitor_fsk = 1;
16617 }
16618 } else if (!strcasecmp(v->name, "cid_rxgain")) {
16619 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16620 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16621 }
16622 } else if (!strcasecmp(v->name, "rxgain")) {
16623 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16624 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16625 }
16626 } else if (!strcasecmp(v->name, "txgain")) {
16627 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16628 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16629 }
16630 } else if (!strcasecmp(v->name, "txdrc")) {
16631 if (sscanf(v->value, "%f", &confp->chan.txdrc) != 1) {
16632 ast_log(LOG_WARNING, "Invalid txdrc: %s\n", v->value);
16633 }
16634 } else if (!strcasecmp(v->name, "rxdrc")) {
16635 if (sscanf(v->value, "%f", &confp->chan.rxdrc) != 1) {
16636 ast_log(LOG_WARNING, "Invalid rxdrc: %s\n", v->value);
16637 }
16638 } else if (!strcasecmp(v->name, "tonezone")) {
16639 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16640 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16641 }
16642 } else if (!strcasecmp(v->name, "callerid")) {
16643 if (!strcasecmp(v->value, "asreceived")) {
16644 confp->chan.cid_num[0] = '\0';
16645 confp->chan.cid_name[0] = '\0';
16646 } else {
16647 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16648 }
16649 } else if (!strcasecmp(v->name, "fullname")) {
16650 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16651 } else if (!strcasecmp(v->name, "cid_number")) {
16652 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16653 } else if (!strcasecmp(v->name, "cid_tag")) {
16654 ast_copy_string(confp->chan.cid_tag, v->value, sizeof(confp->chan.cid_tag));
16655 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16656 confp->chan.dahditrcallerid = ast_true(v->value);
16657 } else if (!strcasecmp(v->name, "restrictcid")) {
16658 confp->chan.restrictcid = ast_true(v->value);
16659 } else if (!strcasecmp(v->name, "usecallingpres")) {
16660 confp->chan.use_callingpres = ast_true(v->value);
16661 } else if (!strcasecmp(v->name, "accountcode")) {
16662 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16663 } else if (!strcasecmp(v->name, "amaflags")) {
16664 y = ast_cdr_amaflags2int(v->value);
16665 if (y < 0)
16666 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16667 else
16668 confp->chan.amaflags = y;
16669 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16670 confp->chan.polarityonanswerdelay = atoi(v->value);
16671 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16672 confp->chan.answeronpolarityswitch = ast_true(v->value);
16673 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16674 confp->chan.hanguponpolarityswitch = ast_true(v->value);
16675 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16676 confp->chan.sendcalleridafter = atoi(v->value);
16677 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16678 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16679 } else if (ast_cc_is_config_param(v->name)) {
16680 ast_cc_set_param(confp->chan.cc_params, v->name, v->value);
16681 } else if (!strcasecmp(v->name, "mwisendtype")) {
16682 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI
16683 if (!strcasecmp(v->value, "rpas")) {
16684 mwisend_rpas = 1;
16685 } else {
16686 mwisend_rpas = 0;
16687 }
16688 #else
16689
16690 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16691 if (strcasestr(v->value, "nofsk")) {
16692 confp->chan.mwisend_fsk = 0;
16693 } else {
16694 confp->chan.mwisend_fsk = 1;
16695 }
16696 if (strcasestr(v->value, "rpas")) {
16697 confp->chan.mwisend_rpas = 1;
16698 } else {
16699 confp->chan.mwisend_rpas = 0;
16700 }
16701 if (strcasestr(v->value, "lrev")) {
16702 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16703 }
16704 if (strcasestr(v->value, "hvdc")) {
16705 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16706 }
16707 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){
16708 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16709 }
16710 #endif
16711 } else if (reload != 1) {
16712 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16713 int orig_radio = confp->chan.radio;
16714 int orig_outsigmod = confp->chan.outsigmod;
16715 int orig_auto = confp->is_sig_auto;
16716
16717 confp->chan.radio = 0;
16718 confp->chan.outsigmod = -1;
16719 confp->is_sig_auto = 0;
16720 if (!strcasecmp(v->value, "em")) {
16721 confp->chan.sig = SIG_EM;
16722 } else if (!strcasecmp(v->value, "em_e1")) {
16723 confp->chan.sig = SIG_EM_E1;
16724 } else if (!strcasecmp(v->value, "em_w")) {
16725 confp->chan.sig = SIG_EMWINK;
16726 } else if (!strcasecmp(v->value, "fxs_ls")) {
16727 confp->chan.sig = SIG_FXSLS;
16728 } else if (!strcasecmp(v->value, "fxs_gs")) {
16729 confp->chan.sig = SIG_FXSGS;
16730 } else if (!strcasecmp(v->value, "fxs_ks")) {
16731 confp->chan.sig = SIG_FXSKS;
16732 } else if (!strcasecmp(v->value, "fxo_ls")) {
16733 confp->chan.sig = SIG_FXOLS;
16734 } else if (!strcasecmp(v->value, "fxo_gs")) {
16735 confp->chan.sig = SIG_FXOGS;
16736 } else if (!strcasecmp(v->value, "fxo_ks")) {
16737 confp->chan.sig = SIG_FXOKS;
16738 } else if (!strcasecmp(v->value, "fxs_rx")) {
16739 confp->chan.sig = SIG_FXSKS;
16740 confp->chan.radio = 1;
16741 } else if (!strcasecmp(v->value, "fxo_rx")) {
16742 confp->chan.sig = SIG_FXOLS;
16743 confp->chan.radio = 1;
16744 } else if (!strcasecmp(v->value, "fxs_tx")) {
16745 confp->chan.sig = SIG_FXSLS;
16746 confp->chan.radio = 1;
16747 } else if (!strcasecmp(v->value, "fxo_tx")) {
16748 confp->chan.sig = SIG_FXOGS;
16749 confp->chan.radio = 1;
16750 } else if (!strcasecmp(v->value, "em_rx")) {
16751 confp->chan.sig = SIG_EM;
16752 confp->chan.radio = 1;
16753 } else if (!strcasecmp(v->value, "em_tx")) {
16754 confp->chan.sig = SIG_EM;
16755 confp->chan.radio = 1;
16756 } else if (!strcasecmp(v->value, "em_rxtx")) {
16757 confp->chan.sig = SIG_EM;
16758 confp->chan.radio = 2;
16759 } else if (!strcasecmp(v->value, "em_txrx")) {
16760 confp->chan.sig = SIG_EM;
16761 confp->chan.radio = 2;
16762 } else if (!strcasecmp(v->value, "sf")) {
16763 confp->chan.sig = SIG_SF;
16764 } else if (!strcasecmp(v->value, "sf_w")) {
16765 confp->chan.sig = SIG_SFWINK;
16766 } else if (!strcasecmp(v->value, "sf_featd")) {
16767 confp->chan.sig = SIG_FEATD;
16768 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16769 confp->chan.sig = SIG_FEATDMF;
16770 } else if (!strcasecmp(v->value, "sf_featb")) {
16771 confp->chan.sig = SIG_SF_FEATB;
16772 } else if (!strcasecmp(v->value, "sf")) {
16773 confp->chan.sig = SIG_SF;
16774 } else if (!strcasecmp(v->value, "sf_rx")) {
16775 confp->chan.sig = SIG_SF;
16776 confp->chan.radio = 1;
16777 } else if (!strcasecmp(v->value, "sf_tx")) {
16778 confp->chan.sig = SIG_SF;
16779 confp->chan.radio = 1;
16780 } else if (!strcasecmp(v->value, "sf_rxtx")) {
16781 confp->chan.sig = SIG_SF;
16782 confp->chan.radio = 2;
16783 } else if (!strcasecmp(v->value, "sf_txrx")) {
16784 confp->chan.sig = SIG_SF;
16785 confp->chan.radio = 2;
16786 } else if (!strcasecmp(v->value, "featd")) {
16787 confp->chan.sig = SIG_FEATD;
16788 } else if (!strcasecmp(v->value, "featdmf")) {
16789 confp->chan.sig = SIG_FEATDMF;
16790 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16791 confp->chan.sig = SIG_FEATDMF_TA;
16792 } else if (!strcasecmp(v->value, "e911")) {
16793 confp->chan.sig = SIG_E911;
16794 } else if (!strcasecmp(v->value, "fgccama")) {
16795 confp->chan.sig = SIG_FGC_CAMA;
16796 } else if (!strcasecmp(v->value, "fgccamamf")) {
16797 confp->chan.sig = SIG_FGC_CAMAMF;
16798 } else if (!strcasecmp(v->value, "featb")) {
16799 confp->chan.sig = SIG_FEATB;
16800 #ifdef HAVE_PRI
16801 } else if (!strcasecmp(v->value, "pri_net")) {
16802 confp->chan.sig = SIG_PRI;
16803 confp->pri.pri.nodetype = PRI_NETWORK;
16804 } else if (!strcasecmp(v->value, "pri_cpe")) {
16805 confp->chan.sig = SIG_PRI;
16806 confp->pri.pri.nodetype = PRI_CPE;
16807 } else if (!strcasecmp(v->value, "bri_cpe")) {
16808 confp->chan.sig = SIG_BRI;
16809 confp->pri.pri.nodetype = PRI_CPE;
16810 } else if (!strcasecmp(v->value, "bri_net")) {
16811 confp->chan.sig = SIG_BRI;
16812 confp->pri.pri.nodetype = PRI_NETWORK;
16813 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16814 confp->chan.sig = SIG_BRI_PTMP;
16815 confp->pri.pri.nodetype = PRI_CPE;
16816 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16817 #if defined(HAVE_PRI_CALL_HOLD)
16818 confp->chan.sig = SIG_BRI_PTMP;
16819 confp->pri.pri.nodetype = PRI_NETWORK;
16820 #else
16821 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
16822 #endif
16823 #endif
16824 #if defined(HAVE_SS7)
16825 } else if (!strcasecmp(v->value, "ss7")) {
16826 confp->chan.sig = SIG_SS7;
16827 #endif
16828 #ifdef HAVE_OPENR2
16829 } else if (!strcasecmp(v->value, "mfcr2")) {
16830 confp->chan.sig = SIG_MFCR2;
16831 #endif
16832 } else if (!strcasecmp(v->value, "auto")) {
16833 confp->is_sig_auto = 1;
16834 } else {
16835 confp->chan.outsigmod = orig_outsigmod;
16836 confp->chan.radio = orig_radio;
16837 confp->is_sig_auto = orig_auto;
16838 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16839 }
16840 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16841 if (!strcasecmp(v->value, "em")) {
16842 confp->chan.outsigmod = SIG_EM;
16843 } else if (!strcasecmp(v->value, "em_e1")) {
16844 confp->chan.outsigmod = SIG_EM_E1;
16845 } else if (!strcasecmp(v->value, "em_w")) {
16846 confp->chan.outsigmod = SIG_EMWINK;
16847 } else if (!strcasecmp(v->value, "sf")) {
16848 confp->chan.outsigmod = SIG_SF;
16849 } else if (!strcasecmp(v->value, "sf_w")) {
16850 confp->chan.outsigmod = SIG_SFWINK;
16851 } else if (!strcasecmp(v->value, "sf_featd")) {
16852 confp->chan.outsigmod = SIG_FEATD;
16853 } else if (!strcasecmp(v->value, "sf_featdmf")) {
16854 confp->chan.outsigmod = SIG_FEATDMF;
16855 } else if (!strcasecmp(v->value, "sf_featb")) {
16856 confp->chan.outsigmod = SIG_SF_FEATB;
16857 } else if (!strcasecmp(v->value, "sf")) {
16858 confp->chan.outsigmod = SIG_SF;
16859 } else if (!strcasecmp(v->value, "featd")) {
16860 confp->chan.outsigmod = SIG_FEATD;
16861 } else if (!strcasecmp(v->value, "featdmf")) {
16862 confp->chan.outsigmod = SIG_FEATDMF;
16863 } else if (!strcasecmp(v->value, "featdmf_ta")) {
16864 confp->chan.outsigmod = SIG_FEATDMF_TA;
16865 } else if (!strcasecmp(v->value, "e911")) {
16866 confp->chan.outsigmod = SIG_E911;
16867 } else if (!strcasecmp(v->value, "fgccama")) {
16868 confp->chan.outsigmod = SIG_FGC_CAMA;
16869 } else if (!strcasecmp(v->value, "fgccamamf")) {
16870 confp->chan.outsigmod = SIG_FGC_CAMAMF;
16871 } else if (!strcasecmp(v->value, "featb")) {
16872 confp->chan.outsigmod = SIG_FEATB;
16873 } else {
16874 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16875 }
16876 #ifdef HAVE_PRI
16877 } else if (!strcasecmp(v->name, "pridialplan")) {
16878 if (!strcasecmp(v->value, "national")) {
16879 confp->pri.pri.dialplan = PRI_NATIONAL_ISDN + 1;
16880 } else if (!strcasecmp(v->value, "unknown")) {
16881 confp->pri.pri.dialplan = PRI_UNKNOWN + 1;
16882 } else if (!strcasecmp(v->value, "private")) {
16883 confp->pri.pri.dialplan = PRI_PRIVATE + 1;
16884 } else if (!strcasecmp(v->value, "international")) {
16885 confp->pri.pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16886 } else if (!strcasecmp(v->value, "local")) {
16887 confp->pri.pri.dialplan = PRI_LOCAL_ISDN + 1;
16888 } else if (!strcasecmp(v->value, "dynamic")) {
16889 confp->pri.pri.dialplan = -1;
16890 } else if (!strcasecmp(v->value, "redundant")) {
16891 confp->pri.pri.dialplan = -2;
16892 } else {
16893 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16894 }
16895 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16896 if (!strcasecmp(v->value, "national")) {
16897 confp->pri.pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16898 } else if (!strcasecmp(v->value, "unknown")) {
16899 confp->pri.pri.localdialplan = PRI_UNKNOWN + 1;
16900 } else if (!strcasecmp(v->value, "private")) {
16901 confp->pri.pri.localdialplan = PRI_PRIVATE + 1;
16902 } else if (!strcasecmp(v->value, "international")) {
16903 confp->pri.pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16904 } else if (!strcasecmp(v->value, "local")) {
16905 confp->pri.pri.localdialplan = PRI_LOCAL_ISDN + 1;
16906 } else if (!strcasecmp(v->value, "dynamic")) {
16907 confp->pri.pri.localdialplan = -1;
16908 } else if (!strcasecmp(v->value, "redundant")) {
16909 confp->pri.pri.localdialplan = -2;
16910 } else {
16911 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16912 }
16913 } else if (!strcasecmp(v->name, "switchtype")) {
16914 if (!strcasecmp(v->value, "national"))
16915 confp->pri.pri.switchtype = PRI_SWITCH_NI2;
16916 else if (!strcasecmp(v->value, "ni1"))
16917 confp->pri.pri.switchtype = PRI_SWITCH_NI1;
16918 else if (!strcasecmp(v->value, "dms100"))
16919 confp->pri.pri.switchtype = PRI_SWITCH_DMS100;
16920 else if (!strcasecmp(v->value, "4ess"))
16921 confp->pri.pri.switchtype = PRI_SWITCH_ATT4ESS;
16922 else if (!strcasecmp(v->value, "5ess"))
16923 confp->pri.pri.switchtype = PRI_SWITCH_LUCENT5E;
16924 else if (!strcasecmp(v->value, "euroisdn"))
16925 confp->pri.pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16926 else if (!strcasecmp(v->value, "qsig"))
16927 confp->pri.pri.switchtype = PRI_SWITCH_QSIG;
16928 else {
16929 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16930 return -1;
16931 }
16932 } else if (!strcasecmp(v->name, "msn")) {
16933 ast_copy_string(confp->pri.pri.msn_list, v->value,
16934 sizeof(confp->pri.pri.msn_list));
16935 } else if (!strcasecmp(v->name, "nsf")) {
16936 if (!strcasecmp(v->value, "sdn"))
16937 confp->pri.pri.nsf = PRI_NSF_SDN;
16938 else if (!strcasecmp(v->value, "megacom"))
16939 confp->pri.pri.nsf = PRI_NSF_MEGACOM;
16940 else if (!strcasecmp(v->value, "tollfreemegacom"))
16941 confp->pri.pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16942 else if (!strcasecmp(v->value, "accunet"))
16943 confp->pri.pri.nsf = PRI_NSF_ACCUNET;
16944 else if (!strcasecmp(v->value, "none"))
16945 confp->pri.pri.nsf = PRI_NSF_NONE;
16946 else {
16947 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16948 confp->pri.pri.nsf = PRI_NSF_NONE;
16949 }
16950 } else if (!strcasecmp(v->name, "priindication")) {
16951 if (!strcasecmp(v->value, "outofband"))
16952 confp->chan.priindication_oob = 1;
16953 else if (!strcasecmp(v->value, "inband"))
16954 confp->chan.priindication_oob = 0;
16955 else
16956 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16957 v->value, v->lineno);
16958 } else if (!strcasecmp(v->name, "priexclusive")) {
16959 confp->chan.priexclusive = ast_true(v->value);
16960 } else if (!strcasecmp(v->name, "internationalprefix")) {
16961 ast_copy_string(confp->pri.pri.internationalprefix, v->value, sizeof(confp->pri.pri.internationalprefix));
16962 } else if (!strcasecmp(v->name, "nationalprefix")) {
16963 ast_copy_string(confp->pri.pri.nationalprefix, v->value, sizeof(confp->pri.pri.nationalprefix));
16964 } else if (!strcasecmp(v->name, "localprefix")) {
16965 ast_copy_string(confp->pri.pri.localprefix, v->value, sizeof(confp->pri.pri.localprefix));
16966 } else if (!strcasecmp(v->name, "privateprefix")) {
16967 ast_copy_string(confp->pri.pri.privateprefix, v->value, sizeof(confp->pri.pri.privateprefix));
16968 } else if (!strcasecmp(v->name, "unknownprefix")) {
16969 ast_copy_string(confp->pri.pri.unknownprefix, v->value, sizeof(confp->pri.pri.unknownprefix));
16970 } else if (!strcasecmp(v->name, "resetinterval")) {
16971 if (!strcasecmp(v->value, "never"))
16972 confp->pri.pri.resetinterval = -1;
16973 else if (atoi(v->value) >= 60)
16974 confp->pri.pri.resetinterval = atoi(v->value);
16975 else
16976 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16977 v->value, v->lineno);
16978 } else if (!strcasecmp(v->name, "minunused")) {
16979 confp->pri.pri.minunused = atoi(v->value);
16980 } else if (!strcasecmp(v->name, "minidle")) {
16981 confp->pri.pri.minidle = atoi(v->value);
16982 } else if (!strcasecmp(v->name, "idleext")) {
16983 ast_copy_string(confp->pri.pri.idleext, v->value, sizeof(confp->pri.pri.idleext));
16984 } else if (!strcasecmp(v->name, "idledial")) {
16985 ast_copy_string(confp->pri.pri.idledial, v->value, sizeof(confp->pri.pri.idledial));
16986 } else if (!strcasecmp(v->name, "overlapdial")) {
16987 if (ast_true(v->value)) {
16988 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16989 } else if (!strcasecmp(v->value, "incoming")) {
16990 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16991 } else if (!strcasecmp(v->value, "outgoing")) {
16992 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16993 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16994 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16995 } else {
16996 confp->pri.pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16997 }
16998 #ifdef HAVE_PRI_PROG_W_CAUSE
16999 } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
17000 if (!strcasecmp(v->value, "logical")) {
17001 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
17002 } else if (!strcasecmp(v->value, "physical")) {
17003 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17004 } else {
17005 confp->pri.pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
17006 }
17007 #endif
17008 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
17009 confp->pri.pri.discardremoteholdretrieval = ast_true(v->value);
17010 #if defined(HAVE_PRI_SERVICE_MESSAGES)
17011 } else if (!strcasecmp(v->name, "service_message_support")) {
17012
17013 if ((confp->pri.pri.switchtype == PRI_SWITCH_ATT4ESS
17014 || confp->pri.pri.switchtype == PRI_SWITCH_LUCENT5E
17015 || confp->pri.pri.switchtype == PRI_SWITCH_NI2) && ast_true(v->value)) {
17016 confp->pri.pri.enable_service_message_support = 1;
17017 } else {
17018 confp->pri.pri.enable_service_message_support = 0;
17019 }
17020 #endif
17021 #ifdef HAVE_PRI_INBANDDISCONNECT
17022 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
17023 confp->pri.pri.inbanddisconnect = ast_true(v->value);
17024 #endif
17025 } else if (!strcasecmp(v->name, "pritimer")) {
17026 #ifdef PRI_GETSET_TIMERS
17027 char tmp[20];
17028 char *timerc;
17029 char *c;
17030 int timer;
17031 int timeridx;
17032
17033 ast_copy_string(tmp, v->value, sizeof(tmp));
17034 c = tmp;
17035 timerc = strsep(&c, ",");
17036 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
17037 timeridx = pri_timer2idx(timerc);
17038 timer = atoi(c);
17039 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
17040 ast_log(LOG_WARNING,
17041 "'%s' is not a valid ISDN timer at line %d.\n", timerc,
17042 v->lineno);
17043 } else if (!timer) {
17044 ast_log(LOG_WARNING,
17045 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
17046 c, timerc, v->lineno);
17047 } else {
17048 confp->pri.pri.pritimers[timeridx] = timer;
17049 }
17050 } else {
17051 ast_log(LOG_WARNING,
17052 "'%s' is not a valid ISDN timer configuration string at line %d.\n",
17053 v->value, v->lineno);
17054 }
17055 #endif
17056 } else if (!strcasecmp(v->name, "facilityenable")) {
17057 confp->pri.pri.facilityenable = ast_true(v->value);
17058 #if defined(HAVE_PRI_AOC_EVENTS)
17059 } else if (!strcasecmp(v->name, "aoc_enable")) {
17060 confp->pri.pri.aoc_passthrough_flag = 0;
17061 if (strchr(v->value, 's') || strchr(v->value, 'S')) {
17062 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_S;
17063 }
17064 if (strchr(v->value, 'd') || strchr(v->value, 'D')) {
17065 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_D;
17066 }
17067 if (strchr(v->value, 'e') || strchr(v->value, 'E')) {
17068 confp->pri.pri.aoc_passthrough_flag |= SIG_PRI_AOC_GRANT_E;
17069 }
17070 } else if (!strcasecmp(v->name, "aoce_delayhangup")) {
17071 confp->pri.pri.aoce_delayhangup = ast_true(v->value);
17072 #endif
17073 #if defined(HAVE_PRI_CALL_HOLD)
17074 } else if (!strcasecmp(v->name, "hold_disconnect_transfer")) {
17075 confp->pri.pri.hold_disconnect_transfer = ast_true(v->value);
17076 #endif
17077 #if defined(HAVE_PRI_CCSS)
17078 } else if (!strcasecmp(v->name, "cc_ptmp_recall_mode")) {
17079 if (!strcasecmp(v->value, "global")) {
17080 confp->pri.pri.cc_ptmp_recall_mode = 0;
17081 } else if (!strcasecmp(v->value, "specific")) {
17082 confp->pri.pri.cc_ptmp_recall_mode = 1;
17083 } else {
17084 confp->pri.pri.cc_ptmp_recall_mode = 1;
17085 }
17086 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_req")) {
17087 if (!strcasecmp(v->value, "release")) {
17088 confp->pri.pri.cc_qsig_signaling_link_req = 0;
17089 } else if (!strcasecmp(v->value, "retain")) {
17090 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17091 } else if (!strcasecmp(v->value, "do_not_care")) {
17092 confp->pri.pri.cc_qsig_signaling_link_req = 2;
17093 } else {
17094 confp->pri.pri.cc_qsig_signaling_link_req = 1;
17095 }
17096 } else if (!strcasecmp(v->name, "cc_qsig_signaling_link_rsp")) {
17097 if (!strcasecmp(v->value, "release")) {
17098 confp->pri.pri.cc_qsig_signaling_link_rsp = 0;
17099 } else if (!strcasecmp(v->value, "retain")) {
17100 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17101 } else {
17102 confp->pri.pri.cc_qsig_signaling_link_rsp = 1;
17103 }
17104 #endif
17105 #if defined(HAVE_PRI_CALL_WAITING)
17106 } else if (!strcasecmp(v->name, "max_call_waiting_calls")) {
17107 confp->pri.pri.max_call_waiting_calls = atoi(v->value);
17108 if (confp->pri.pri.max_call_waiting_calls < 0) {
17109
17110 confp->pri.pri.max_call_waiting_calls = 0;
17111 }
17112 } else if (!strcasecmp(v->name, "allow_call_waiting_calls")) {
17113 confp->pri.pri.allow_call_waiting_calls = ast_true(v->value);
17114 #endif
17115 #if defined(HAVE_PRI_MWI)
17116 } else if (!strcasecmp(v->name, "mwi_mailboxes")) {
17117 ast_copy_string(confp->pri.pri.mwi_mailboxes, v->value,
17118 sizeof(confp->pri.pri.mwi_mailboxes));
17119 #endif
17120 } else if (!strcasecmp(v->name, "append_msn_to_cid_tag")) {
17121 confp->pri.pri.append_msn_to_user_tag = ast_true(v->value);
17122 #endif
17123 #if defined(HAVE_SS7)
17124 } else if (!strcasecmp(v->name, "ss7type")) {
17125 if (!strcasecmp(v->value, "itu")) {
17126 cur_ss7type = SS7_ITU;
17127 } else if (!strcasecmp(v->value, "ansi")) {
17128 cur_ss7type = SS7_ANSI;
17129 } else
17130 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
17131 } else if (!strcasecmp(v->name, "linkset")) {
17132 cur_linkset = atoi(v->value);
17133 } else if (!strcasecmp(v->name, "pointcode")) {
17134 cur_pointcode = parse_pointcode(v->value);
17135 } else if (!strcasecmp(v->name, "adjpointcode")) {
17136 cur_adjpointcode = parse_pointcode(v->value);
17137 } else if (!strcasecmp(v->name, "defaultdpc")) {
17138 cur_defaultdpc = parse_pointcode(v->value);
17139 } else if (!strcasecmp(v->name, "cicbeginswith")) {
17140 cur_cicbeginswith = atoi(v->value);
17141 } else if (!strcasecmp(v->name, "networkindicator")) {
17142 if (!strcasecmp(v->value, "national"))
17143 cur_networkindicator = SS7_NI_NAT;
17144 else if (!strcasecmp(v->value, "national_spare"))
17145 cur_networkindicator = SS7_NI_NAT_SPARE;
17146 else if (!strcasecmp(v->value, "international"))
17147 cur_networkindicator = SS7_NI_INT;
17148 else if (!strcasecmp(v->value, "international_spare"))
17149 cur_networkindicator = SS7_NI_INT_SPARE;
17150 else
17151 cur_networkindicator = -1;
17152 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
17153 ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
17154 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
17155 ast_copy_string(confp->ss7.ss7.nationalprefix, v->value, sizeof(confp->ss7.ss7.nationalprefix));
17156 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
17157 ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
17158 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
17159 ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
17160 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
17161 if (!strcasecmp(v->value, "national")) {
17162 confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
17163 } else if (!strcasecmp(v->value, "international")) {
17164 confp->ss7.ss7.called_nai = SS7_NAI_INTERNATIONAL;
17165 } else if (!strcasecmp(v->value, "subscriber")) {
17166 confp->ss7.ss7.called_nai = SS7_NAI_SUBSCRIBER;
17167 } else if (!strcasecmp(v->value, "unknown")) {
17168 confp->ss7.ss7.called_nai = SS7_NAI_UNKNOWN;
17169 } else if (!strcasecmp(v->value, "dynamic")) {
17170 confp->ss7.ss7.called_nai = SS7_NAI_DYNAMIC;
17171 } else {
17172 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
17173 }
17174 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
17175 if (!strcasecmp(v->value, "national")) {
17176 confp->ss7.ss7.calling_nai = SS7_NAI_NATIONAL;
17177 } else if (!strcasecmp(v->value, "international")) {
17178 confp->ss7.ss7.calling_nai = SS7_NAI_INTERNATIONAL;
17179 } else if (!strcasecmp(v->value, "subscriber")) {
17180 confp->ss7.ss7.calling_nai = SS7_NAI_SUBSCRIBER;
17181 } else if (!strcasecmp(v->value, "unknown")) {
17182 confp->ss7.ss7.calling_nai = SS7_NAI_UNKNOWN;
17183 } else if (!strcasecmp(v->value, "dynamic")) {
17184 confp->ss7.ss7.calling_nai = SS7_NAI_DYNAMIC;
17185 } else {
17186 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
17187 }
17188 } else if (!strcasecmp(v->name, "sigchan")) {
17189 int sigchan, res;
17190 sigchan = atoi(v->value);
17191 res = linkset_addsigchan(sigchan);
17192 if (res < 0)
17193 return -1;
17194
17195 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
17196 struct dahdi_ss7 *link;
17197 link = ss7_resolve_linkset(cur_linkset);
17198 if (!link) {
17199 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
17200 return -1;
17201 }
17202 if (ast_true(v->value))
17203 link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
17204 #endif
17205 #ifdef HAVE_OPENR2
17206 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
17207 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
17208 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);
17209 } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
17210 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
17211 } else if (!strcasecmp(v->name, "mfcr2_variant")) {
17212 confp->mfcr2.variant = openr2_proto_get_variant(v->value);
17213 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
17214 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
17215 confp->mfcr2.variant = OR2_VAR_ITU;
17216 }
17217 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
17218 confp->mfcr2.mfback_timeout = atoi(v->value);
17219 if (!confp->mfcr2.mfback_timeout) {
17220 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
17221 confp->mfcr2.mfback_timeout = -1;
17222 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
17223 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
17224 }
17225 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
17226 confp->mfcr2.metering_pulse_timeout = atoi(v->value);
17227 if (confp->mfcr2.metering_pulse_timeout > 500) {
17228 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
17229 }
17230 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
17231 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
17232 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
17233 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
17234 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
17235 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
17236 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
17237 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
17238 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
17239 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
17240 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
17241 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
17242 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
17243 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
17244 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
17245 } else if (!strcasecmp(v->name, "mfcr2_skip_category")) {
17246 confp->mfcr2.skip_category_request = ast_true(v->value) ? 1 : 0;
17247 #endif
17248 } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
17249 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
17250 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
17251 confp->mfcr2.max_ani = atoi(v->value);
17252 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
17253 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
17254 }
17255 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
17256 confp->mfcr2.max_dnis = atoi(v->value);
17257 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
17258 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
17259 }
17260 } else if (!strcasecmp(v->name, "mfcr2_category")) {
17261 confp->mfcr2.category = openr2_proto_get_category(v->value);
17262 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
17263 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
17264 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
17265 v->value, v->lineno);
17266 }
17267 } else if (!strcasecmp(v->name, "mfcr2_logging")) {
17268 openr2_log_level_t tmplevel;
17269 char *clevel;
17270 char *logval = ast_strdupa(v->value);
17271 while (logval) {
17272 clevel = strsep(&logval,",");
17273 if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
17274 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
17275 continue;
17276 }
17277 confp->mfcr2.loglevel |= tmplevel;
17278 }
17279 #endif
17280 } else if (!strcasecmp(v->name, "cadence")) {
17281
17282 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
17283 int i;
17284 struct dahdi_ring_cadence new_cadence;
17285 int cid_location = -1;
17286 int firstcadencepos = 0;
17287 char original_args[80];
17288 int cadence_is_ok = 1;
17289
17290 ast_copy_string(original_args, v->value, sizeof(original_args));
17291
17292 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]);
17293
17294
17295 if (element_count % 2 == 1) {
17296 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
17297 cadence_is_ok = 0;
17298 }
17299
17300
17301 for (i = 0; i < element_count; i++) {
17302 if (c[i] == 0) {
17303 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
17304 cadence_is_ok = 0;
17305 break;
17306 } else if (c[i] < 0) {
17307 if (i % 2 == 1) {
17308
17309 if (cid_location == -1) {
17310 cid_location = i;
17311 c[i] *= -1;
17312 } else {
17313 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
17314 cadence_is_ok = 0;
17315 break;
17316 }
17317 } else {
17318 if (firstcadencepos == 0) {
17319 firstcadencepos = i;
17320
17321 } else {
17322 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
17323 cadence_is_ok = 0;
17324 break;
17325 }
17326 }
17327 }
17328 }
17329
17330
17331 for (i = 0; i < 16; i++) {
17332 new_cadence.ringcadence[i] = c[i];
17333 }
17334
17335 if (cadence_is_ok) {
17336
17337 if (element_count < 2) {
17338 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
17339 } else {
17340 if (cid_location == -1) {
17341
17342 cid_location = 1;
17343 } else {
17344
17345 cid_location = (cid_location + 1) / 2;
17346 }
17347
17348 if (!user_has_defined_cadences++)
17349
17350 num_cadence = 0;
17351 if ((num_cadence+1) >= NUM_CADENCE_MAX)
17352 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
17353 else {
17354 cadences[num_cadence] = new_cadence;
17355 cidrings[num_cadence++] = cid_location;
17356 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
17357 }
17358 }
17359 }
17360 } else if (!strcasecmp(v->name, "ringtimeout")) {
17361 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17362 } else if (!strcasecmp(v->name, "prewink")) {
17363 confp->timing.prewinktime = atoi(v->value);
17364 } else if (!strcasecmp(v->name, "preflash")) {
17365 confp->timing.preflashtime = atoi(v->value);
17366 } else if (!strcasecmp(v->name, "wink")) {
17367 confp->timing.winktime = atoi(v->value);
17368 } else if (!strcasecmp(v->name, "flash")) {
17369 confp->timing.flashtime = atoi(v->value);
17370 } else if (!strcasecmp(v->name, "start")) {
17371 confp->timing.starttime = atoi(v->value);
17372 } else if (!strcasecmp(v->name, "rxwink")) {
17373 confp->timing.rxwinktime = atoi(v->value);
17374 } else if (!strcasecmp(v->name, "rxflash")) {
17375 confp->timing.rxflashtime = atoi(v->value);
17376 } else if (!strcasecmp(v->name, "debounce")) {
17377 confp->timing.debouncetime = atoi(v->value);
17378 } else if (!strcasecmp(v->name, "toneduration")) {
17379 int toneduration;
17380 int ctlfd;
17381 int res;
17382 struct dahdi_dialparams dps;
17383
17384 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17385 if (ctlfd == -1) {
17386 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17387 return -1;
17388 }
17389
17390 toneduration = atoi(v->value);
17391 if (toneduration > -1) {
17392 memset(&dps, 0, sizeof(dps));
17393
17394 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17395 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17396 if (res < 0) {
17397 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17398 close(ctlfd);
17399 return -1;
17400 }
17401 }
17402 close(ctlfd);
17403 } else if (!strcasecmp(v->name, "defaultcic")) {
17404 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17405 } else if (!strcasecmp(v->name, "defaultozz")) {
17406 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17407 } else if (!strcasecmp(v->name, "mwilevel")) {
17408 mwilevel = atoi(v->value);
17409 } else if (!strcasecmp(v->name, "dtmfcidlevel")) {
17410 dtmfcid_level = atoi(v->value);
17411 } else if (!strcasecmp(v->name, "reportalarms")) {
17412 if (!strcasecmp(v->value, "all"))
17413 report_alarms = REPORT_CHANNEL_ALARMS | REPORT_SPAN_ALARMS;
17414 if (!strcasecmp(v->value, "none"))
17415 report_alarms = 0;
17416 else if (!strcasecmp(v->value, "channels"))
17417 report_alarms = REPORT_CHANNEL_ALARMS;
17418 else if (!strcasecmp(v->value, "spans"))
17419 report_alarms = REPORT_SPAN_ALARMS;
17420 }
17421 } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17422 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17423 }
17424 if (dahdichan[0]) {
17425
17426
17427 if (build_channels(confp, dahdichan, reload, 0, &found_pseudo)) {
17428 return -1;
17429 }
17430 }
17431
17432
17433 for (tmp = iflist, y=-1; tmp; tmp = tmp->next) {
17434 if (!tmp->destroy && tmp->span != y) {
17435 tmp->manages_span_alarms = 1;
17436 y = tmp->span;
17437 } else {
17438 tmp->manages_span_alarms = 0;
17439 }
17440 }
17441
17442
17443
17444 if (!found_pseudo && reload != 1) {
17445
17446
17447
17448
17449 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17450
17451 if (conf.chan.cc_params) {
17452 tmp = mkintf(CHAN_PSEUDO, &conf, reload);
17453 } else {
17454 tmp = NULL;
17455 }
17456 if (tmp) {
17457 ast_verb(3, "Automatically generated pseudo channel\n");
17458 } else {
17459 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17460 }
17461 ast_cc_config_params_destroy(conf.chan.cc_params);
17462 }
17463 return 0;
17464 }
17465
17466
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476 static void deep_copy_dahdi_chan_conf(struct dahdi_chan_conf *dest, const struct dahdi_chan_conf *src)
17477 {
17478 struct ast_cc_config_params *cc_params;
17479
17480 cc_params = dest->chan.cc_params;
17481 *dest = *src;
17482 dest->chan.cc_params = cc_params;
17483 ast_cc_copy_config_params(dest->chan.cc_params, src->chan.cc_params);
17484 }
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496
17497 static int setup_dahdi_int(int reload, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf)
17498 {
17499 struct ast_config *cfg;
17500 struct ast_config *ucfg;
17501 struct ast_variable *v;
17502 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17503 const char *cat;
17504 int res;
17505
17506 #ifdef HAVE_PRI
17507 char *c;
17508 int spanno;
17509 int i;
17510 int logicalspan;
17511 int trunkgroup;
17512 int dchannels[SIG_PRI_NUM_DCHANS];
17513 #endif
17514
17515 cfg = ast_config_load(config, config_flags);
17516
17517
17518 if (!cfg) {
17519 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17520 return 0;
17521 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17522 ucfg = ast_config_load("users.conf", config_flags);
17523 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17524 return 0;
17525 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17526 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17527 return 0;
17528 }
17529 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17530 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17531 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17532 ast_config_destroy(ucfg);
17533 return 0;
17534 }
17535 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17536 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config);
17537 return 0;
17538 } else {
17539 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17540 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17541 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n");
17542 ast_config_destroy(cfg);
17543 return 0;
17544 }
17545 }
17546
17547
17548 ast_mutex_lock(&iflock);
17549 #ifdef HAVE_PRI
17550 if (reload != 1) {
17551
17552 v = ast_variable_browse(cfg, "trunkgroups");
17553 while (v) {
17554 if (!strcasecmp(v->name, "trunkgroup")) {
17555 trunkgroup = atoi(v->value);
17556 if (trunkgroup > 0) {
17557 if ((c = strchr(v->value, ','))) {
17558 i = 0;
17559 memset(dchannels, 0, sizeof(dchannels));
17560 while (c && (i < SIG_PRI_NUM_DCHANS)) {
17561 dchannels[i] = atoi(c + 1);
17562 if (dchannels[i] < 0) {
17563 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);
17564 } else
17565 i++;
17566 c = strchr(c + 1, ',');
17567 }
17568 if (i) {
17569 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17570 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);
17571 } else
17572 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");
17573 } else
17574 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17575 } else
17576 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17577 } else
17578 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17579 } else if (!strcasecmp(v->name, "spanmap")) {
17580 spanno = atoi(v->value);
17581 if (spanno > 0) {
17582 if ((c = strchr(v->value, ','))) {
17583 trunkgroup = atoi(c + 1);
17584 if (trunkgroup > 0) {
17585 if ((c = strchr(c + 1, ',')))
17586 logicalspan = atoi(c + 1);
17587 else
17588 logicalspan = 0;
17589 if (logicalspan >= 0) {
17590 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17591 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17592 } else
17593 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17594 } else
17595 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);
17596 } else
17597 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17598 } else
17599 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17600 } else
17601 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17602 } else {
17603 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17604 }
17605 v = v->next;
17606 }
17607 }
17608 #endif
17609
17610
17611 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17612
17613 mwimonitornotify[0] = '\0';
17614
17615 v = ast_variable_browse(cfg, "channels");
17616 if ((res = process_dahdi(base_conf, "", v, reload, 0))) {
17617 ast_mutex_unlock(&iflock);
17618 ast_config_destroy(cfg);
17619 if (ucfg) {
17620 ast_config_destroy(ucfg);
17621 }
17622 return res;
17623 }
17624
17625
17626 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17627
17628
17629
17630 if (!strcasecmp(cat, "general") ||
17631 !strcasecmp(cat, "trunkgroups") ||
17632 !strcasecmp(cat, "globals") ||
17633 !strcasecmp(cat, "channels")) {
17634 continue;
17635 }
17636
17637
17638 deep_copy_dahdi_chan_conf(conf, base_conf);
17639
17640 if ((res = process_dahdi(conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17641 ast_mutex_unlock(&iflock);
17642 ast_config_destroy(cfg);
17643 if (ucfg) {
17644 ast_config_destroy(ucfg);
17645 }
17646 return res;
17647 }
17648 }
17649
17650 ast_config_destroy(cfg);
17651
17652 if (ucfg) {
17653 const char *chans;
17654
17655 process_dahdi(base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17656
17657 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17658 if (!strcasecmp(cat, "general")) {
17659 continue;
17660 }
17661
17662 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17663
17664 if (ast_strlen_zero(chans)) {
17665 continue;
17666 }
17667
17668
17669 deep_copy_dahdi_chan_conf(conf, base_conf);
17670
17671 if ((res = process_dahdi(conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17672 ast_config_destroy(ucfg);
17673 ast_mutex_unlock(&iflock);
17674 return res;
17675 }
17676 }
17677 ast_config_destroy(ucfg);
17678 }
17679 ast_mutex_unlock(&iflock);
17680
17681 #ifdef HAVE_PRI
17682 if (reload != 1) {
17683 int x;
17684 for (x = 0; x < NUM_SPANS; x++) {
17685 if (pris[x].pri.pvts[0]) {
17686 prepare_pri(pris + x);
17687 if (sig_pri_start_pri(&pris[x].pri)) {
17688 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17689 return -1;
17690 } else
17691 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17692 }
17693 }
17694 }
17695 #endif
17696 #if defined(HAVE_SS7)
17697 if (reload != 1) {
17698 int x;
17699 for (x = 0; x < NUM_SPANS; x++) {
17700 if (linksets[x].ss7.ss7) {
17701 linksets[x].ss7.calls = &dahdi_ss7_callbacks;
17702 if (ast_pthread_create(&linksets[x].ss7.master, NULL, ss7_linkset, &linksets[x].ss7)) {
17703 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17704 return -1;
17705 } else
17706 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17707 }
17708 }
17709 }
17710 #endif
17711 #ifdef HAVE_OPENR2
17712 if (reload != 1) {
17713 int x;
17714 for (x = 0; x < r2links_count; x++) {
17715 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17716 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17717 return -1;
17718 } else {
17719 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17720 }
17721 }
17722 }
17723 #endif
17724
17725 restart_monitor();
17726 return 0;
17727 }
17728
17729
17730
17731
17732
17733
17734
17735
17736
17737
17738 static int setup_dahdi(int reload)
17739 {
17740 int res;
17741 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17742 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17743
17744 if (base_conf.chan.cc_params && conf.chan.cc_params) {
17745 res = setup_dahdi_int(reload, &base_conf, &conf);
17746 } else {
17747 res = -1;
17748 }
17749 ast_cc_config_params_destroy(base_conf.chan.cc_params);
17750 ast_cc_config_params_destroy(conf.chan.cc_params);
17751
17752 return res;
17753 }
17754
17755
17756
17757
17758
17759
17760
17761
17762 static int dahdi_status_data_provider_get(const struct ast_data_search *search,
17763 struct ast_data *data_root)
17764 {
17765 int ctl, res, span;
17766 struct ast_data *data_span, *data_alarms;
17767 struct dahdi_spaninfo s;
17768
17769 ctl = open("/dev/dahdi/ctl", O_RDWR);
17770 if (ctl < 0) {
17771 ast_log(LOG_ERROR, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
17772 return -1;
17773 }
17774 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
17775 s.spanno = span;
17776 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
17777 if (res) {
17778 continue;
17779 }
17780
17781 data_span = ast_data_add_node(data_root, "span");
17782 if (!data_span) {
17783 continue;
17784 }
17785 ast_data_add_str(data_span, "description", s.desc);
17786
17787
17788 data_alarms = ast_data_add_node(data_span, "alarms");
17789 if (!data_alarms) {
17790 continue;
17791 }
17792
17793 ast_data_add_bool(data_alarms, "BLUE", s.alarms & DAHDI_ALARM_BLUE);
17794 ast_data_add_bool(data_alarms, "YELLOW", s.alarms & DAHDI_ALARM_YELLOW);
17795 ast_data_add_bool(data_alarms, "RED", s.alarms & DAHDI_ALARM_RED);
17796 ast_data_add_bool(data_alarms, "LOOPBACK", s.alarms & DAHDI_ALARM_LOOPBACK);
17797 ast_data_add_bool(data_alarms, "RECOVER", s.alarms & DAHDI_ALARM_RECOVER);
17798 ast_data_add_bool(data_alarms, "NOTOPEN", s.alarms & DAHDI_ALARM_NOTOPEN);
17799
17800 ast_data_add_int(data_span, "irqmisses", s.irqmisses);
17801 ast_data_add_int(data_span, "bpviol", s.bpvcount);
17802 ast_data_add_int(data_span, "crc4", s.crc4count);
17803 ast_data_add_str(data_span, "framing", s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
17804 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
17805 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
17806 "CAS");
17807 ast_data_add_str(data_span, "coding", s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
17808 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
17809 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
17810 "Unknown");
17811 ast_data_add_str(data_span, "options", s.lineconfig & DAHDI_CONFIG_CRC4 ?
17812 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" :
17813 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "YEL" : "");
17814 ast_data_add_str(data_span, "lbo", lbostr[s.lbo]);
17815
17816
17817 if (!ast_data_search_match(search, data_span)) {
17818 ast_data_remove_node(data_root, data_span);
17819 }
17820 }
17821 close(ctl);
17822
17823 return 0;
17824 }
17825
17826
17827
17828
17829
17830
17831
17832
17833 static int dahdi_channels_data_provider_get(const struct ast_data_search *search,
17834 struct ast_data *data_root)
17835 {
17836 struct dahdi_pvt *tmp;
17837 struct ast_data *data_channel;
17838
17839 ast_mutex_lock(&iflock);
17840 for (tmp = iflist; tmp; tmp = tmp->next) {
17841 data_channel = ast_data_add_node(data_root, "channel");
17842 if (!data_channel) {
17843 continue;
17844 }
17845
17846 ast_data_add_structure(dahdi_pvt, data_channel, tmp);
17847
17848
17849 if (!ast_data_search_match(search, data_channel)) {
17850 ast_data_remove_node(data_root, data_channel);
17851 }
17852 }
17853 ast_mutex_unlock(&iflock);
17854
17855 return 0;
17856 }
17857
17858
17859
17860
17861
17862
17863
17864
17865 static int dahdi_version_data_provider_get(const struct ast_data_search *search,
17866 struct ast_data *data_root)
17867 {
17868 int pseudo_fd = -1;
17869 struct dahdi_versioninfo vi = {
17870 .version = "Unknown",
17871 .echo_canceller = "Unknown"
17872 };
17873
17874 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
17875 ast_log(LOG_ERROR, "Failed to open control file to get version.\n");
17876 return -1;
17877 }
17878
17879 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) {
17880 ast_log(LOG_ERROR, "Failed to get DAHDI version: %s\n", strerror(errno));
17881 }
17882
17883 close(pseudo_fd);
17884
17885 ast_data_add_str(data_root, "value", vi.version);
17886 ast_data_add_str(data_root, "echocanceller", vi.echo_canceller);
17887
17888 return 0;
17889 }
17890
17891 static const struct ast_data_handler dahdi_status_data_provider = {
17892 .version = AST_DATA_HANDLER_VERSION,
17893 .get = dahdi_status_data_provider_get
17894 };
17895
17896 static const struct ast_data_handler dahdi_channels_data_provider = {
17897 .version = AST_DATA_HANDLER_VERSION,
17898 .get = dahdi_channels_data_provider_get
17899 };
17900
17901 static const struct ast_data_handler dahdi_version_data_provider = {
17902 .version = AST_DATA_HANDLER_VERSION,
17903 .get = dahdi_version_data_provider_get
17904 };
17905
17906 static const struct ast_data_entry dahdi_data_providers[] = {
17907 AST_DATA_ENTRY("asterisk/channel/dahdi/status", &dahdi_status_data_provider),
17908 AST_DATA_ENTRY("asterisk/channel/dahdi/channels", &dahdi_channels_data_provider),
17909 AST_DATA_ENTRY("asterisk/channel/dahdi/version", &dahdi_version_data_provider)
17910 };
17911
17912 static int load_module(void)
17913 {
17914 int res;
17915 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17916 int y;
17917 #endif
17918
17919 #ifdef HAVE_PRI
17920 memset(pris, 0, sizeof(pris));
17921 for (y = 0; y < NUM_SPANS; y++) {
17922 sig_pri_init_pri(&pris[y].pri);
17923 }
17924 pri_set_error(dahdi_pri_error);
17925 pri_set_message(dahdi_pri_message);
17926 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17927 #ifdef HAVE_PRI_PROG_W_CAUSE
17928 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17929 #endif
17930 #if defined(HAVE_PRI_CCSS)
17931 if (ast_cc_agent_register(&dahdi_pri_cc_agent_callbacks)
17932 || ast_cc_monitor_register(&dahdi_pri_cc_monitor_callbacks)) {
17933 __unload_module();
17934 return AST_MODULE_LOAD_FAILURE;
17935 }
17936 #endif
17937 if (sig_pri_load(
17938 #if defined(HAVE_PRI_CCSS)
17939 dahdi_pri_cc_type
17940 #else
17941 NULL
17942 #endif
17943 )) {
17944 __unload_module();
17945 return AST_MODULE_LOAD_FAILURE;
17946 }
17947 #endif
17948 #if defined(HAVE_SS7)
17949 memset(linksets, 0, sizeof(linksets));
17950 for (y = 0; y < NUM_SPANS; y++) {
17951 sig_ss7_init_linkset(&linksets[y].ss7);
17952 }
17953 ss7_set_error(dahdi_ss7_error);
17954 ss7_set_message(dahdi_ss7_message);
17955 #endif
17956 res = setup_dahdi(0);
17957
17958 if (res)
17959 return AST_MODULE_LOAD_DECLINE;
17960 if (ast_channel_register(&dahdi_tech)) {
17961 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17962 __unload_module();
17963 return AST_MODULE_LOAD_FAILURE;
17964 }
17965 #ifdef HAVE_PRI
17966 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17967 #endif
17968 #if defined(HAVE_SS7)
17969 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17970 #endif
17971 #ifdef HAVE_OPENR2
17972 ast_cli_register_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
17973 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17974 #endif
17975
17976 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17977
17978 ast_data_register_multiple(dahdi_data_providers, ARRAY_LEN(dahdi_data_providers));
17979 memset(round_robin, 0, sizeof(round_robin));
17980 ast_manager_register_xml("DAHDITransfer", 0, action_transfer);
17981 ast_manager_register_xml("DAHDIHangup", 0, action_transferhangup);
17982 ast_manager_register_xml("DAHDIDialOffhook", 0, action_dahdidialoffhook);
17983 ast_manager_register_xml("DAHDIDNDon", 0, action_dahdidndon);
17984 ast_manager_register_xml("DAHDIDNDoff", 0, action_dahdidndoff);
17985 ast_manager_register_xml("DAHDIShowChannels", 0, action_dahdishowchannels);
17986 ast_manager_register_xml("DAHDIRestart", 0, action_dahdirestart);
17987
17988 ast_cond_init(&ss_thread_complete, NULL);
17989
17990 return res;
17991 }
17992
17993 static int dahdi_sendtext(struct ast_channel *c, const char *text)
17994 {
17995 #define END_SILENCE_LEN 400
17996 #define HEADER_MS 50
17997 #define TRAILER_MS 5
17998 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17999 #define ASCII_BYTES_PER_CHAR 80
18000
18001 unsigned char *buf,*mybuf;
18002 struct dahdi_pvt *p = c->tech_pvt;
18003 struct pollfd fds[1];
18004 int size,res,fd,len,x;
18005 int bytes=0;
18006
18007 float cr = 1.0;
18008 float ci = 0.0;
18009 float scont = 0.0;
18010 int idx;
18011
18012 idx = dahdi_get_index(c, p, 0);
18013 if (idx < 0) {
18014 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
18015 return -1;
18016 }
18017 if (!text[0]) return(0);
18018 if ((!p->tdd) && (!p->mate)) return(0);
18019 if (p->mate)
18020 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
18021 else
18022 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
18023 if (!buf)
18024 return -1;
18025 mybuf = buf;
18026 if (p->mate) {
18027 int codec = AST_LAW(p);
18028 for (x = 0; x < HEADER_MS; x++) {
18029 PUT_CLID_MARKMS;
18030 }
18031
18032 for (x = 0; text[x]; x++) {
18033 PUT_CLID(text[x]);
18034 }
18035 for (x = 0; x < TRAILER_MS; x++) {
18036 PUT_CLID_MARKMS;
18037 }
18038 len = bytes;
18039 buf = mybuf;
18040 } else {
18041 len = tdd_generate(p->tdd, buf, text);
18042 if (len < 1) {
18043 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
18044 ast_free(mybuf);
18045 return -1;
18046 }
18047 }
18048 memset(buf + len, 0x7f, END_SILENCE_LEN);
18049 len += END_SILENCE_LEN;
18050 fd = p->subs[idx].dfd;
18051 while (len) {
18052 if (ast_check_hangup(c)) {
18053 ast_free(mybuf);
18054 return -1;
18055 }
18056 size = len;
18057 if (size > READ_SIZE)
18058 size = READ_SIZE;
18059 fds[0].fd = fd;
18060 fds[0].events = POLLOUT | POLLPRI;
18061 fds[0].revents = 0;
18062 res = poll(fds, 1, -1);
18063 if (!res) {
18064 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
18065 continue;
18066 }
18067
18068 if (fds[0].revents & POLLPRI) {
18069 ast_free(mybuf);
18070 return -1;
18071 }
18072 if (!(fds[0].revents & POLLOUT)) {
18073 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
18074 continue;
18075 }
18076 res = write(fd, buf, size);
18077 if (res != size) {
18078 if (res == -1) {
18079 ast_free(mybuf);
18080 return -1;
18081 }
18082 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
18083 break;
18084 }
18085 len -= size;
18086 buf += size;
18087 }
18088 ast_free(mybuf);
18089 return(0);
18090 }
18091
18092
18093 static int reload(void)
18094 {
18095 int res = 0;
18096
18097 res = setup_dahdi(1);
18098 if (res) {
18099 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
18100 return -1;
18101 }
18102 return 0;
18103 }
18104
18105
18106
18107
18108
18109 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, tdesc,
18110 .load = load_module,
18111 .unload = unload_module,
18112 .reload = reload,
18113 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
18114 .nonoptreq = "res_smdi",
18115 );